Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,26 @@ repos:
language: "rust"
entry: cargo +nightly fmt --manifest-path ./pythnet/message_buffer/Cargo.toml --all -- --config-path rustfmt.toml
pass_filenames: false
files: message_buffer
files: pythnet/message_buffer
- id: cargo-clippy-message-buffer
name: Cargo clippy for message buffer contract
language: "rust"
entry: cargo +nightly clippy --manifest-path ./pythnet/message_buffer/Cargo.toml --tests --fix --allow-dirty --allow-staged --features test-bpf -- -D warnings
pass_filenames: false
files: message_buffer
files: pythnet/message_buffer
# Hooks for pythnet_sdk
- id: cargo-fmt-pythnet-sdk
name: Cargo format for pythnet SDK
language: "rust"
entry: cargo +nightly fmt --manifest-path ./pythnet/pythnet_sdk/Cargo.toml --all -- --config-path rustfmt.toml
pass_filenames: false
files: pythnet/pythnet_sdk
- id: cargo-clippy-pythnet-sdk
name: Cargo clippy for pythnet SDK
language: "rust"
entry: cargo +nightly clippy --manifest-path ./pythnet/pythnet_sdk/Cargo.toml --tests --fix --allow-dirty --allow-staged -- -D warnings
pass_filenames: false
files: pythnet/pythnet_sdk
# Hooks for solana receiver contract
- id: cargo-fmt-solana-receiver
name: Cargo format for solana target chain contract
Expand Down
6 changes: 4 additions & 2 deletions pythnet/pythnet_sdk/examples/generate_pyth_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ use {
solana_client::rpc_client::RpcClient,
solana_pyth::PYTH_PID,
solana_sdk::pubkey::Pubkey,
std::str::FromStr,
std::io::Write,
std::{
io::Write,
str::FromStr,
},
};

fn main() {
Expand Down
37 changes: 25 additions & 12 deletions pythnet/pythnet_sdk/src/accumulators/merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ impl<H: Hasher> MerklePath<H> {
pub fn new(path: Vec<H::Hash>) -> Self {
Self(path)
}

pub fn serialize(&self) -> Option<Vec<u8>> {
let mut serialized = vec![];
let proof_size: u8 = self.0.len().try_into().ok()?;
serialized.extend_from_slice(&proof_size.to_be_bytes());

for node in self.0.iter() {
serialized.extend_from_slice(node.as_ref());
}

Some(serialized)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why did this need to be added?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ali asked for this as he is serializing these in hermes by hand, this is also not the right place for this and I am hoping to replace the distributed hand-rolled serialization soon, but as the PR is modifying one serializer and Ali needed another it made sense to couple the change-set for now, I can remove this and leave the hand-rolling in hermes or do it in a separate PR if you prefer, but I'm planning to rip this out so I figured It's fine to place the current serialization in the same place until I move it all out.

}

/// A MerkleAccumulator maintains a Merkle Tree.
Expand Down Expand Up @@ -86,11 +98,12 @@ pub struct MerkleAccumulator<H: Hasher = Keccak256> {
// TODO: This code does not belong to MerkleAccumulator, we should be using the wire data types in
// calling code to wrap this value.
impl<'a, H: Hasher + 'a> MerkleAccumulator<H> {
pub fn serialize(&self, storage: u32) -> Vec<u8> {
pub fn serialize(&self, slot: u64, ring_size: u32) -> Vec<u8> {
let mut serialized = vec![];
serialized.extend_from_slice(0x41555756u32.to_be_bytes().as_ref());
serialized.extend_from_slice(0u8.to_be_bytes().as_ref());
serialized.extend_from_slice(storage.to_be_bytes().as_ref());
serialized.extend_from_slice(slot.to_be_bytes().as_ref());
serialized.extend_from_slice(ring_size.to_be_bytes().as_ref());
serialized.extend_from_slice(self.root.as_ref());
serialized
}
Expand Down Expand Up @@ -146,7 +159,7 @@ impl<H: Hasher> MerkleAccumulator<H> {
// Filling the leaf hashes
for i in 0..(1 << depth) {
if i < items.len() {
tree[(1 << depth) + i] = hash_leaf::<H>(items[i].as_ref());
tree[(1 << depth) + i] = hash_leaf::<H>(items[i]);
} else {
tree[(1 << depth) + i] = hash_null::<H>();
}
Expand All @@ -171,7 +184,7 @@ impl<H: Hasher> MerkleAccumulator<H> {
fn find_path(&self, mut index: usize) -> MerklePath<H> {
let mut path = Vec::new();
while index > 1 {
path.push(self.nodes[index ^ 1].clone());
path.push(self.nodes[index ^ 1]);
index /= 2;
}
MerklePath::new(path)
Expand Down Expand Up @@ -369,7 +382,7 @@ mod test {
// Accumulate into a 2 level tree.
let accumulator = MerkleAccumulator::<Keccak256>::from_set(set.into_iter()).unwrap();
let proof = accumulator.prove(&item_a).unwrap();
assert!(accumulator.check(proof.clone(), &item_a));
assert!(accumulator.check(proof, &item_a));

// We now have a 2 level tree with 4 nodes:
//
Expand Down Expand Up @@ -399,10 +412,10 @@ mod test {
let faulty_accumulator = MerkleAccumulator::<Keccak256> {
root: accumulator.root,
nodes: vec![
accumulator.nodes[0].clone(),
accumulator.nodes[1].clone(), // Root Stays the Same
accumulator.nodes[2].clone(), // Left node hash becomes a leaf.
accumulator.nodes[3].clone(), // Right node hash becomes a leaf.
accumulator.nodes[0],
accumulator.nodes[1], // Root Stays the Same
accumulator.nodes[2], // Left node hash becomes a leaf.
accumulator.nodes[3], // Right node hash becomes a leaf.
],
};

Expand All @@ -415,13 +428,13 @@ mod test {
.concat();

// Confirm our combined hash existed as a node pair in the original tree.
assert_eq!(hash_leaf::<Keccak256>(&fake_leaf_A), accumulator.nodes[2]);
assert_eq!(hash_leaf::<Keccak256>(fake_leaf_A), accumulator.nodes[2]);

// Now we can try and prove leaf membership in the faulty accumulator. NOTE: this should
// fail but to confirm that the test is actually correct you can remove the PREFIXES from
// the hash functions and this test will erroneously pass.
let proof = faulty_accumulator.prove(&fake_leaf_A).unwrap();
assert!(faulty_accumulator.check(proof, &fake_leaf_A));
let proof = faulty_accumulator.prove(fake_leaf_A).unwrap();
assert!(faulty_accumulator.check(proof, fake_leaf_A));
}

proptest! {
Expand Down