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: starknet GMP (INTERNAL REVIEW) #57

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open

Conversation

ctoyan
Copy link
Member

@ctoyan ctoyan commented Jan 10, 2025

No description provided.

Comment on lines 365 to 369
// while let Some(result) = futures.next().await {
// if !result {
// panic!("expected conversion to fail for malformed event");
// }
// }
Copy link
Member

Choose a reason for hiding this comment

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

old code?

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// while let Some(result) = futures.next().await {
// if !result {
// panic!("expected conversion to fail for malformed event");
// }
// }


let event: Option<(Felt, ContractCallEvent)> = match receipt_with_block_info.receipt {
TransactionReceipt::Invoke(tx) => {
// NOTE: There should be only one ContractCall event per gateway tx
Copy link
Member

Choose a reason for hiding this comment

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

What is meant by gateway tx? Because there can be many ContractCalls in a single tx

Copy link
Member

Choose a reason for hiding this comment

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

not sure about your question, but there would be more ContractCalls only in scenario where within single transaction frame we call multiple times Gateway::ContractCall, no? otherwise it should be one event per transaction.

Copy link
Member Author

Choose a reason for hiding this comment

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

Same question as Marcin. I believe we expect a single ContractCall per tx.

Is multicall what you're referring to and are you familiar with it's use case and if we should actually implement it?
I remember that Squid might need it, but I have no details on the matter.

Copy link
Member

Choose a reason for hiding this comment

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

but there would be more ContractCalls only in scenario where within single transaction frame we call multiple times Gateway::ContractCall

Exactly, and based on the //NOTE: comment I assume that this is not covered 😄

Multicall is one example.
Another example would be ITS, which allows to call arbitrary contracts upon token bridiging with a custom payload (all within the same tx), these contracts can be user-made contracts, or even the Multicall contract that calls the Gateway eg 3x times. What if I want to send 10 memo messages from starknet to EVM by only having to sign & send a single tx on Starknet 😄

summary: I don't think any of the implementations (evm, Solana, multiversx) assume that there would be only a single ContractCall event per on-chain tx, and I dont think you should assume that too.

///
/// # Type Parameters
/// * `C` - A Starknet client type that implements the [`StarknetClient`] trait
#[allow(dead_code)]
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
#[allow(dead_code)]

Copy link
Member

@puhtaytow puhtaytow left a comment

Choose a reason for hiding this comment

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

LGTM, left some comments


let event: Option<(Felt, ContractCallEvent)> = match receipt_with_block_info.receipt {
TransactionReceipt::Invoke(tx) => {
// NOTE: There should be only one ContractCall event per gateway tx
Copy link
Member

Choose a reason for hiding this comment

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

not sure about your question, but there would be more ContractCalls only in scenario where within single transaction frame we call multiple times Gateway::ContractCall, no? otherwise it should be one event per transaction.

use crate::handlers::starknet_verify_msg::Message;
use crate::handlers::starknet_verify_verifier_set::VerifierSetConfirmation;

/// Attempts to fetch the tx provided in `axl_msg.tx_id`.
Copy link
Member

Choose a reason for hiding this comment

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

I would add full Docs body

}
}

pub fn verify_verifier_set(
Copy link
Member

Choose a reason for hiding this comment

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

I would add full Docs body here as well

Comment on lines 8 to 43
/// Error returned when a required signers hash is missing from a
/// transaction.
#[error("missing signers hash for transaction")]
MissingSignersHash,

/// Error returned when payload data cannot be parsed correctly.
#[error("failed to parse payload data, error: {0}")]
FailedToParsePayloadData(String),

/// Error returned when the payload data is missing.
#[error("missing payload data for transaction")]
MissingPayloadData,

/// Error returned when the epoch number in a transaction is invalid or
/// unexpected.
#[error("incorrect epoch for transaction")]
IncorrectEpoch,

/// Error returned when the first key doesn't correspod to the
/// SignersRotated event.
#[error("not a SignersRotated event")]
InvalidEvent,

/// Error returned when the threshold in a transaction is invalid or
/// unexpected.
#[error("incorrect threshold for transaction")]
IncorrectThreshold,

/// Error returned when the nonce in a transaction is missing.
#[error("missing nonce for transaction")]
MissingNonce,

/// Error returned when the keys in a transaction are missing.
#[error("missing keys for transaction")]
MissingKeys,
}
Copy link
Member

Choose a reason for hiding this comment

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

the empty lines between arent needed

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// Error returned when a required signers hash is missing from a
/// transaction.
#[error("missing signers hash for transaction")]
MissingSignersHash,
/// Error returned when payload data cannot be parsed correctly.
#[error("failed to parse payload data, error: {0}")]
FailedToParsePayloadData(String),
/// Error returned when the payload data is missing.
#[error("missing payload data for transaction")]
MissingPayloadData,
/// Error returned when the epoch number in a transaction is invalid or
/// unexpected.
#[error("incorrect epoch for transaction")]
IncorrectEpoch,
/// Error returned when the first key doesn't correspod to the
/// SignersRotated event.
#[error("not a SignersRotated event")]
InvalidEvent,
/// Error returned when the threshold in a transaction is invalid or
/// unexpected.
#[error("incorrect threshold for transaction")]
IncorrectThreshold,
/// Error returned when the nonce in a transaction is missing.
#[error("missing nonce for transaction")]
MissingNonce,
/// Error returned when the keys in a transaction are missing.
#[error("missing keys for transaction")]
MissingKeys,
}
/// Error returned when a required signers hash is missing from a
/// transaction.
#[error("missing signers hash for transaction")]
MissingSignersHash,
/// Error returned when payload data cannot be parsed correctly.
#[error("failed to parse payload data, error: {0}")]
FailedToParsePayloadData(String),
/// Error returned when the payload data is missing.
#[error("missing payload data for transaction")]
MissingPayloadData,
/// Error returned when the epoch number in a transaction is invalid or
/// unexpected.
#[error("incorrect epoch for transaction")]
IncorrectEpoch,
/// Error returned when the first key doesn't correspod to the
/// SignersRotated event.
#[error("not a SignersRotated event")]
InvalidEvent,
/// Error returned when the threshold in a transaction is invalid or
/// unexpected.
#[error("incorrect threshold for transaction")]
IncorrectThreshold,
/// Error returned when the nonce in a transaction is missing.
#[error("missing nonce for transaction")]
MissingNonce,
/// Error returned when the keys in a transaction are missing.
#[error("missing keys for transaction")]
MissingKeys,
}


