diff --git a/lazer/Cargo.lock b/lazer/Cargo.lock index 319447ca97..e0da52bb3e 100644 --- a/lazer/Cargo.lock +++ b/lazer/Cargo.lock @@ -3882,7 +3882,7 @@ dependencies = [ [[package]] name = "pyth-lazer-publisher-sdk" -version = "0.1.3" +version = "0.1.4" dependencies = [ "anyhow", "fs-err", diff --git a/lazer/publisher_sdk/proto/governance_instruction.proto b/lazer/publisher_sdk/proto/governance_instruction.proto index d03e56f475..9f655a32e6 100644 --- a/lazer/publisher_sdk/proto/governance_instruction.proto +++ b/lazer/publisher_sdk/proto/governance_instruction.proto @@ -13,9 +13,15 @@ package pyth_lazer_transaction; // Representation of a complete governance instruction. This value will be signed // by a governance source. +// +// If the governance source is SingleEd25519, this message will be the payload of LazerTransaction. +// +// If the governance source is Wormhole emitter, this message will be the body of the GovernancePayload which +// is the VAA message Pyth governance sends to Wormhole. The GovernancePayload follows xc-admin spec +// and looks like so: +// +// You can find the xc-admin spec in: ../../../governance/xc_admin/packages/xc_admin_common/src/governance_payload message GovernanceInstruction { - // [required] Governance source that signed this instruction. - optional GovernanceSource source = 1; // Action requested by this instruction. For the instruction to be accepted, all directives // must be successfully applied. In case of any failure, the whole instruction is reverted. // However, note that if the instruction targets multiple (or all) shards, each shard will @@ -29,14 +35,15 @@ message GovernanceInstruction { // is greater than the specified value. After `max_execution_timestamp` is in the past, // it will no longer be possible to execute this instruction. optional google.protobuf.Timestamp max_execution_timestamp = 4; - // [required] Sequence number of this instruction. It must be greater than 0. - // It must always be increasing, but not required to be - // strictly sequential (i.e. gaps are allowed). Each shard separately keeps track of the last executed - // governance instruction and will reject instructions with the same or smaller sequence no. - // Note that if instructions are received out of order, some of them may become permanently - // rejected (e.g. if instruction #3 has been successfully processed before instruction #2 was observed, - // #2 will always be rejected). - // Sequence numbers are assigned and tracked separately for each governance source. + // [optional] Sequence number of this instruction. Required for SingleEd25519 governance source + // and optional for WomrholeEmitter governance source (because Wormhole has its own sequence + // numbers). If set, it must be greater than 0, and always be increasing, but not required to be + // strictly sequential (i.e. gaps are allowed). Each shard separately keeps track of the last + // executed governance instruction and will reject instructions with the same or smaller + // sequence no. Note that if instructions are received out of order, some of them may become + // permanently rejected (e.g. if instruction #3 has been successfully processed before + // instruction #2 was observed, #2 will always be rejected). Sequence numbers are assigned and + // tracked separately for each governance source. optional uint32 governance_sequence_no = 5; } @@ -155,10 +162,17 @@ message GovernanceSource { optional bytes public_key = 1; } + message WormholeEmitter { + // [required] Wormhole emitter address. + optional bytes address = 1; + // [required] Wormhole emitter chain ID. Restricted to uint16. + optional uint32 chain_id = 2; + } + // [required] oneof source { SingleEd25519 single_ed25519 = 1; - // TODO: wormhole source goes here. + WormholeEmitter wormhole_emitter = 2; } } @@ -290,8 +304,8 @@ message SetPublisherActive { // Feed is inactive when added, meaning that it will be available to publishers but not to consumers. message AddFeed { - // [required] ID of the price feed. Must be unique (within the shard). - optional uint32 price_feed_id = 1; + // [required] ID of the feed. Must be unique (within the shard). + optional uint32 feed_id = 1; // [required] Feed metadata. Some properties are required (name, exponent, etc.). // Known properties must have the expected type. // Additional arbitrary properties are allowed. @@ -303,7 +317,7 @@ message AddFeed { message UpdateFeed { // [required] ID of the feed that is being updated. Rejects if there is no such feed. - optional uint32 price_feed_id = 1; + optional uint32 feed_id = 1; // [required] // Note: when adding a new variant here, update `Permissions` as well. oneof action { @@ -347,4 +361,3 @@ message DeactivateFeed { // governance instruction is processed. optional google.protobuf.Timestamp deactivation_timestamp = 1; } - diff --git a/lazer/publisher_sdk/proto/pyth_lazer_transaction.proto b/lazer/publisher_sdk/proto/pyth_lazer_transaction.proto index 39798dcd46..f755c4b7a6 100644 --- a/lazer/publisher_sdk/proto/pyth_lazer_transaction.proto +++ b/lazer/publisher_sdk/proto/pyth_lazer_transaction.proto @@ -15,7 +15,18 @@ message SignedLazerTransaction { // [required] signature with public key optional SignatureData signature_data = 1; - // [required] lazer transaction encoded as bytes through protobuf + // [required] lazer transaction payload encoded as bytes. + // + // If the signature data is a Ed25519SignatureData, the payload is the encoded + // LazerTransaction protobuf message. + // + // If the signature data is a WormholeMultiSigData, the payload is the encoded + // Wormhole VAA body. The Wormhole VAA can be any of the following: + // 1. A governance message from Pyth that updates Lazer state (e.g. a new feed) which + // is an ecoded GovernancePayload according to xc-admin spec which contains the + // encoded GovernanceInstruction protobuf message. + // 2. A governance message from Wormhole that updates Wormhole guardian set which follows + // the Wormhole specification. optional bytes payload = 2; } @@ -27,9 +38,35 @@ message SignatureData { // [required] type of signature, which determines included data needed for verifying oneof data { Ed25519SignatureData ed25519 = 1; + WormholeMultiSigData wormholeMultiSig = 2; }; } +// Wormhole multisig data which is the proto encoding of the VAA +// header taken from the following wire format: +// https://github.com/wormhole-foundation/wormhole/blob/main/whitepapers/0001_generic_message_passing.md +message WormholeMultiSigData { + // [required] Protocol version of the entire VAA. + optional int32 version = 1; + + // [required] GuardianSetIndex is the index of the guardian set that signed + // this VAA. Signatures are verified against the public keys in the + // guardian set. + optional int32 guardianSetIndex = 2; + + // Signatures contain a list of signatures made by the guardian set. + repeated WormholeGuardianSignature signatures = 3; +} + +// Wormhole multisig signature +message WormholeGuardianSignature { + // [required] Index of the guardian that signed the transaction + optional int32 index = 1; + + // [required] 65 byte eccdsa signature + optional bytes signature = 2; +} + // ED25519 style signature. Should include a single signature and a single public key // Signature will be verified using public key after determining public key is valid message Ed25519SignatureData { diff --git a/lazer/publisher_sdk/rust/Cargo.toml b/lazer/publisher_sdk/rust/Cargo.toml index 665a3c22d0..8ee0a53845 100644 --- a/lazer/publisher_sdk/rust/Cargo.toml +++ b/lazer/publisher_sdk/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pyth-lazer-publisher-sdk" -version = "0.1.3" +version = "0.1.4" edition = "2021" description = "Pyth Lazer Publisher SDK types." license = "Apache-2.0"