-
Notifications
You must be signed in to change notification settings - Fork 0
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 support for solana message id's #32
Conversation
* feat(minor-ampd): register public key takes in key type * tofnd client parse ed25519 * cargo sort
…rst tick (axelarnetwork#480) * fix: directly pass interval to queued broadcaster and pass the first unwanted tick * refactor: address PR comments * refactor: simplify steps to take after interval tick in run function
…work#478) * feat: check caller authorization status for multisig * refactor: rename query function name to caller_authorized
…twork#476) * feat(minor-voting-verifier): consistent gas cost for voting
Base58SolanaTxDigestAndEventIndex::new_from_b58_encoded_signature_and_index( | ||
id, index, | ||
) | ||
.unwrap() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like to unwrap, but functions signature does not allow returning errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same, but looks like the other implementations also use unwraps freely here.
@@ -137,6 +138,12 @@ fn parse_message_id( | |||
|
|||
Ok((id.tx_hash_as_hex(), id.event_index)) | |||
} | |||
MessageIdFormat::Base58SolanaTxDigestAndEventIndex => { | |||
let id = Base58SolanaTxDigestAndEventIndex::from_str(&message_id) | |||
.map_err(|_| ContractError::InvalidMessageID(message_id.into()))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder about providing more error info. But maybe it doesn't worth it, as we wouldn't get much more information anyways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, would be nice, but lets keep it as is, because it fits with the rest of the code.
} | ||
} | ||
|
||
pub fn new_from_b58_encoded_signature_and_index( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added this extra constructor for convenience, and for not spreading the decoding code everywhere.
} | ||
} | ||
|
||
fn decode_b58_signature(signature: &str) -> Result<RawSignature, Report<Error>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added this helper func for not repeating code.
|
||
use super::*; | ||
|
||
fn random_bytes() -> [u8; 64] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Increased this from [u8;32]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use the type alias that you defined at the top of the file RawSignature
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed at 3ce8e17
#[test] | ||
fn should_parse_msg_id() { | ||
let res = Base58SolanaTxDigestAndEventIndex::from_str( | ||
"4hHzKKdpXH2QMB5Jm11YR48cLqUJb9Cwq2YL3tveVTPeFkZaLP8cdcH5UphVPJ7kYwCUCRLnywd3xkUhb4ZYWtf5-0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adapted to a solana signature here
let event_index = random_event_index(); | ||
|
||
// too long | ||
let msg_id = format!("{}{}-{}", tx_digest, tx_digest, event_index); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically the test doubles the length here.
assert!(res.is_err()); | ||
|
||
// too short | ||
let msg_id = format!("{}-{}", &tx_digest[0..30], event_index); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we keep the same lower bound
)); | ||
assert!(res.is_err()); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think here, as in other places, another option would be to test the REGEX directly with something like rstest
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally speaking, I would opt for using proptest and do some property-based testing that generates the values for us. But let's not overcomplicate this PR. I'm just mentioning this as something cool that can be expanded upon.
let decoded = bs58::decode(&b58[trim..]).into_vec().unwrap(); | ||
assert_ne!(bytes.to_vec(), decoded); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this kind of tests are more "exploratory" ones of the b58
library. Tests that provide insights about a library expected behaviour. If i am right, i would not put them here, but in a dedicated integration test suite, so not related with any specific part of the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
overall lgtm, left some adjustments
Base58SolanaTxDigestAndEventIndex::new_from_b58_encoded_signature_and_index( | ||
id, index, | ||
) | ||
.unwrap() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same, but looks like the other implementations also use unwraps freely here.
@@ -137,6 +138,12 @@ fn parse_message_id( | |||
|
|||
Ok((id.tx_hash_as_hex(), id.event_index)) | |||
} | |||
MessageIdFormat::Base58SolanaTxDigestAndEventIndex => { | |||
let id = Base58SolanaTxDigestAndEventIndex::from_str(&message_id) | |||
.map_err(|_| ContractError::InvalidMessageID(message_id.into()))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, would be nice, but lets keep it as is, because it fits with the rest of the code.
packages/axelar-wasm-std/src/hash.rs
Outdated
@@ -1 +1 @@ | |||
pub type Hash = [u8; 32]; | |||
pub type Hash = [u8; 32]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like the newline character got deleted on this file, and this diff is unnecessary. You can probably git reset this file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed at 5e6e475
.map_err(|e: TryFromSliceError| { | ||
Error::InvalidTxDigest(format!( | ||
"Signature - {}: {}", | ||
signature, | ||
e | ||
)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's change the error message so it would be used the same way as in the other msg_id files (only populate it with the message id - signature in our case), without the extra format!
call:
.map_err(|e: TryFromSliceError| {
Error::InvalidTxDigest(
signature.to_owned()
))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed at c370f4d
|
||
#[test] | ||
fn should_not_parse_msg_id_with_correct_length_base58_but_wrong_length_hex() { | ||
// this is 88 chars and valid base58, but will encode to 33 bytes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This commend is invalid, right?
but will encode to 33 bytes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch ! fixed at c8d6344
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also updated this lower bound check to 64 99bd04d
})?) | ||
} | ||
|
||
const PATTERN: &str = "^([1-9A-HJ-NP-Za-km-z]{32,88})-(0|[1-9][0-9]*)$"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on my reading, the Solana signatures are 86-88 chars long.
But a zeroized byte array [0, 0, ..n]
(n=64) will result in base58 string that's 64 chars long:
import base58
# Create 64 bytes all containing 0
data = bytes([0] * 64)
# Encode the data using Base58
encoded = base58.b58encode(data)
# Print the encoded string
print(f"Base58 Encoded String: {encoded}")
print(f"Length of Encoded String: {len(encoded)}")
# Base58 Encoded String: b'1111111111111111111111111111111111111111111111111111111111111111'
# Length of Encoded String: 64
Im not sure if there are other edge cases like this 🤔 , but I think its safe to adjust the regex pattern to ..{64,88}..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on the signature's code , i think it's suggesting at least we are going to fill the whole byte slice [u8; 64] , thus the minimum of 64
you are commmenting makes sense and seems safe to adopt.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed at 002caa6
|
||
use super::*; | ||
|
||
fn random_bytes() -> [u8; 64] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use the type alias that you defined at the top of the file RawSignature
let res = Base58SolanaTxDigestAndEventIndex::from_str( | ||
"4hHzKKdpXH2QMB5Jm11YR48cLqUJb9Cwq2YL3tveVTPeFkZaLP8cdcH5UphVPJ7kYwCUCRLnywd3xkUhb4ZYWtf5-0", | ||
); | ||
res.unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it would be more idiomatic to assert the Result type rather than unwrap and not use the result:
assert!(res.is_ok());
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed at edb54bd . I changed it previously to debug a test. IMO, this is a bad sympton of fragile tests. As the negative can come from different underlying reasons. but let's keep aligned with current test structure.
// this is 44 chars and valid base 58, but will encode to 33 bytes | ||
// (z is the largest base58 digit, and so this will overflow 2^256) | ||
let tx_digest = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"; | ||
assert_eq!(tx_digest.len(), 44); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be adjusted to test the upper 88
char limit rather than 44
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also fixed at c8d6344
)); | ||
assert!(res.is_err()); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally speaking, I would opt for using proptest and do some property-based testing that generates the values for us. But let's not overcomplicate this PR. I'm just mentioning this as something cool that can be expanded upon.
02fb8f9
to
c8d6344
Compare
@roberts-pumpurs thanks for your review, addressed all suggestions. I will start crafting a new PR based on this outcome for upstream. |
Upstream PR is ready for review: axelarnetwork#494 |
Closing this PR because it has been merged in upstream |
Description
At Eiger we are developing the Solana integration. During tests, we realised the current Base58TxDigestAndEventIndex does not support the specific Solana transaction ids (a.k.a as Signatures), which have a length of
88
characters on it'sbase58
encoded form.This PR aims to add support for the Solana message id type's by adding a new enum variant on the existing codebase.
Todos
Steps to Test
Expected Behaviour
Other Notes
We are unsure about the non direct implications of this change nor it's impact into Axelar's future plans. We appreciate your feedback and suggestions.