#[cfg(test)]
mod tests {
// use futures::stream::{FuturesUnordered, StreamExt};
Copy link
Member

Choose a reason for hiding this comment

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

could be removed

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// use futures::stream::{FuturesUnordered, StreamExt};

.map_err(|err| ContractCallError::TryFromConversion(err.to_string()))?
.into();

// It's + 3, because we need to offset the 0th element, pending_word and
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// It's + 3, because we need to offset the 0th element, pending_word and
// it's + 3, because we need to offset the 0th element, pending_word and

type Error = ArraySpanError;

fn try_from(data: Vec<Felt>) -> Result<Self, Self::Error> {
// First element is always the array length, which is a felt (so u8 is enough)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// First element is always the array length, which is a felt (so u8 is enough)
// first element is always the array length, which is a felt (so u8 is enough)


let result = StarknetMessage::from_token(starknet_msg_token);

// Tested like this, because InvalidOutputType doesn't implement PartialEq
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// Tested like this, because InvalidOutputType doesn't implement PartialEq
// tested like this, because InvalidOutputType doesn't implement PartialEq


let result = StarknetMessage::from_token(starknet_msg_token);

// Tested like this, because InvalidOutputType doesn't implement PartialEq
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// Tested like this, because InvalidOutputType doesn't implement PartialEq
// tested like this, because InvalidOutputType doesn't implement PartialEq


let result = StarknetMessage::from_token(starknet_msg_token);

// Tested like this, because InvalidOutputType doesn't implement PartialEq
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// Tested like this, because InvalidOutputType doesn't implement PartialEq
// tested like this, because InvalidOutputType doesn't implement PartialEq

Copy link
Member

@puhtaytow puhtaytow left a comment

Choose a reason for hiding this comment

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

LGTM2 left suggestions

Comment on lines 8 to 43
/// Error returned when a required signers hash is missing from a
/// transaction.
#[error("missing signers hash for transaction")]
MissingSignersHash,

/// Error returned when payload data cannot be parsed correctly.
#[error("failed to parse payload data, error: {0}")]
FailedToParsePayloadData(String),

/// Error returned when the payload data is missing.
#[error("missing payload data for transaction")]
MissingPayloadData,

/// Error returned when the epoch number in a transaction is invalid or
/// unexpected.
#[error("incorrect epoch for transaction")]
IncorrectEpoch,

/// Error returned when the first key doesn't correspod to the
/// SignersRotated event.
#[error("not a SignersRotated event")]
InvalidEvent,

/// Error returned when the threshold in a transaction is invalid or
/// unexpected.
#[error("incorrect threshold for transaction")]
IncorrectThreshold,

/// Error returned when the nonce in a transaction is missing.
#[error("missing nonce for transaction")]
MissingNonce,

/// Error returned when the keys in a transaction are missing.
#[error("missing keys for transaction")]
MissingKeys,
}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// Error returned when a required signers hash is missing from a
/// transaction.
#[error("missing signers hash for transaction")]
MissingSignersHash,
/// Error returned when payload data cannot be parsed correctly.
#[error("failed to parse payload data, error: {0}")]
FailedToParsePayloadData(String),
/// Error returned when the payload data is missing.
#[error("missing payload data for transaction")]
MissingPayloadData,
/// Error returned when the epoch number in a transaction is invalid or
/// unexpected.
#[error("incorrect epoch for transaction")]
IncorrectEpoch,
/// Error returned when the first key doesn't correspod to the
/// SignersRotated event.
#[error("not a SignersRotated event")]
InvalidEvent,
/// Error returned when the threshold in a transaction is invalid or
/// unexpected.
#[error("incorrect threshold for transaction")]
IncorrectThreshold,
/// Error returned when the nonce in a transaction is missing.
#[error("missing nonce for transaction")]
MissingNonce,
/// Error returned when the keys in a transaction are missing.
#[error("missing keys for transaction")]
MissingKeys,
}
/// Error returned when a required signers hash is missing from a
/// transaction.
#[error("missing signers hash for transaction")]
MissingSignersHash,
/// Error returned when payload data cannot be parsed correctly.
#[error("failed to parse payload data, error: {0}")]
FailedToParsePayloadData(String),
/// Error returned when the payload data is missing.
#[error("missing payload data for transaction")]
MissingPayloadData,
/// Error returned when the epoch number in a transaction is invalid or
/// unexpected.
#[error("incorrect epoch for transaction")]
IncorrectEpoch,
/// Error returned when the first key doesn't correspod to the
/// SignersRotated event.
#[error("not a SignersRotated event")]
InvalidEvent,
/// Error returned when the threshold in a transaction is invalid or
/// unexpected.
#[error("incorrect threshold for transaction")]
IncorrectThreshold,
/// Error returned when the nonce in a transaction is missing.
#[error("missing nonce for transaction")]
MissingNonce,
/// Error returned when the keys in a transaction are missing.
#[error("missing keys for transaction")]
MissingKeys,
}


#[tokio::test]
async fn test_try_from_event_randomly_malformed_data_x1000() {
// let mut futures = FuturesUnordered::new();
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// let mut futures = FuturesUnordered::new();

keys: event.keys,
});
assert!(result.is_err());
// });
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// });

//
// This field, should not exceed 252 bits (a felt's length)
let destination_chain = parse_cairo_short_string(&event.keys[1])?;

Copy link
Member

Choose a reason for hiding this comment

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

What about using &event.keys.get(1).expect("I expected this key") ?

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.

4 participants