node: add BridgeUpgradeContract governance VAA
Example VAA produced by the template: (*vaa.VAA)(0xc0004f4510)({ Version: (uint8) 1, GuardianSetIndex: (uint32) 0, Signatures: ([]*vaa.Signature) (len=1 cap=1) { (*vaa.Signature)(0xc0003b0370)({ Index: (uint8) 0, Signature: (vaa.SignatureData) (len=65 cap=65) 0f97ec9093c21ccc4ce544898ed5c21b66ab4c90be894642fbb43474ed9fb48a26d6e12f3397b9fdab160fee64e797d26599a2a9d81a4bf4bc98970b5fa5122501 }) }, Timestamp: (time.Time) 1970-01-01 00:00:00 +0000 UTC, Nonce: (uint32) 1375049878, Sequence: (uint64) 3557202656914991802, ConsistencyLevel: (uint8) 32, EmitterChain: (vaa.ChainID) solana, EmitterAddress: (vaa.Address) (len=32 cap=32) 0000000000000000000000000000000000000000000000000000000000000004, Payload: ([]uint8) (len=67 cap=1000) { 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000010 00 00 00 00 00 54 6f 6b 65 6e 42 72 69 64 67 65 |.....TokenBridge| 00000020 02 00 05 00 00 00 00 00 00 00 00 00 00 00 00 02 |................| 00000030 90 fb 16 72 08 af 45 5b b1 37 78 01 63 b7 b7 a9 |...r..E[.7x.c...| 00000040 a1 0c 16 |...| } }) Change-Id: Ibe95db01e1bc0a9c36e1be06920a389db886fdd1
This commit is contained in:
parent
e6aded4fdc
commit
6fd6cb9f02
|
@ -122,6 +122,35 @@ func tokenBridgeRegisterChain(req *nodev1.BridgeRegisterChain, guardianSetIndex
|
|||
return v, nil
|
||||
}
|
||||
|
||||
// tokenBridgeUpgradeContract converts a nodev1.TokenBridgeRegisterChain message to its canonical VAA representation.
|
||||
// Returns an error if the data is invalid.
|
||||
func tokenBridgeUpgradeContract(req *nodev1.BridgeUpgradeContract, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
|
||||
if req.TargetChainId > math.MaxUint16 {
|
||||
return nil, errors.New("invalid target_chain_id")
|
||||
}
|
||||
|
||||
b, err := hex.DecodeString(req.NewContract)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid new contract address (expected hex)")
|
||||
}
|
||||
|
||||
if len(b) != 32 {
|
||||
return nil, errors.New("invalid new contract address (expected 32 bytes)")
|
||||
}
|
||||
|
||||
newContract := vaa.Address{}
|
||||
copy(newContract[:], b)
|
||||
|
||||
v := vaa.CreateGovernanceVAA(nonce, sequence, guardianSetIndex,
|
||||
vaa.BodyTokenBridgeUpgradeContract{
|
||||
Module: req.Module,
|
||||
TargetChainID: vaa.ChainID(req.TargetChainId),
|
||||
NewContract: newContract,
|
||||
}.Serialize())
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (s *nodePrivilegedService) InjectGovernanceVAA(ctx context.Context, req *nodev1.InjectGovernanceVAARequest) (*nodev1.InjectGovernanceVAAResponse, error) {
|
||||
s.logger.Info("governance VAA injected via admin socket", zap.String("request", req.String()))
|
||||
|
||||
|
@ -136,6 +165,8 @@ func (s *nodePrivilegedService) InjectGovernanceVAA(ctx context.Context, req *no
|
|||
v, err = adminContractUpgradeToVAA(payload.ContractUpgrade, req.CurrentSetIndex, req.Nonce, req.Sequence)
|
||||
case *nodev1.InjectGovernanceVAARequest_BridgeRegisterChain:
|
||||
v, err = tokenBridgeRegisterChain(payload.BridgeRegisterChain, req.CurrentSetIndex, req.Nonce, req.Sequence)
|
||||
case *nodev1.InjectGovernanceVAARequest_BridgeContractUpgrade:
|
||||
v, err = tokenBridgeUpgradeContract(payload.BridgeContractUpgrade, req.CurrentSetIndex, req.Nonce, req.Sequence)
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported VAA type: %T", payload))
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ func init() {
|
|||
TemplateCmd.AddCommand(AdminClientGuardianSetTemplateCmd)
|
||||
TemplateCmd.AddCommand(AdminClientContractUpgradeTemplateCmd)
|
||||
TemplateCmd.AddCommand(AdminClientTokenBridgeRegisterChainCmd)
|
||||
TemplateCmd.AddCommand(AdminClientTokenBridgeUpgradeContractCmd)
|
||||
}
|
||||
|
||||
var TemplateCmd = &cobra.Command{
|
||||
|
@ -52,6 +53,13 @@ var AdminClientTokenBridgeRegisterChainCmd = &cobra.Command{
|
|||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
|
||||
var AdminClientTokenBridgeUpgradeContractCmd = &cobra.Command{
|
||||
Use: "token-bridge-upgrade-contract [FILENAME]",
|
||||
Short: "Generate an empty token bridge contract upgrade template at specified path (offline)",
|
||||
Run: runTokenBridgeUpgradeContractTemplate,
|
||||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
|
||||
func runGuardianSetTemplate(cmd *cobra.Command, args []string) {
|
||||
path := args[0]
|
||||
|
||||
|
@ -136,3 +144,30 @@ func runTokenBridgeRegisterChainTemplate(cmd *cobra.Command, args []string) {
|
|||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func runTokenBridgeUpgradeContractTemplate(cmd *cobra.Command, args []string) {
|
||||
path := args[0]
|
||||
|
||||
m := &nodev1.InjectGovernanceVAARequest{
|
||||
CurrentSetIndex: uint32(*templateGuardianIndex),
|
||||
Sequence: rand.Uint64(),
|
||||
Nonce: rand.Uint32(),
|
||||
Payload: &nodev1.InjectGovernanceVAARequest_BridgeContractUpgrade{
|
||||
BridgeContractUpgrade: &nodev1.BridgeUpgradeContract{
|
||||
Module: "TokenBridge",
|
||||
TargetChainId: 5,
|
||||
NewContract: "0000000000000000000000000290FB167208Af455bB137780163b7B7a9a10C16",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(path, b, 0640)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,13 @@ type (
|
|||
ChainID ChainID
|
||||
EmitterAddress Address
|
||||
}
|
||||
|
||||
// BodyTokenBridgeUpgradeContract is a governance message to upgrade the token bridge.
|
||||
BodyTokenBridgeUpgradeContract struct {
|
||||
Module string
|
||||
TargetChainID ChainID
|
||||
NewContract Address
|
||||
}
|
||||
)
|
||||
|
||||
func (b BodyContractUpgrade) Serialize() []byte {
|
||||
|
@ -87,3 +94,25 @@ func (r BodyTokenBridgeRegisterChain) Serialize() []byte {
|
|||
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func (r BodyTokenBridgeUpgradeContract) Serialize() []byte {
|
||||
if len(r.Module) > 32 {
|
||||
panic("module longer than 32 byte")
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
|
||||
// Write token bridge header
|
||||
for i := 0; i < (32 - len(r.Module)); i++ {
|
||||
buf.WriteByte(0x00)
|
||||
}
|
||||
buf.Write([]byte(r.Module))
|
||||
// Write action ID
|
||||
MustWrite(buf, binary.BigEndian, uint8(2))
|
||||
// Write target chain
|
||||
MustWrite(buf, binary.BigEndian, r.TargetChainID)
|
||||
// Write emitter address of chain to be registered
|
||||
buf.Write(r.NewContract[:])
|
||||
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ message InjectGovernanceVAARequest {
|
|||
// Token bridge and NFT module
|
||||
|
||||
BridgeRegisterChain bridge_register_chain = 12;
|
||||
BridgeUpgradeContract bridge_contract_upgrade = 13;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,6 +98,17 @@ message ContractUpgrade {
|
|||
bytes new_contract = 2;
|
||||
}
|
||||
|
||||
message BridgeUpgradeContract {
|
||||
// Module identifier of the token or NFT bridge (typically "TokenBridge" or "NFTBridge").
|
||||
string module = 1;
|
||||
|
||||
// ID of the chain where the bridge contract should be updated (uint16).
|
||||
uint32 target_chain_id = 2;
|
||||
|
||||
// Address of the new program/contract.
|
||||
string new_contract = 3;
|
||||
}
|
||||
|
||||
message FindMissingMessagesRequest {
|
||||
// Emitter chain ID to iterate.
|
||||
uint32 emitter_chain = 1;
|
||||
|
|
Loading…
Reference in New Issue