Fix Governance Headers

Change-Id: If2026ff4a6107327f69c5d0675a736e6ab87f1bd
This commit is contained in:
Reisen 2021-07-20 15:40:56 +00:00 committed by Hendrik Hofstadt
parent 1992684351
commit 99c3e40968
9 changed files with 122 additions and 33 deletions

View File

@ -57,7 +57,7 @@ where
#[derive(FromAccounts)]
pub struct UpgradeContract<'b> {
/// Payer for account creation (vaa-claim)
pub payer: Signer<Info<'b>>,
pub payer: Mut<Signer<Info<'b>>>,
/// Upgrade VAA
pub vaa: ClaimableVAA<'b, GovernancePayloadUpgrade>,
@ -91,8 +91,10 @@ pub fn upgrade_contract(
accs.spill.key,
);
let _seeds = accs.upgrade_authority.self_seeds(None);
invoke_signed(&upgrade_ix, ctx.accounts, &[])?;
let seeds = accs.upgrade_authority.self_bumped_seeds(None, ctx.program_id);
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(())
}
@ -138,6 +140,7 @@ pub fn upgrade_guardian_set(
_data: UpgradeGuardianSetData,
) -> Result<()> {
verify_claim(&accs.vaa)?;
accs.guardian_set_old.verify_derivation(
ctx.program_id,
&GuardianSetDerivationData {

View File

@ -62,8 +62,6 @@ pub struct VerifySignaturesData {
pub hash: [u8; 32],
/// instruction indices of signers (-1 for missing)
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

View File

@ -240,10 +240,10 @@ pub fn upgrade_contract(
accounts: vec![
AccountMeta::new(payer, true),
AccountMeta::new(payload_message, false),
AccountMeta::new_readonly(payload_message, false),
AccountMeta::new(claim, false),
AccountMeta::new(upgrade_authority, false),
AccountMeta::new(spill, false),
AccountMeta::new_readonly(upgrade_authority, false),
AccountMeta::new_readonly(spill, false),
],
data: (crate::instruction::Instruction::UpgradeContract, UpgradeContractData {})

View File

@ -251,6 +251,7 @@ where
{
fn deserialize(buf: &mut &[u8]) -> Result<Self, SolitaireError> {
let mut c = Cursor::new(buf);
Self::check_governance_header(&mut c)?;
let new_index = c.read_u32::<BigEndian>()?;
@ -270,7 +271,7 @@ where
}
impl DeserializeGovernancePayload for GovernancePayloadGuardianSetChange {
const MODULE: &'static str = "CORE";
const MODULE: &'static str = "Core";
const ACTION: u8 = 1;
}
@ -279,13 +280,19 @@ pub struct GovernancePayloadUpgrade {
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
where
Self: DeserializeGovernancePayload,
{
fn deserialize(buf: &mut &[u8]) -> Result<Self, SolitaireError> {
let mut c = Cursor::new(buf);
Self::check_governance_header(&mut c)?;
let mut addr = [0u8; 32];
@ -329,6 +336,7 @@ where
{
fn deserialize(buf: &mut &[u8]) -> Result<Self, SolitaireError> {
let mut c = Cursor::new(buf);
Self::check_governance_header(&mut c)?;
let mut fee_data: [u8; 32] = [0; 32];
c.read_exact(&mut fee_data)?;
@ -374,6 +382,7 @@ where
{
fn deserialize(buf: &mut &[u8]) -> Result<Self, SolitaireError> {
let mut c = Cursor::new(buf);
Self::check_governance_header(&mut c)?;
let mut amount_data: [u8; 32] = [0; 32];
c.read_exact(&mut amount_data)?;

View File

@ -39,13 +39,27 @@ use std::{
ops::Deref,
};
pub trait SerializePayload: Sized {
pub trait SerializePayload: Sized + DeserializeGovernancePayload {
fn serialize<W: Write>(&self, writer: &mut W) -> std::result::Result<(), SolitaireError>;
fn try_to_vec(&self) -> std::result::Result<Vec<u8>, SolitaireError> {
let mut result = Vec::with_capacity(256);
self.write_governance_header(&mut result)?;
self.serialize(&mut 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 {

View File

@ -75,6 +75,7 @@ use bridge::{
instructions,
types::{
BridgeConfig,
ConsistencyLevel,
PostedMessage,
SequenceTracker,
},
@ -207,6 +208,7 @@ mod helpers {
.unwrap()
.as_secs() as u32,
nonce,
consistency_level: ConsistencyLevel::Confirmed as u8,
};
// 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(&vaa.emitter_address).unwrap();
v.write_u64::<BigEndian>(vaa.sequence).unwrap();
v.write_u8(vaa.consistency_level).unwrap();
v.write(&vaa.payload).unwrap();
v.into_inner()
};
@ -293,6 +296,7 @@ mod helpers {
nonce,
data,
persist,
ConsistencyLevel::Confirmed,
)
.unwrap();
@ -337,7 +341,6 @@ mod helpers {
guardian_set_version,
VerifySignaturesData {
hash: body_hash,
initial_creation: true,
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(
client: &RpcClient,
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(
client: &RpcClient,
program: &Pubkey,

View File

@ -69,9 +69,11 @@ use bridge::{
types::{
BridgeConfig,
BridgeData,
ConsistencyLevel,
GovernancePayloadGuardianSetChange,
GovernancePayloadSetMessageFee,
GovernancePayloadTransferFees,
GovernancePayloadUpgrade,
GuardianSetData,
PostedMessage,
PostedMessageData,
@ -140,6 +142,7 @@ fn run_integration_tests() {
test_persistent_bridge_messages(&mut context);
test_invalid_emitter(&mut context);
test_duplicate_messages_fail(&mut context);
test_upgrade_contract(&mut context);
test_guardian_set_change(&mut context);
test_guardian_set_change_fails(&mut context);
test_set_fees(&mut context);
@ -444,6 +447,7 @@ fn test_invalid_emitter(context: &mut Context) {
nonce,
message,
false,
ConsistencyLevel::Confirmed,
)
.unwrap();
@ -1255,3 +1259,47 @@ fn test_transfer_total_fails(context: &mut Context) {
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);
}

View File

@ -1189,6 +1189,12 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hex-literal"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76505e26b6ca3bbdbbb360b68472abbb80998c5fa5dc43672eca34f28258e138"
[[package]]
name = "hidapi"
version = "1.2.6"
@ -3442,10 +3448,16 @@ dependencies = [
"borsh",
"bridge",
"byteorder",
"hex",
"hex-literal",
"libsecp256k1",
"primitive-types",
"rand 0.7.3",
"rocksalt",
"sha3",
"solana-client",
"solana-program",
"solana-sdk",
"solitaire",
"solitaire-client",
"spl-token",