Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add determinstic deposit hash & new exclusivity logic #759

Merged
merged 26 commits into from
Nov 25, 2024

Conversation

chrismaree
Copy link
Member

@chrismaree chrismaree commented Nov 22, 2024

This PR adds the logic defined in this PR: #756 to the solana implementation.

there is one gotcha and opinionated change that was needed to make this work: deposit_id is now a [u8;32] to accommodate this change. practically, this is not really a big deal for relayers or data worker but should be noted.

Signed-off-by: chrismaree <christopher.maree@gmail.com>
@chrismaree chrismaree changed the title feat: temp feat: add determinstic deposit hash & new exclusivity logic 2 Nov 22, 2024
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
@chrismaree chrismaree changed the title feat: add determinstic deposit hash & new exclusivity logic 2 feat: add determinstic deposit hash & new exclusivity logic Nov 22, 2024
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
@chrismaree chrismaree marked this pull request as ready for review November 22, 2024 08:01
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
state.number_of_deposits += 1; // Increment number of deposits
let mut applied_deposit_id = deposit_id;
// If the passed in deposit_id is all zeros, then we use the state's number of deposits as deposit_id.
if deposit_id.iter().all(|&x| x == 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: maybe more concise to do if deposit_id == ZERO_DEPOSIT_ID
where
const ZERO_DEPOSIT_ID: [u8; 32] = [0u8; 32];

output_amount,
destination_chain_id,
exclusive_relayer,
[0u8; 32], // deposit_id of informs internal function to use state.number_of_deposits as id.
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.

Nit: we could store this in constants as it's reused multiple times

// Define a dummy context struct so we can export this as a view function in lib.
#[derive(Accounts)]
pub struct Null {}
pub fn get_unsafe_deposit_id(msg_sender: Pubkey, depositor: Pubkey, deposit_nonce: u64) -> [u8; 32] {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you think it makes sense to expose this? Are we planning to use it off-chain, or should we implement a similar function in TS for efficiency?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes, I think having it exposed is useful. it's done in solidity and it's good to not force users to have to do this in js. for example say you wanted to do the deposit with etherscan for example. i don't think there is any downside in having it public. do you agree?

Comment on lines 119 to 124
if deposit_id.iter().all(|&x| x == 0) {
state.number_of_deposits += 1;
let mut deposit_id_bytes = [0u8; 32];
deposit_id_bytes[..4].copy_from_slice(&state.number_of_deposits.to_le_bytes());
applied_deposit_id = deposit_id_bytes;
}
Copy link
Contributor

@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.

Suggested change
if deposit_id.iter().all(|&x| x == 0) {
state.number_of_deposits += 1;
let mut deposit_id_bytes = [0u8; 32];
deposit_id_bytes[..4].copy_from_slice(&state.number_of_deposits.to_le_bytes());
applied_deposit_id = deposit_id_bytes;
}
if deposit_id == [0u8; 32] {
state.number_of_deposits += 1;
applied_deposit_id[..4].copy_from_slice(&state.number_of_deposits.to_le_bytes());
}

We can use simpler form of fixed array comparison and also we can avoid deposit_id_bytes variable by reusing applied_deposit_id that is known to be all zeros in this block

Copy link
Member Author

Choose a reason for hiding this comment

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

good call.

data.extend_from_slice(&depositor.to_bytes());
data.extend_from_slice(&deposit_nonce.to_le_bytes());

keccak::hash(&data).0
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
keccak::hash(&data).0
keccak::hash(&data).to_bytes()

Better not access internal elements

Comment on lines 258 to 260
data.extend_from_slice(&msg_sender.to_bytes());
data.extend_from_slice(&depositor.to_bytes());
data.extend_from_slice(&deposit_nonce.to_le_bytes());
Copy link
Contributor

@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.

we might better reuse anchor serializer (should have the same result):

AnchorSerialize::serialize(&(msg_sender, depositor, deposit_nonce), &mut data)?

this though requires converting this function to return Result

Or alternative use borch directly:

let data = (msg_sender, depositor, deposit_nonce).try_to_vec()?

Copy link
Contributor

Choose a reason for hiding this comment

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

note, I ended up using AnchorSerialize in this PR

Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Copy link
Contributor

@md0x md0x left a comment

Choose a reason for hiding this comment

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

Looks good!

Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
data.extend_from_slice(&depositor.to_bytes());
data.extend_from_slice(&deposit_nonce.to_le_bytes());
// Use AnchorSerialize to serialize the tuple of values
(msg_sender, depositor, deposit_nonce).serialize(&mut data).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

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

note that this is not AnchorSerialize wrapper (like mentioned in comment above), but using borch directly. Though, I guess functionally its the same in this case.

Copy link
Member Author

Choose a reason for hiding this comment

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

done.

Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
@chrismaree chrismaree merged commit 0bae98f into master Nov 25, 2024
9 checks passed
@chrismaree chrismaree deleted the chrismaree/solana-determinstic branch November 25, 2024 07:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants