Skip to content

Commit

Permalink
feat(minor-multisig-prover): stellar encode execute data (#598)
Browse files Browse the repository at this point in the history
  • Loading branch information
haiyizxx authored Sep 10, 2024
1 parent bcc5dc1 commit e2ea40c
Show file tree
Hide file tree
Showing 11 changed files with 415 additions and 13 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions contracts/multisig-prover/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ serde_json = "1.0.89"
service-registry = { workspace = true }
sha3 = { workspace = true }
stellar = { workspace = true }
stellar-xdr = { workspace = true }
sui-gateway = { workspace = true }
thiserror = { workspace = true }
voting-verifier = { workspace = true, features = ["library"] }
Expand Down
4 changes: 2 additions & 2 deletions contracts/multisig-prover/src/encoding/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ impl Encoder {
&self.digest(domain_separator, verifier_set, payload)?,
payload,
),
Encoder::StellarXdr => todo!(),
Encoder::StellarXdr => stellar_xdr::encode_execute_data(verifier_set, sigs, payload),
}
}
}
Expand All @@ -70,7 +70,7 @@ where
let recovery_transform = match encoder {
Encoder::Abi => add_27,
Encoder::Bcs => no_op,
Encoder::StellarXdr => no_op,
_ => panic!("unsupported encoder"),
};
signers
.into_iter()
Expand Down
195 changes: 186 additions & 9 deletions contracts/multisig-prover/src/encoding/stellar_xdr.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use axelar_wasm_std::hash::Hash;
use axelar_wasm_std::FnExt;
use cosmwasm_std::HexBinary;
use error_stack::{Result, ResultExt};
use multisig::msg::SignerWithSig;
use multisig::verifier_set::VerifierSet;
use sha3::{Digest, Keccak256};
use stellar::{Message, Messages, WeightedSigners};
use stellar::{Message, Messages, Proof, WeightedSigners};
use stellar_xdr::curr::{Limits, ScVal, WriteXdr};

use crate::error::ContractError;
use crate::payload::Payload;
Expand Down Expand Up @@ -42,15 +45,49 @@ pub fn payload_digest(
Ok(Keccak256::digest(unsigned).into())
}

/// `encode_execute_data` returns the XDR encoded external gateway function call args.
/// The relayer will use this data to submit the payload to the contract.
pub fn encode_execute_data(
verifier_set: &VerifierSet,
signatures: Vec<SignerWithSig>,
payload: &Payload,
) -> Result<HexBinary, ContractError> {
let payload = match payload {
Payload::Messages(messages) => ScVal::try_from(
messages
.iter()
.map(Message::try_from)
.collect::<Result<Vec<_>, _>>()
.change_context(ContractError::InvalidMessage)?
.then(Messages::from),
),
Payload::VerifierSet(verifier_set) => ScVal::try_from(
WeightedSigners::try_from(verifier_set)
.change_context(ContractError::InvalidVerifierSet)?,
),
}
.change_context(ContractError::SerializeData)?;

let proof =
Proof::try_from((verifier_set.clone(), signatures)).change_context(ContractError::Proof)?;

let execute_data = ScVal::try_from((payload, proof))
.expect("must convert tuple of size 2 to ScVec")
.to_xdr(Limits::none())
.change_context(ContractError::SerializeData)?;

Ok(execute_data.as_slice().into())
}
#[cfg(test)]
mod tests {
use cosmwasm_std::{Addr, HexBinary, Uint128};
use multisig::key::KeyType;
use multisig::msg::Signer;
use multisig::key::KeyType::Ed25519;
use multisig::key::Signature;
use multisig::msg::{Signer, SignerWithSig};
use multisig::verifier_set::VerifierSet;
use router_api::{CrossChainId, Message};

use crate::encoding::stellar_xdr::payload_digest;
use crate::encoding::stellar_xdr::{encode_execute_data, payload_digest};
use crate::payload::Payload;

#[test]
Expand Down Expand Up @@ -87,7 +124,7 @@ mod tests {
6u128,
),
];
let verifier_set = gen_veifier_set(signers_data, 22, 2024);
let verifier_set = gen_verifier_set(signers_data, 22, 2024);

let payload = Payload::Messages(vec![Message {
cc_id: CrossChainId {
Expand Down Expand Up @@ -120,7 +157,7 @@ mod tests {

#[test]
fn stellar_verifier_set_payload_digest() {
let verifier_set = gen_veifier_set(
let verifier_set = gen_verifier_set(
vec![(
"addr_1",
"bf95c447eb2e694974ee2cf5f17e7165bc884a0cb676bb4de50c604bb7a6ea77",
Expand Down Expand Up @@ -156,7 +193,7 @@ mod tests {
7u128,
),
];
let payload = Payload::VerifierSet(gen_veifier_set(signers_data, 27, 2024));
let payload = Payload::VerifierSet(gen_verifier_set(signers_data, 27, 2024));
let domain_separator: [u8; 32] =
HexBinary::from_hex("6773bd037510492f863cba62a0f3c55ac846883f33cae7266aff8be5eb9681e8")
.unwrap()
Expand All @@ -168,7 +205,130 @@ mod tests {
));
}

fn gen_veifier_set(
#[test]
fn stellar_approve_messages_execute_data() {
let signers_data = vec![
(
"addr_1",
"12f7d9a9463212335914b39ee90bfa2045f90b64c1f2d7b58ed335282abac4a4",
8u128,
"b5b3b0749aa585f866d802e32ca4a6356f82eb52e2a1b4797cbaa30f3d755462f2eb995c70d9099e436b8a48498e4d613ff2d3ca7618973a36c2fde17493180f",
),
(
"addr_2",
"4c3863e4b0252a8674c1c6ad70b3ca3002b400b49ddfae5583b21907e65c5dd8",
1u128,
"cb8a1b98ec7678d5eb965d47c449b2b8396d170e53ad7b5f65a7c0fdf2aebe206b65be7cb2e81c7ddd8924acb2ffc2d463b678993227fdfbfc3ef03a8ffa030c",
),
(
"addr_3",
"c35aa94d2038f258ecb1bb28fbc8a83ab79d2dc0a7223fd528a8f52a14c03292",
7u128,
"28e2c8accfa1c2db93349c6d3f783004d6a92cdbf322b92b3555315999e0eaf5d8bdf9deb58d798168a880972e81b8513dcb942de44862317d501cf7445c660a"
),

];

let verifier_set = gen_verifier_set(
signers_data
.iter()
.map(|(t1, t2, t3, _)| (*t1, *t2, *t3))
.collect(),
10,
2024,
);

let signer_with_sig = gen_signers_with_sig(signers_data);

let payload = Payload::Messages(vec![Message {
cc_id: CrossChainId {
source_chain: "source".parse().unwrap(),
message_id: "test".parse().unwrap(),
},
source_address: "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
.parse()
.unwrap(),
destination_chain: "stellar".parse().unwrap(),
destination_address: "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4"
.parse()
.unwrap(),
payload_hash: HexBinary::from_hex(
"595c9108df17d1cc43e8268ec1516064299c1388bcc86fdd566bcdf400a0a1ed",
)
.unwrap()
.to_array()
.unwrap(),
}]);

goldie::assert!(
encode_execute_data(&verifier_set, signer_with_sig, &payload)
.unwrap()
.to_hex()
);
}

#[test]
fn stellar_rotate_signers_execute_data() {
let signers_data = vec![
(
"addr_1",
"77dd4768dda195f8080fe970be8fec5fee9cea781718158ce19d4a331442fd57",
2u128,
"91db8ad94ab379ee9021caeb3ee852582d09d06801213256cbd2937f2ad8182f518fde7a7f8c801adde7161e05cbbb9841ac0bf3290831570a54c6ae3d089703",
),
];

let verifier_set = gen_verifier_set(
signers_data
.iter()
.map(|(t1, t2, t3, _)| (*t1, *t2, *t3))
.collect(),
1,
2024,
);

let signer_with_sig = gen_signers_with_sig(signers_data);

let payload = Payload::VerifierSet(gen_verifier_set(
vec![
(
"addr_1",
"358a2305fc783b6072049ee6f5f76fb14c3a14d7c01e36d9ef502661bf46a011",
9u128,
),
(
"addr_2",
"3b1caf530189a9a65ae347b18cb8bf88729ba90d2aeaf7f185b600400ab49891",
1u128,
),
(
"addr_3",
"531616448afd45c0e3e053622cbccb65d8fc99cd2f02636d728739811e72eafb",
3u128,
),
(
"addr_4",
"5e4c8ec6569774adf69cb6e2bc4ef556c2fc6b412c85d6a5e0b18d54b069e594",
7u128,
),
(
"addr_5",
"8097528d987899f887c08c23a928dfe6fe9550010d19c7be0b46b5d0596997cc",
3u128,
),
],
17,
2024,
));

goldie::assert!(
encode_execute_data(&verifier_set, signer_with_sig, &payload)
.unwrap()
.to_hex()
);
}

fn gen_verifier_set(
signers_data: Vec<(&str, &str, u128)>,
threshold: u128,
created_at: u64,
Expand All @@ -181,7 +341,7 @@ mod tests {
addr.to_string(),
Signer {
address: Addr::unchecked(addr),
pub_key: (KeyType::Ed25519, HexBinary::from_hex(pub_key).unwrap())
pub_key: (Ed25519, HexBinary::from_hex(pub_key).unwrap())
.try_into()
.unwrap(),
weight: Uint128::from(weight),
Expand All @@ -193,4 +353,21 @@ mod tests {
created_at,
}
}
fn gen_signers_with_sig(signers_data: Vec<(&str, &str, u128, &str)>) -> Vec<SignerWithSig> {
signers_data
.into_iter()
.map(|(addr, pub_key, weight, sig)| {
Signer {
address: Addr::unchecked(addr),
pub_key: (Ed25519, HexBinary::from_hex(pub_key).unwrap())
.try_into()
.unwrap(),
weight: Uint128::from(weight),
}
.with_sig(
Signature::try_from((Ed25519, HexBinary::from_hex(sig).unwrap())).unwrap(),
)
})
.collect::<Vec<_>>()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0000001000000001000000020000001000000001000000010000001100000001000000050000000f00000010636f6e74726163745f61646472657373000000120000000100000000000000000000000000000000000000000000000000000000000000060000000f0000000a6d6573736167655f696400000000000e00000004746573740000000f0000000c7061796c6f61645f686173680000000d00000020595c9108df17d1cc43e8268ec1516064299c1388bcc86fdd566bcdf400a0a1ed0000000f0000000e736f757263655f6164647265737300000000000e0000003843414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141484b334d0000000f0000000c736f757263655f636861696e0000000e00000006736f7572636500000000001100000001000000030000000f000000056e6f6e63650000000000000d0000002000000000000000000000000000000000000000000000000000000000000007e80000000f000000077369676e657273000000001000000001000000030000001100000001000000020000000f000000097369676e61747572650000000000001000000001000000020000000f000000065369676e656400000000000d00000040b5b3b0749aa585f866d802e32ca4a6356f82eb52e2a1b4797cbaa30f3d755462f2eb995c70d9099e436b8a48498e4d613ff2d3ca7618973a36c2fde17493180f0000000f000000067369676e657200000000001100000001000000020000000f000000067369676e657200000000000d0000002012f7d9a9463212335914b39ee90bfa2045f90b64c1f2d7b58ed335282abac4a40000000f00000006776569676874000000000009000000000000000000000000000000080000001100000001000000020000000f000000097369676e61747572650000000000001000000001000000020000000f000000065369676e656400000000000d00000040cb8a1b98ec7678d5eb965d47c449b2b8396d170e53ad7b5f65a7c0fdf2aebe206b65be7cb2e81c7ddd8924acb2ffc2d463b678993227fdfbfc3ef03a8ffa030c0000000f000000067369676e657200000000001100000001000000020000000f000000067369676e657200000000000d000000204c3863e4b0252a8674c1c6ad70b3ca3002b400b49ddfae5583b21907e65c5dd80000000f00000006776569676874000000000009000000000000000000000000000000010000001100000001000000020000000f000000097369676e61747572650000000000001000000001000000020000000f000000065369676e656400000000000d0000004028e2c8accfa1c2db93349c6d3f783004d6a92cdbf322b92b3555315999e0eaf5d8bdf9deb58d798168a880972e81b8513dcb942de44862317d501cf7445c660a0000000f000000067369676e657200000000001100000001000000020000000f000000067369676e657200000000000d00000020c35aa94d2038f258ecb1bb28fbc8a83ab79d2dc0a7223fd528a8f52a14c032920000000f00000006776569676874000000000009000000000000000000000000000000070000000f000000097468726573686f6c64000000000000090000000000000000000000000000000a
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0000001000000001000000020000001100000001000000030000000f000000056e6f6e63650000000000000d0000002000000000000000000000000000000000000000000000000000000000000007e80000000f000000077369676e657273000000001000000001000000050000001100000001000000020000000f000000067369676e657200000000000d00000020358a2305fc783b6072049ee6f5f76fb14c3a14d7c01e36d9ef502661bf46a0110000000f00000006776569676874000000000009000000000000000000000000000000090000001100000001000000020000000f000000067369676e657200000000000d000000203b1caf530189a9a65ae347b18cb8bf88729ba90d2aeaf7f185b600400ab498910000000f00000006776569676874000000000009000000000000000000000000000000010000001100000001000000020000000f000000067369676e657200000000000d00000020531616448afd45c0e3e053622cbccb65d8fc99cd2f02636d728739811e72eafb0000000f00000006776569676874000000000009000000000000000000000000000000030000001100000001000000020000000f000000067369676e657200000000000d000000205e4c8ec6569774adf69cb6e2bc4ef556c2fc6b412c85d6a5e0b18d54b069e5940000000f00000006776569676874000000000009000000000000000000000000000000070000001100000001000000020000000f000000067369676e657200000000000d000000208097528d987899f887c08c23a928dfe6fe9550010d19c7be0b46b5d0596997cc0000000f00000006776569676874000000000009000000000000000000000000000000030000000f000000097468726573686f6c6400000000000009000000000000000000000000000000110000001100000001000000030000000f000000056e6f6e63650000000000000d0000002000000000000000000000000000000000000000000000000000000000000007e80000000f000000077369676e657273000000001000000001000000010000001100000001000000020000000f000000097369676e61747572650000000000001000000001000000020000000f000000065369676e656400000000000d0000004091db8ad94ab379ee9021caeb3ee852582d09d06801213256cbd2937f2ad8182f518fde7a7f8c801adde7161e05cbbb9841ac0bf3290831570a54c6ae3d0897030000000f000000067369676e657200000000001100000001000000020000000f000000067369676e657200000000000d0000002077dd4768dda195f8080fe970be8fec5fee9cea781718158ce19d4a331442fd570000000f00000006776569676874000000000009000000000000000000000000000000020000000f000000097468726573686f6c640000000000000900000000000000000000000000000001
4 changes: 4 additions & 0 deletions external-gateways/stellar/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ pub enum Error {
InvalidPublicKey,
#[error("invalid destination address")]
InvalidDestinationAddress,
#[error("unsupported type of signature")]
UnsupportedSignature,
#[error("invalid signature")]
InvalidSignature,
}
Loading

0 comments on commit e2ea40c

Please sign in to comment.