Fix Governance Headers
Change-Id: If2026ff4a6107327f69c5d0675a736e6ab87f1bd
This commit is contained in:
parent
1992684351
commit
99c3e40968
|
@ -57,7 +57,7 @@ where
|
||||||
#[derive(FromAccounts)]
|
#[derive(FromAccounts)]
|
||||||
pub struct UpgradeContract<'b> {
|
pub struct UpgradeContract<'b> {
|
||||||
/// Payer for account creation (vaa-claim)
|
/// Payer for account creation (vaa-claim)
|
||||||
pub payer: Signer<Info<'b>>,
|
pub payer: Mut<Signer<Info<'b>>>,
|
||||||
|
|
||||||
/// Upgrade VAA
|
/// Upgrade VAA
|
||||||
pub vaa: ClaimableVAA<'b, GovernancePayloadUpgrade>,
|
pub vaa: ClaimableVAA<'b, GovernancePayloadUpgrade>,
|
||||||
|
@ -91,8 +91,10 @@ pub fn upgrade_contract(
|
||||||
accs.spill.key,
|
accs.spill.key,
|
||||||
);
|
);
|
||||||
|
|
||||||
let _seeds = accs.upgrade_authority.self_seeds(None);
|
let seeds = accs.upgrade_authority.self_bumped_seeds(None, ctx.program_id);
|
||||||
invoke_signed(&upgrade_ix, ctx.accounts, &[])?;
|
let seeds: Vec<&[u8]> = seeds.iter().map(|item| item.as_slice()).collect();
|
||||||
|
let seeds = seeds.as_slice();
|
||||||
|
invoke_signed(&upgrade_ix, ctx.accounts, &[seeds])?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -138,6 +140,7 @@ pub fn upgrade_guardian_set(
|
||||||
_data: UpgradeGuardianSetData,
|
_data: UpgradeGuardianSetData,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
verify_claim(&accs.vaa)?;
|
verify_claim(&accs.vaa)?;
|
||||||
|
|
||||||
accs.guardian_set_old.verify_derivation(
|
accs.guardian_set_old.verify_derivation(
|
||||||
ctx.program_id,
|
ctx.program_id,
|
||||||
&GuardianSetDerivationData {
|
&GuardianSetDerivationData {
|
||||||
|
|
|
@ -62,8 +62,6 @@ pub struct VerifySignaturesData {
|
||||||
pub hash: [u8; 32],
|
pub hash: [u8; 32],
|
||||||
/// instruction indices of signers (-1 for missing)
|
/// instruction indices of signers (-1 for missing)
|
||||||
pub signers: [i8; MAX_LEN_GUARDIAN_KEYS],
|
pub signers: [i8; MAX_LEN_GUARDIAN_KEYS],
|
||||||
/// indicates whether this verification should only succeed if the sig account does not exist
|
|
||||||
pub initial_creation: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SigInfo contains metadata about signers in a VerifySignature ix
|
/// SigInfo contains metadata about signers in a VerifySignature ix
|
||||||
|
|
|
@ -240,10 +240,10 @@ pub fn upgrade_contract(
|
||||||
|
|
||||||
accounts: vec![
|
accounts: vec![
|
||||||
AccountMeta::new(payer, true),
|
AccountMeta::new(payer, true),
|
||||||
AccountMeta::new(payload_message, false),
|
AccountMeta::new_readonly(payload_message, false),
|
||||||
AccountMeta::new(claim, false),
|
AccountMeta::new(claim, false),
|
||||||
AccountMeta::new(upgrade_authority, false),
|
AccountMeta::new_readonly(upgrade_authority, false),
|
||||||
AccountMeta::new(spill, false),
|
AccountMeta::new_readonly(spill, false),
|
||||||
],
|
],
|
||||||
|
|
||||||
data: (crate::instruction::Instruction::UpgradeContract, UpgradeContractData {})
|
data: (crate::instruction::Instruction::UpgradeContract, UpgradeContractData {})
|
||||||
|
|
|
@ -251,6 +251,7 @@ where
|
||||||
{
|
{
|
||||||
fn deserialize(buf: &mut &[u8]) -> Result<Self, SolitaireError> {
|
fn deserialize(buf: &mut &[u8]) -> Result<Self, SolitaireError> {
|
||||||
let mut c = Cursor::new(buf);
|
let mut c = Cursor::new(buf);
|
||||||
|
Self::check_governance_header(&mut c)?;
|
||||||
|
|
||||||
let new_index = c.read_u32::<BigEndian>()?;
|
let new_index = c.read_u32::<BigEndian>()?;
|
||||||
|
|
||||||
|
@ -270,7 +271,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeserializeGovernancePayload for GovernancePayloadGuardianSetChange {
|
impl DeserializeGovernancePayload for GovernancePayloadGuardianSetChange {
|
||||||
const MODULE: &'static str = "CORE";
|
const MODULE: &'static str = "Core";
|
||||||
const ACTION: u8 = 1;
|
const ACTION: u8 = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,13 +280,19 @@ pub struct GovernancePayloadUpgrade {
|
||||||
pub new_contract: Pubkey,
|
pub new_contract: Pubkey,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SerializePayload for GovernancePayloadUpgrade {
|
||||||
|
fn serialize<W: Write>(&self, v: &mut W) -> std::result::Result<(), SolitaireError> {
|
||||||
|
v.write(&self.new_contract.to_bytes())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl DeserializePayload for GovernancePayloadUpgrade
|
impl DeserializePayload for GovernancePayloadUpgrade
|
||||||
where
|
where
|
||||||
Self: DeserializeGovernancePayload,
|
Self: DeserializeGovernancePayload,
|
||||||
{
|
{
|
||||||
fn deserialize(buf: &mut &[u8]) -> Result<Self, SolitaireError> {
|
fn deserialize(buf: &mut &[u8]) -> Result<Self, SolitaireError> {
|
||||||
let mut c = Cursor::new(buf);
|
let mut c = Cursor::new(buf);
|
||||||
|
|
||||||
Self::check_governance_header(&mut c)?;
|
Self::check_governance_header(&mut c)?;
|
||||||
|
|
||||||
let mut addr = [0u8; 32];
|
let mut addr = [0u8; 32];
|
||||||
|
@ -329,6 +336,7 @@ where
|
||||||
{
|
{
|
||||||
fn deserialize(buf: &mut &[u8]) -> Result<Self, SolitaireError> {
|
fn deserialize(buf: &mut &[u8]) -> Result<Self, SolitaireError> {
|
||||||
let mut c = Cursor::new(buf);
|
let mut c = Cursor::new(buf);
|
||||||
|
Self::check_governance_header(&mut c)?;
|
||||||
|
|
||||||
let mut fee_data: [u8; 32] = [0; 32];
|
let mut fee_data: [u8; 32] = [0; 32];
|
||||||
c.read_exact(&mut fee_data)?;
|
c.read_exact(&mut fee_data)?;
|
||||||
|
@ -374,6 +382,7 @@ where
|
||||||
{
|
{
|
||||||
fn deserialize(buf: &mut &[u8]) -> Result<Self, SolitaireError> {
|
fn deserialize(buf: &mut &[u8]) -> Result<Self, SolitaireError> {
|
||||||
let mut c = Cursor::new(buf);
|
let mut c = Cursor::new(buf);
|
||||||
|
Self::check_governance_header(&mut c)?;
|
||||||
|
|
||||||
let mut amount_data: [u8; 32] = [0; 32];
|
let mut amount_data: [u8; 32] = [0; 32];
|
||||||
c.read_exact(&mut amount_data)?;
|
c.read_exact(&mut amount_data)?;
|
||||||
|
|
|
@ -39,13 +39,27 @@ use std::{
|
||||||
ops::Deref,
|
ops::Deref,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait SerializePayload: Sized {
|
pub trait SerializePayload: Sized + DeserializeGovernancePayload {
|
||||||
fn serialize<W: Write>(&self, writer: &mut W) -> std::result::Result<(), SolitaireError>;
|
fn serialize<W: Write>(&self, writer: &mut W) -> std::result::Result<(), SolitaireError>;
|
||||||
fn try_to_vec(&self) -> std::result::Result<Vec<u8>, SolitaireError> {
|
fn try_to_vec(&self) -> std::result::Result<Vec<u8>, SolitaireError> {
|
||||||
let mut result = Vec::with_capacity(256);
|
let mut result = Vec::with_capacity(256);
|
||||||
|
self.write_governance_header(&mut result)?;
|
||||||
self.serialize(&mut result)?;
|
self.serialize(&mut result)?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write_governance_header<W: Write>(
|
||||||
|
&self,
|
||||||
|
c: &mut W,
|
||||||
|
) -> std::result::Result<(), SolitaireError> {
|
||||||
|
use byteorder::WriteBytesExt;
|
||||||
|
let module = format!("{:\0>32}", Self::MODULE);
|
||||||
|
let module = module.as_bytes();
|
||||||
|
c.write(&module)?;
|
||||||
|
c.write_u8(Self::ACTION)?;
|
||||||
|
c.write_u16::<BigEndian>(CHAIN_ID_SOLANA)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DeserializePayload: Sized {
|
pub trait DeserializePayload: Sized {
|
||||||
|
|
|
@ -75,6 +75,7 @@ use bridge::{
|
||||||
instructions,
|
instructions,
|
||||||
types::{
|
types::{
|
||||||
BridgeConfig,
|
BridgeConfig,
|
||||||
|
ConsistencyLevel,
|
||||||
PostedMessage,
|
PostedMessage,
|
||||||
SequenceTracker,
|
SequenceTracker,
|
||||||
},
|
},
|
||||||
|
@ -207,6 +208,7 @@ mod helpers {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_secs() as u32,
|
.as_secs() as u32,
|
||||||
nonce,
|
nonce,
|
||||||
|
consistency_level: ConsistencyLevel::Confirmed as u8,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Hash data, the thing we wish to actually sign.
|
// Hash data, the thing we wish to actually sign.
|
||||||
|
@ -217,6 +219,7 @@ mod helpers {
|
||||||
v.write_u16::<BigEndian>(vaa.emitter_chain).unwrap();
|
v.write_u16::<BigEndian>(vaa.emitter_chain).unwrap();
|
||||||
v.write(&vaa.emitter_address).unwrap();
|
v.write(&vaa.emitter_address).unwrap();
|
||||||
v.write_u64::<BigEndian>(vaa.sequence).unwrap();
|
v.write_u64::<BigEndian>(vaa.sequence).unwrap();
|
||||||
|
v.write_u8(vaa.consistency_level).unwrap();
|
||||||
v.write(&vaa.payload).unwrap();
|
v.write(&vaa.payload).unwrap();
|
||||||
v.into_inner()
|
v.into_inner()
|
||||||
};
|
};
|
||||||
|
@ -293,6 +296,7 @@ mod helpers {
|
||||||
nonce,
|
nonce,
|
||||||
data,
|
data,
|
||||||
persist,
|
persist,
|
||||||
|
ConsistencyLevel::Confirmed,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -337,7 +341,6 @@ mod helpers {
|
||||||
guardian_set_version,
|
guardian_set_version,
|
||||||
VerifySignaturesData {
|
VerifySignaturesData {
|
||||||
hash: body_hash,
|
hash: body_hash,
|
||||||
initial_creation: true,
|
|
||||||
signers,
|
signers,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -364,27 +367,6 @@ mod helpers {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn upgrade_contract(
|
|
||||||
client: &RpcClient,
|
|
||||||
program: &Pubkey,
|
|
||||||
payer: &Keypair,
|
|
||||||
payload_message: Pubkey,
|
|
||||||
spill: Pubkey,
|
|
||||||
) -> Result<Signature, ClientError> {
|
|
||||||
execute(
|
|
||||||
client,
|
|
||||||
payer,
|
|
||||||
&[payer],
|
|
||||||
&[instructions::upgrade_contract(
|
|
||||||
*program,
|
|
||||||
payer.pubkey(),
|
|
||||||
payload_message,
|
|
||||||
spill,
|
|
||||||
)],
|
|
||||||
CommitmentConfig::processed(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn upgrade_guardian_set(
|
pub fn upgrade_guardian_set(
|
||||||
client: &RpcClient,
|
client: &RpcClient,
|
||||||
program: &Pubkey,
|
program: &Pubkey,
|
||||||
|
@ -412,6 +394,29 @@ mod helpers {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn upgrade_contract(
|
||||||
|
client: &RpcClient,
|
||||||
|
program: &Pubkey,
|
||||||
|
payer: &Keypair,
|
||||||
|
payload_message: Pubkey,
|
||||||
|
emitter: Pubkey,
|
||||||
|
spill: Pubkey,
|
||||||
|
sequence: u64,
|
||||||
|
) -> Result<Signature, ClientError> {
|
||||||
|
execute(
|
||||||
|
client,
|
||||||
|
payer,
|
||||||
|
&[payer],
|
||||||
|
&[instructions::upgrade_contract(
|
||||||
|
*program,
|
||||||
|
payer.pubkey(),
|
||||||
|
payload_message,
|
||||||
|
spill,
|
||||||
|
)],
|
||||||
|
CommitmentConfig::processed(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_fees(
|
pub fn set_fees(
|
||||||
client: &RpcClient,
|
client: &RpcClient,
|
||||||
program: &Pubkey,
|
program: &Pubkey,
|
||||||
|
|
|
@ -69,9 +69,11 @@ use bridge::{
|
||||||
types::{
|
types::{
|
||||||
BridgeConfig,
|
BridgeConfig,
|
||||||
BridgeData,
|
BridgeData,
|
||||||
|
ConsistencyLevel,
|
||||||
GovernancePayloadGuardianSetChange,
|
GovernancePayloadGuardianSetChange,
|
||||||
GovernancePayloadSetMessageFee,
|
GovernancePayloadSetMessageFee,
|
||||||
GovernancePayloadTransferFees,
|
GovernancePayloadTransferFees,
|
||||||
|
GovernancePayloadUpgrade,
|
||||||
GuardianSetData,
|
GuardianSetData,
|
||||||
PostedMessage,
|
PostedMessage,
|
||||||
PostedMessageData,
|
PostedMessageData,
|
||||||
|
@ -140,6 +142,7 @@ fn run_integration_tests() {
|
||||||
test_persistent_bridge_messages(&mut context);
|
test_persistent_bridge_messages(&mut context);
|
||||||
test_invalid_emitter(&mut context);
|
test_invalid_emitter(&mut context);
|
||||||
test_duplicate_messages_fail(&mut context);
|
test_duplicate_messages_fail(&mut context);
|
||||||
|
test_upgrade_contract(&mut context);
|
||||||
test_guardian_set_change(&mut context);
|
test_guardian_set_change(&mut context);
|
||||||
test_guardian_set_change_fails(&mut context);
|
test_guardian_set_change_fails(&mut context);
|
||||||
test_set_fees(&mut context);
|
test_set_fees(&mut context);
|
||||||
|
@ -444,6 +447,7 @@ fn test_invalid_emitter(context: &mut Context) {
|
||||||
nonce,
|
nonce,
|
||||||
message,
|
message,
|
||||||
false,
|
false,
|
||||||
|
ConsistencyLevel::Confirmed,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -1255,3 +1259,47 @@ fn test_transfer_total_fails(context: &mut Context) {
|
||||||
account_balance + 10_000
|
account_balance + 10_000
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_upgrade_contract(context: &mut Context) {
|
||||||
|
// Initialize a wormhole bridge on Solana to test with.
|
||||||
|
let (ref payer, ref client, ref program) = common::setup();
|
||||||
|
|
||||||
|
// Upgrade the guardian set with a new set of guardians.
|
||||||
|
let (new_public_keys, new_secret_keys) = common::generate_keys(1);
|
||||||
|
|
||||||
|
let nonce = rand::thread_rng().gen();
|
||||||
|
let emitter = Keypair::from_bytes(&GOVERNANCE_KEY).unwrap();
|
||||||
|
let sequence = context.seq.next(emitter.pubkey().to_bytes());
|
||||||
|
let message = GovernancePayloadUpgrade {
|
||||||
|
new_contract: Pubkey::new_unique(),
|
||||||
|
}
|
||||||
|
.try_to_vec()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let message_key = common::post_message(
|
||||||
|
client,
|
||||||
|
program,
|
||||||
|
payer,
|
||||||
|
&emitter,
|
||||||
|
nonce,
|
||||||
|
message.clone(),
|
||||||
|
10_000,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let (vaa, body, body_hash) = common::generate_vaa(&emitter, message.clone(), nonce, 0, 1);
|
||||||
|
common::verify_signatures(client, program, payer, body, body_hash, &context.secret, 0).unwrap();
|
||||||
|
common::post_vaa(client, program, payer, vaa).unwrap();
|
||||||
|
common::upgrade_contract(
|
||||||
|
client,
|
||||||
|
program,
|
||||||
|
payer,
|
||||||
|
message_key,
|
||||||
|
emitter.pubkey(),
|
||||||
|
Pubkey::new_unique(),
|
||||||
|
sequence,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
common::sync(client, payer);
|
||||||
|
}
|
||||||
|
|
|
@ -1189,6 +1189,12 @@ version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hex-literal"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76505e26b6ca3bbdbbb360b68472abbb80998c5fa5dc43672eca34f28258e138"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hidapi"
|
name = "hidapi"
|
||||||
version = "1.2.6"
|
version = "1.2.6"
|
||||||
|
@ -3442,10 +3448,16 @@ dependencies = [
|
||||||
"borsh",
|
"borsh",
|
||||||
"bridge",
|
"bridge",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
"hex",
|
||||||
|
"hex-literal",
|
||||||
|
"libsecp256k1",
|
||||||
"primitive-types",
|
"primitive-types",
|
||||||
|
"rand 0.7.3",
|
||||||
"rocksalt",
|
"rocksalt",
|
||||||
"sha3",
|
"sha3",
|
||||||
|
"solana-client",
|
||||||
"solana-program",
|
"solana-program",
|
||||||
|
"solana-sdk",
|
||||||
"solitaire",
|
"solitaire",
|
||||||
"solitaire-client",
|
"solitaire-client",
|
||||||
"spl-token",
|
"spl-token",
|
||||||
|
|
Loading…
Reference in New Issue