solana/bridge: change VAA structure
Change-Id: I8304d2573aafd2291f2ddfc2eec6e605326d0e2d
This commit is contained in:
parent
84c47797ed
commit
776d774494
|
@ -1,11 +1,10 @@
|
|||
use std::io::{Cursor, Read, Write};
|
||||
|
||||
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||
use primitive_types::U256;
|
||||
use sha3::Digest;
|
||||
use solana_program::program_error::ProgramError;
|
||||
|
||||
use crate::{error::Error, state::AssetMeta};
|
||||
use crate::error::Error;
|
||||
use solana_program::pubkey::Pubkey;
|
||||
|
||||
pub type ForeignAddress = [u8; 32];
|
||||
|
@ -19,7 +18,10 @@ pub struct VAA {
|
|||
|
||||
// Body part
|
||||
pub timestamp: u32,
|
||||
pub payload: Option<VAABody>,
|
||||
pub nonce: u32,
|
||||
pub emitter_chain: u8,
|
||||
pub emitter_address: ForeignAddress,
|
||||
pub payload: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||
|
@ -37,7 +39,10 @@ impl VAA {
|
|||
guardian_set_index: 0,
|
||||
signatures: vec![],
|
||||
timestamp: 0,
|
||||
payload: None,
|
||||
emitter_chain: 0,
|
||||
emitter_address: [0u8; 32],
|
||||
nonce: 0,
|
||||
payload: vec![],
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -71,12 +76,10 @@ impl VAA {
|
|||
}
|
||||
|
||||
v.write_u32::<BigEndian>(self.timestamp)?;
|
||||
|
||||
let payload = self.payload.as_ref().ok_or(Error::InvalidVAAAction)?;
|
||||
v.write_u8(payload.action_id())?;
|
||||
|
||||
let payload_data = payload.serialize()?;
|
||||
v.write(payload_data.as_slice())?;
|
||||
v.write_u32::<BigEndian>(self.nonce)?;
|
||||
v.write_u8(self.emitter_chain)?;
|
||||
v.write(&self.emitter_address)?;
|
||||
v.write(&self.payload)?;
|
||||
|
||||
Ok(v.into_inner())
|
||||
}
|
||||
|
@ -85,12 +88,10 @@ impl VAA {
|
|||
let mut v = Cursor::new(Vec::new());
|
||||
|
||||
v.write_u32::<BigEndian>(self.timestamp)?;
|
||||
|
||||
let payload = self.payload.as_ref().ok_or(Error::InvalidVAAAction)?;
|
||||
v.write_u8(payload.action_id())?;
|
||||
|
||||
let payload_data = payload.serialize()?;
|
||||
v.write(payload_data.as_slice())?;
|
||||
v.write_u32::<BigEndian>(self.nonce)?;
|
||||
v.write_u8(self.emitter_chain)?;
|
||||
v.write(&self.emitter_address)?;
|
||||
v.write(&self.payload)?;
|
||||
|
||||
Ok(v.into_inner())
|
||||
}
|
||||
|
@ -117,388 +118,11 @@ impl VAA {
|
|||
v.signatures = sigs;
|
||||
|
||||
v.timestamp = rdr.read_u32::<BigEndian>()?;
|
||||
|
||||
let mut payload_d = Vec::new();
|
||||
rdr.read_to_end(&mut payload_d)?;
|
||||
v.payload = Some(VAABody::deserialize(&payload_d)?);
|
||||
v.nonce = rdr.read_u32::<BigEndian>()?;
|
||||
v.emitter_chain = rdr.read_u8()?;
|
||||
rdr.read_exact(&mut v.emitter_address)?;
|
||||
rdr.read_to_end(&mut v.payload)?;
|
||||
|
||||
Ok(v)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum VAABody {
|
||||
UpdateGuardianSet(BodyUpdateGuardianSet),
|
||||
Transfer(BodyTransfer),
|
||||
UpgradeContract(BodyContractUpgrade),
|
||||
}
|
||||
|
||||
impl VAABody {
|
||||
fn action_id(&self) -> u8 {
|
||||
match self {
|
||||
VAABody::UpdateGuardianSet(_) => 0x01,
|
||||
VAABody::UpgradeContract(_) => 0x02,
|
||||
VAABody::Transfer(_) => 0x10,
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize(data: &Vec<u8>) -> Result<VAABody, Error> {
|
||||
let mut payload_data = Cursor::new(data);
|
||||
let action = payload_data.read_u8()?;
|
||||
|
||||
let payload = match action {
|
||||
0x01 => {
|
||||
VAABody::UpdateGuardianSet(BodyUpdateGuardianSet::deserialize(&mut payload_data)?)
|
||||
}
|
||||
0x02 => VAABody::UpgradeContract(BodyContractUpgrade::deserialize(&mut payload_data)?),
|
||||
0x10 => VAABody::Transfer(BodyTransfer::deserialize(&mut payload_data)?),
|
||||
_ => {
|
||||
return Err(Error::InvalidVAAAction);
|
||||
}
|
||||
};
|
||||
|
||||
Ok(payload)
|
||||
}
|
||||
|
||||
fn serialize(&self) -> Result<Vec<u8>, Error> {
|
||||
match self {
|
||||
VAABody::Transfer(b) => b.serialize(),
|
||||
VAABody::UpdateGuardianSet(b) => b.serialize(),
|
||||
VAABody::UpgradeContract(b) => b.serialize(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct BodyUpdateGuardianSet {
|
||||
pub new_index: u32,
|
||||
pub new_keys: Vec<[u8; 20]>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct BodyTransfer {
|
||||
pub nonce: u32,
|
||||
pub source_chain: u8,
|
||||
pub target_chain: u8,
|
||||
pub source_address: ForeignAddress,
|
||||
pub target_address: ForeignAddress,
|
||||
pub asset: AssetMeta,
|
||||
pub amount: U256,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct BodyContractUpgrade {
|
||||
pub chain_id: u8,
|
||||
pub buffer: Pubkey,
|
||||
}
|
||||
|
||||
impl BodyContractUpgrade {
|
||||
fn deserialize(data: &mut Cursor<&Vec<u8>>) -> Result<BodyContractUpgrade, Error> {
|
||||
let chain_id = data.read_u8()?;
|
||||
let mut key: [u8; 32] = [0; 32];
|
||||
data.read(&mut key[..])?;
|
||||
|
||||
Ok(BodyContractUpgrade {
|
||||
chain_id,
|
||||
buffer: Pubkey::new(&key[..]),
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize(&self) -> Result<Vec<u8>, Error> {
|
||||
let mut v: Cursor<Vec<u8>> = Cursor::new(Vec::new());
|
||||
v.write_u8(self.chain_id)?;
|
||||
v.write(&self.buffer.to_bytes());
|
||||
|
||||
Ok(v.into_inner())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl BodyUpdateGuardianSet {
|
||||
fn deserialize(data: &mut Cursor<&Vec<u8>>) -> Result<BodyUpdateGuardianSet, Error> {
|
||||
let new_index = data.read_u32::<BigEndian>()?;
|
||||
|
||||
let keys_len = data.read_u8()?;
|
||||
let mut keys = Vec::with_capacity(keys_len as usize);
|
||||
for _ in 0..keys_len {
|
||||
let mut key: [u8; 20] = [0; 20];
|
||||
data.read(&mut key)?;
|
||||
keys.push(key);
|
||||
}
|
||||
|
||||
Ok(BodyUpdateGuardianSet {
|
||||
new_index,
|
||||
new_keys: keys,
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize(&self) -> Result<Vec<u8>, Error> {
|
||||
let mut v: Cursor<Vec<u8>> = Cursor::new(Vec::new());
|
||||
v.write_u32::<BigEndian>(self.new_index)?;
|
||||
v.write_u8(self.new_keys.len() as u8)?;
|
||||
|
||||
for k in self.new_keys.iter() {
|
||||
v.write(k)?;
|
||||
}
|
||||
|
||||
Ok(v.into_inner())
|
||||
}
|
||||
}
|
||||
|
||||
impl BodyTransfer {
|
||||
fn deserialize(data: &mut Cursor<&Vec<u8>>) -> Result<BodyTransfer, Error> {
|
||||
let nonce = data.read_u32::<BigEndian>()?;
|
||||
let source_chain = data.read_u8()?;
|
||||
let target_chain = data.read_u8()?;
|
||||
let mut source_address: ForeignAddress = ForeignAddress::default();
|
||||
data.read_exact(&mut source_address)?;
|
||||
let mut target_address: ForeignAddress = ForeignAddress::default();
|
||||
data.read_exact(&mut target_address)?;
|
||||
let token_chain = data.read_u8()?;
|
||||
let mut token_address: ForeignAddress = ForeignAddress::default();
|
||||
data.read_exact(&mut token_address)?;
|
||||
let token_decimals = data.read_u8()?;
|
||||
|
||||
let mut am_data: [u8; 32] = [0; 32];
|
||||
data.read_exact(&mut am_data)?;
|
||||
let amount = U256::from_big_endian(&am_data);
|
||||
|
||||
Ok(BodyTransfer {
|
||||
nonce,
|
||||
source_chain,
|
||||
target_chain,
|
||||
source_address,
|
||||
target_address,
|
||||
asset: AssetMeta {
|
||||
address: token_address,
|
||||
chain: token_chain,
|
||||
decimals: token_decimals,
|
||||
},
|
||||
amount,
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize(&self) -> Result<Vec<u8>, Error> {
|
||||
let mut v: Cursor<Vec<u8>> = Cursor::new(Vec::new());
|
||||
v.write_u32::<BigEndian>(self.nonce)?;
|
||||
v.write_u8(self.source_chain)?;
|
||||
v.write_u8(self.target_chain)?;
|
||||
v.write(&self.source_address)?;
|
||||
v.write(&self.target_address)?;
|
||||
v.write_u8(self.asset.chain)?;
|
||||
v.write(&self.asset.address)?;
|
||||
v.write_u8(self.asset.decimals)?;
|
||||
|
||||
let mut am_data: [u8; 32] = [0; 32];
|
||||
self.amount.to_big_endian(&mut am_data);
|
||||
v.write(&am_data[..])?;
|
||||
|
||||
Ok(v.into_inner())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use hex;
|
||||
use primitive_types::U256;
|
||||
|
||||
use crate::{
|
||||
state::AssetMeta,
|
||||
vaa::{BodyTransfer, BodyUpdateGuardianSet, Signature, VAABody, VAA},
|
||||
};
|
||||
use crate::vaa::BodyContractUpgrade;
|
||||
use solana_program::pubkey::Pubkey;
|
||||
|
||||
#[test]
|
||||
fn serialize_deserialize_vaa_transfer() {
|
||||
let vaa = VAA {
|
||||
version: 8,
|
||||
guardian_set_index: 3,
|
||||
signatures: vec![Signature {
|
||||
index: 1,
|
||||
r: [2; 32],
|
||||
s: [2; 32],
|
||||
v: 7,
|
||||
}],
|
||||
timestamp: 83,
|
||||
payload: Some(VAABody::Transfer(BodyTransfer {
|
||||
nonce: 28,
|
||||
source_chain: 1,
|
||||
target_chain: 2,
|
||||
source_address: [1; 32],
|
||||
target_address: [1; 32],
|
||||
asset: AssetMeta {
|
||||
address: [2; 32],
|
||||
chain: 8,
|
||||
decimals: 9,
|
||||
},
|
||||
amount: U256::from(3),
|
||||
})),
|
||||
};
|
||||
|
||||
let data = vaa.serialize().unwrap();
|
||||
let parsed_vaa = VAA::deserialize(data.as_slice()).unwrap();
|
||||
assert_eq!(vaa, parsed_vaa)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serialize_deserialize_vaa_guardian() {
|
||||
let vaa = VAA {
|
||||
version: 8,
|
||||
guardian_set_index: 3,
|
||||
signatures: vec![Signature {
|
||||
index: 1,
|
||||
r: [2; 32],
|
||||
s: [2; 32],
|
||||
v: 7,
|
||||
}],
|
||||
timestamp: 83,
|
||||
payload: Some(VAABody::UpdateGuardianSet(BodyUpdateGuardianSet {
|
||||
new_index: 29,
|
||||
new_keys: vec![],
|
||||
})),
|
||||
};
|
||||
|
||||
let data = vaa.serialize().unwrap();
|
||||
let parsed_vaa = VAA::deserialize(data.as_slice()).unwrap();
|
||||
assert_eq!(vaa, parsed_vaa)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serialize_deserialize_vaa_contract_upgrade() {
|
||||
let vaa = VAA {
|
||||
version: 8,
|
||||
guardian_set_index: 3,
|
||||
signatures: vec![Signature {
|
||||
index: 1,
|
||||
r: [2; 32],
|
||||
s: [2; 32],
|
||||
v: 7,
|
||||
}],
|
||||
timestamp: 83,
|
||||
payload: Some(VAABody::UpgradeContract(BodyContractUpgrade {
|
||||
chain_id: 3,
|
||||
buffer: Pubkey::new_unique(),
|
||||
})),
|
||||
};
|
||||
|
||||
let data = vaa.serialize().unwrap();
|
||||
let parsed_vaa = VAA::deserialize(data.as_slice()).unwrap();
|
||||
assert_eq!(vaa, parsed_vaa)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_given_guardian_set_update() {
|
||||
let vaa = VAA {
|
||||
version: 1,
|
||||
guardian_set_index: 0,
|
||||
signatures: vec![Signature {
|
||||
index: 0,
|
||||
r: [
|
||||
51, 130, 199, 26, 76, 121, 225, 81, 138, 108, 226, 156, 145, 86, 159, 100, 39,
|
||||
166, 10, 149, 105, 106, 53, 21, 184, 194, 52, 11, 106, 207, 253, 114,
|
||||
],
|
||||
s: [
|
||||
51, 21, 189, 16, 17, 170, 119, 159, 34, 87, 56, 130, 164, 237, 254, 27, 130, 6,
|
||||
84, 142, 19, 72, 113, 162, 63, 139, 160, 193, 199, 208, 181, 237,
|
||||
],
|
||||
v: 1,
|
||||
}],
|
||||
timestamp: 3000,
|
||||
payload: Some(VAABody::UpdateGuardianSet(BodyUpdateGuardianSet {
|
||||
new_index: 1,
|
||||
new_keys: vec![[
|
||||
190, 250, 66, 157, 87, 205, 24, 183, 248, 164, 217, 26, 45, 169, 171, 74, 240,
|
||||
93, 15, 190,
|
||||
]],
|
||||
})),
|
||||
};
|
||||
let data = hex::decode("010000000001003382c71a4c79e1518a6ce29c91569f6427a60a95696a3515b8c2340b6acffd723315bd1011aa779f22573882a4edfe1b8206548e134871a23f8ba0c1c7d0b5ed0100000bb8010000000101befa429d57cd18b7f8a4d91a2da9ab4af05d0fbe").unwrap();
|
||||
let parsed_vaa = VAA::deserialize(data.as_slice()).unwrap();
|
||||
assert_eq!(vaa, parsed_vaa);
|
||||
|
||||
let rec_data = parsed_vaa.serialize().unwrap();
|
||||
assert_eq!(data, rec_data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_given_transfer() {
|
||||
let vaa = VAA {
|
||||
version: 1,
|
||||
guardian_set_index: 0,
|
||||
signatures: vec![Signature {
|
||||
index: 0,
|
||||
r: [
|
||||
146, 115, 122, 21, 4, 243, 179, 223, 140, 147, 203, 133, 198, 74, 72, 96, 187,
|
||||
39, 14, 38, 2, 107, 110, 55, 240, 149, 53, 106, 64, 111, 106, 244,
|
||||
],
|
||||
s: [
|
||||
57, 198, 178, 233, 119, 95, 161, 198, 102, 149, 37, 240, 110, 218, 176, 51,
|
||||
186, 93, 68, 115, 8, 244, 227, 189, 179, 60, 15, 54, 29, 195, 46, 195,
|
||||
],
|
||||
v: 1,
|
||||
}],
|
||||
timestamp: 1597440008,
|
||||
payload: Some(VAABody::Transfer(BodyTransfer {
|
||||
nonce: 53,
|
||||
source_chain: 1,
|
||||
target_chain: 2,
|
||||
source_address: [
|
||||
2, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
],
|
||||
target_address: [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 248, 191, 106, 71, 159, 50, 14, 173,
|
||||
7, 68, 17, 164, 176, 231, 148, 78, 168, 201, 193,
|
||||
],
|
||||
asset: AssetMeta {
|
||||
address: [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 71, 239, 52, 104, 123, 220, 159, 24,
|
||||
158, 135, 169, 32, 6, 88, 217, 196, 14, 153, 136,
|
||||
],
|
||||
chain: 1,
|
||||
decimals: 8,
|
||||
},
|
||||
amount: U256::from_dec_str("5000000000000000000").unwrap(),
|
||||
})),
|
||||
};
|
||||
let data = hex::decode("0100000000010092737a1504f3b3df8c93cb85c64a4860bb270e26026b6e37f095356a406f6af439c6b2e9775fa1c6669525f06edab033ba5d447308f4e3bdb33c0f361dc32ec3015f37000810000000350102020104000000000000000000000000000000000000000000000000000000000000000000000000000000000090f8bf6a479f320ead074411a4b0e7944ea8c9c1010000000000000000000000000347ef34687bdc9f189e87a9200658d9c40e9988080000000000000000000000000000000000000000000000004563918244f40000").unwrap();
|
||||
let parsed_vaa = VAA::deserialize(data.as_slice()).unwrap();
|
||||
assert_eq!(vaa, parsed_vaa);
|
||||
|
||||
let rec_data = parsed_vaa.serialize().unwrap();
|
||||
assert_eq!(data, rec_data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_given_contract_upgrade() {
|
||||
let vaa = VAA {
|
||||
version: 1,
|
||||
guardian_set_index: 2,
|
||||
signatures: vec![Signature {
|
||||
index: 0,
|
||||
r: [
|
||||
72, 156, 56, 20, 222, 146, 161, 112, 22, 97, 69, 59, 188, 199, 130, 240, 89,
|
||||
249, 241, 79, 96, 27, 235, 10, 99, 16, 56, 80, 232, 188, 235, 11
|
||||
],
|
||||
s: [
|
||||
65, 19, 144, 42, 104, 122, 52, 0, 126, 7, 43, 127, 120, 85, 5, 21, 216, 207,
|
||||
78, 73, 213, 207, 142, 103, 211, 192, 100, 90, 27, 98, 176, 98
|
||||
],
|
||||
v: 1,
|
||||
}],
|
||||
timestamp: 4000,
|
||||
payload: Some(VAABody::UpgradeContract(BodyContractUpgrade {
|
||||
chain_id: 2,
|
||||
buffer: Pubkey::new(&[146, 115, 122, 21, 4, 243, 179, 223, 140, 147, 203, 133, 198, 74, 72, 96, 187,
|
||||
39, 14, 38, 2, 107, 110, 55, 240, 149, 53, 106, 64, 111, 106, 244]),
|
||||
})),
|
||||
};
|
||||
let data = hex::decode("01000000020100489c3814de92a1701661453bbcc782f059f9f14f601beb0a63103850e8bceb0b4113902a687a34007e072b7f78550515d8cf4e49d5cf8e67d3c0645a1b62b0620100000fa0020292737a1504f3b3df8c93cb85c64a4860bb270e26026b6e37f095356a406f6af4").unwrap();
|
||||
let parsed_vaa = VAA::deserialize(data.as_slice()).unwrap();
|
||||
assert_eq!(vaa, parsed_vaa);
|
||||
|
||||
let rec_data = parsed_vaa.serialize().unwrap();
|
||||
assert_eq!(data, rec_data);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue