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
23 changes: 7 additions & 16 deletions programs/svm-spoke/src/instructions/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ pub struct RelayerRefundLeaf {
}

impl RelayerRefundLeaf {
pub fn to_bytes(&self) -> Vec<u8> {
pub fn to_bytes(&self) -> Result<Vec<u8>> {
let mut bytes = Vec::new();

// This requires the first 64 bytes to be 0 within the encoded leaf data. This protects any kind of EVM leaf
Expand All @@ -88,23 +88,14 @@ impl RelayerRefundLeaf {
// in interpreted by SVM, to be zero always blocking this leaf type on EVM.
bytes.extend_from_slice(&[0u8; 64]);

bytes.extend_from_slice(&self.amount_to_return.to_le_bytes());
bytes.extend_from_slice(&self.chain_id.to_le_bytes());
for amount in &self.refund_amounts {
bytes.extend_from_slice(&amount.to_le_bytes());
}
bytes.extend_from_slice(&self.leaf_id.to_le_bytes());
bytes.extend_from_slice(self.mint_public_key.as_ref());
for address in &self.refund_addresses {
bytes.extend_from_slice(address.as_ref());
}
AnchorSerialize::serialize(&self, &mut bytes)?;
Copy link
Contributor

@md0x md0x Nov 22, 2024

Choose a reason for hiding this comment

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

Wow! Much better like this


bytes
Ok(bytes)
}

pub fn to_keccak_hash(&self) -> [u8; 32] {
let input = self.to_bytes();
keccak::hash(&input).0
pub fn to_keccak_hash(&self) -> Result<[u8; 32]> {
let input = self.to_bytes()?;
Ok(keccak::hash(&input).to_bytes())
}
}

Expand All @@ -124,7 +115,7 @@ where
let state = &ctx.accounts.state;

let root = ctx.accounts.root_bundle.relayer_refund_root;
let leaf = relayer_refund_leaf.to_keccak_hash();
let leaf = relayer_refund_leaf.to_keccak_hash()?;
verify_merkle_proof(root, leaf, proof)?;

if relayer_refund_leaf.chain_id != state.chain_id {
Expand Down
31 changes: 9 additions & 22 deletions programs/svm-spoke/src/instructions/slow_fill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,34 +94,21 @@ pub struct V3SlowFill {
}

impl V3SlowFill {
pub fn to_bytes(&self) -> Vec<u8> {
pub fn to_bytes(&self) -> Result<Vec<u8>> {
let mut bytes = Vec::new();

// This requires the first 64 bytes to be 0 within the encoded leaf data. This protects any kind of EVM leaf
// from ever being used on SVM (and vice versa). This covers the deposit and recipient fields.
bytes.extend_from_slice(&[0u8; 64]);
// Order should match the Solidity struct field order
bytes.extend_from_slice(&self.relay_data.depositor.to_bytes());
bytes.extend_from_slice(&self.relay_data.recipient.to_bytes());
bytes.extend_from_slice(&self.relay_data.exclusive_relayer.to_bytes());
bytes.extend_from_slice(&self.relay_data.input_token.to_bytes());
bytes.extend_from_slice(&self.relay_data.output_token.to_bytes());
bytes.extend_from_slice(&self.relay_data.input_amount.to_le_bytes());
bytes.extend_from_slice(&self.relay_data.output_amount.to_le_bytes());
bytes.extend_from_slice(&self.relay_data.origin_chain_id.to_le_bytes());
bytes.extend_from_slice(&self.relay_data.deposit_id.to_le_bytes());
bytes.extend_from_slice(&self.relay_data.fill_deadline.to_le_bytes());
bytes.extend_from_slice(&self.relay_data.exclusivity_deadline.to_le_bytes());
bytes.extend_from_slice(&self.relay_data.message);
bytes.extend_from_slice(&self.chain_id.to_le_bytes());
bytes.extend_from_slice(&self.updated_output_amount.to_le_bytes());

bytes

AnchorSerialize::serialize(&self, &mut bytes)?;

Ok(bytes)
}

pub fn to_keccak_hash(&self) -> [u8; 32] {
let input = self.to_bytes();
keccak::hash(&input).0
pub fn to_keccak_hash(&self) -> Result<[u8; 32]> {
let input = self.to_bytes()?;
Ok(keccak::hash(&input).to_bytes())
}
}

Expand Down Expand Up @@ -188,7 +175,7 @@ pub fn execute_v3_slow_relay_leaf<'info>(
};

let root = ctx.accounts.root_bundle.slow_relay_root;
let leaf = slow_fill.to_keccak_hash();
let leaf = slow_fill.to_keccak_hash()?;
verify_merkle_proof(root, leaf, proof)?;

// Check if the fill deadline has passed
Expand Down
8 changes: 5 additions & 3 deletions test/svm/SvmSpoke.SlowFill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
mintTo,
createApproveCheckedInstruction,
} from "@solana/spl-token";
import { PublicKey, Keypair, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
import { PublicKey, Keypair, Transaction, sendAndConfirmTransaction, ComputeBudgetProgram } from "@solana/web3.js";
import { common } from "./SvmSpoke.common";
import { MerkleTree } from "@uma/common/dist/MerkleTree";
import {
Expand Down Expand Up @@ -372,7 +372,7 @@ describe("svm_spoke.slow_fill", () => {
.rpc();

// Execute V3 slow relay leaf after requesting slow fill
await program.methods
const ix = await program.methods
.executeV3SlowRelayLeaf(
Array.from(relayHash),
{ ...leaf, relayData: formatRelayData(relayData) },
Expand All @@ -381,7 +381,9 @@ describe("svm_spoke.slow_fill", () => {
)
.accounts(executeSlowRelayLeafAccounts)
.remainingAccounts(fillRemainingAccounts)
.rpc();
.instruction();
const computeBudgetInstruction = ComputeBudgetProgram.setComputeUnitLimit({ units: 1_400_000 });
Copy link
Contributor

Choose a reason for hiding this comment

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

Has the borsh serialisation increased the CU?

Copy link
Contributor Author

@Reinis-FRP Reinis-FRP Nov 22, 2024

Choose a reason for hiding this comment

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

Its hard to tell precisely as our tests are not deterministic and have much more variance due to differing bumps in PDA derivation, but over 10 runs I observed on average +2% in CU, which I guess is acceptable here.

await sendAndConfirmTransaction(connection, new Transaction().add(computeBudgetInstruction, ix), [payer]);

// Verify the results
const fVaultBal = (await connection.getTokenAccountBalance(vault)).value.amount;
Expand Down
5 changes: 5 additions & 0 deletions test/svm/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,14 +164,17 @@ export function calculateRelayerRefundLeafHashUint8Array(relayData: RelayerRefun

const refundAddressesBuffer = Buffer.concat(relayData.refundAddresses.map((address) => address.toBuffer()));

// TODO: We better consider reusing Borch serializer in production.
Copy link
Contributor

Choose a reason for hiding this comment

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

+1 we should probably test this and make sure they produce the same byte layout

const contentToHash = Buffer.concat([
// SVM leaves require the first 64 bytes to be 0 to ensure EVM leaves can never be played on SVM and vice versa.
Buffer.alloc(64, 0),
relayData.amountToReturn.toArrayLike(Buffer, "le", 8),
relayData.chainId.toArrayLike(Buffer, "le", 8),
new BN(relayData.refundAmounts.length).toArrayLike(Buffer, "le", 4),
refundAmountsBuffer,
relayData.leafId.toArrayLike(Buffer, "le", 4),
relayData.mintPublicKey.toBuffer(),
new BN(relayData.refundAddresses.length).toArrayLike(Buffer, "le", 4),
refundAddressesBuffer,
]);

Expand Down Expand Up @@ -222,6 +225,7 @@ export interface SlowFillLeaf {
updatedOutputAmount: BN;
}

// TODO: We better consider reusing Borch serializer in production.
export function slowFillHashFn(slowFillLeaf: SlowFillLeaf): string {
const contentToHash = Buffer.concat([
// SVM leaves require the first 64 bytes to be 0 to ensure EVM leaves can never be played on SVM and vice versa.
Expand All @@ -237,6 +241,7 @@ export function slowFillHashFn(slowFillLeaf: SlowFillLeaf): string {
slowFillLeaf.relayData.depositId.toArrayLike(Buffer, "le", 4),
slowFillLeaf.relayData.fillDeadline.toArrayLike(Buffer, "le", 4),
slowFillLeaf.relayData.exclusivityDeadline.toArrayLike(Buffer, "le", 4),
new BN(slowFillLeaf.relayData.message.length).toArrayLike(Buffer, "le", 4),
slowFillLeaf.relayData.message,
slowFillLeaf.chainId.toArrayLike(Buffer, "le", 8),
slowFillLeaf.updatedOutputAmount.toArrayLike(Buffer, "le", 8),
Expand Down
Loading