diff --git a/types/extrinsic.go b/types/extrinsic.go index ecb437f4..7b791473 100644 --- a/types/extrinsic.go +++ b/types/extrinsic.go @@ -47,8 +47,8 @@ const ( type Extrinsic struct { // Version is the encoded version flag (which encodes the raw transaction version and signing information in one byte) Version byte - // Signature is the ExtrinsicSignatureV4, it's presence depends on the Version flag - Signature ExtrinsicSignatureV4 + // Signature is the ExtrinsicSignatureV5, it's presence depends on the Version flag + Signature ExtrinsicSignatureV5 // Method is the call this extrinsic wraps Method Call } @@ -136,17 +136,21 @@ func (e *Extrinsic) Sign(signer signature.KeyringPair, o SignatureOptions) error era = ExtrinsicEra{IsImmortalEra: true} } - payload := ExtrinsicPayloadV4{ - ExtrinsicPayloadV3: ExtrinsicPayloadV3{ - Method: mb, - Era: era, - Nonce: o.Nonce, - Tip: o.Tip, - SpecVersion: o.SpecVersion, - GenesisHash: o.GenesisHash, - BlockHash: o.BlockHash, + payload := ExtrinsicPayloadV5{ + ExtrinsicPayloadV4: ExtrinsicPayloadV4{ + ExtrinsicPayloadV3: ExtrinsicPayloadV3{ + Method: mb, + Era: era, + Nonce: o.Nonce, + Tip: o.Tip, + SpecVersion: o.SpecVersion, + GenesisHash: o.GenesisHash, + BlockHash: o.BlockHash, + }, + TransactionVersion: o.TransactionVersion, }, - TransactionVersion: o.TransactionVersion, + CheckMetadataMode: o.CheckMetadataMode, + CheckMetadataHash: o.CheckMetadataHash, } signerPubKey, err := NewMultiAddressFromAccountID(signer.PublicKey) @@ -160,12 +164,13 @@ func (e *Extrinsic) Sign(signer signature.KeyringPair, o SignatureOptions) error return err } - extSig := ExtrinsicSignatureV4{ - Signer: signerPubKey, - Signature: MultiSignature{IsSr25519: true, AsSr25519: sig}, - Era: era, - Nonce: o.Nonce, - Tip: o.Tip, + extSig := ExtrinsicSignatureV5{ + Signer: signerPubKey, + Signature: MultiSignature{IsSr25519: true, AsSr25519: sig}, + Era: era, + Nonce: o.Nonce, + Tip: o.Tip, + CheckMetadataMode: o.CheckMetadataMode, } e.Signature = extSig diff --git a/types/extrinsic_examplary.go b/types/extrinsic_examplary.go index d39235cc..3c7141ce 100644 --- a/types/extrinsic_examplary.go +++ b/types/extrinsic_examplary.go @@ -16,6 +16,4 @@ package types -import "math/big" - -var ExamplaryExtrinsic = Extrinsic{Version: 0x84, Signature: ExtrinsicSignatureV4{Signer: MultiAddress{IsID: true, AsID: AccountID{0xd4, 0x35, 0x93, 0xc7, 0x15, 0xfd, 0xd3, 0x1c, 0x61, 0x14, 0x1a, 0xbd, 0x4, 0xa9, 0x9f, 0xd6, 0x82, 0x2c, 0x85, 0x58, 0x85, 0x4c, 0xcd, 0xe3, 0x9a, 0x56, 0x84, 0xe7, 0xa5, 0x6d, 0xa2, 0x7d}}, Signature: MultiSignature{IsSr25519: true, AsSr25519: Signature{0x5c, 0x77, 0x1d, 0xd5, 0x6a, 0xe0, 0xce, 0xed, 0x68, 0xd, 0xb3, 0xbb, 0x4c, 0x40, 0x7a, 0x38, 0x96, 0x99, 0x97, 0xae, 0xb6, 0xa, 0x2c, 0x62, 0x39, 0x1, 0x6, 0x2f, 0x7f, 0x8e, 0xbf, 0x2f, 0xe7, 0x73, 0x3a, 0x61, 0x3c, 0xf1, 0x6b, 0x78, 0xf6, 0x10, 0xc6, 0x52, 0x32, 0xa2, 0x3c, 0xc5, 0xce, 0x25, 0xda, 0x29, 0xa3, 0xd5, 0x84, 0x85, 0xd8, 0x7b, 0xd8, 0x3d, 0xb8, 0x18, 0x3f, 0x8}}, Era: ExtrinsicEra{IsImmortalEra: true, IsMortalEra: false, AsMortalEra: MortalEra{First: 0x0, Second: 0x0}}, Nonce: UCompact(*big.NewInt(1)), Tip: UCompact(*big.NewInt(2))}, Method: Call{CallIndex: CallIndex{SectionIndex: 0x3, MethodIndex: 0x0}, Args: Args{0xff, 0x8e, 0xaf, 0x4, 0x15, 0x16, 0x87, 0x73, 0x63, 0x26, 0xc9, 0xfe, 0xa1, 0x7e, 0x25, 0xfc, 0x52, 0x87, 0x61, 0x36, 0x93, 0xc9, 0x12, 0x90, 0x9c, 0xb2, 0x26, 0xaa, 0x47, 0x94, 0xf2, 0x6a, 0x48, 0xe5, 0x6c}}} //nolint:lll +//var ExamplaryExtrinsic = Extrinsic{Version: 0x84, Signature: ExtrinsicSignatureV4{Signer: MultiAddress{IsID: true, AsID: AccountID{0xd4, 0x35, 0x93, 0xc7, 0x15, 0xfd, 0xd3, 0x1c, 0x61, 0x14, 0x1a, 0xbd, 0x4, 0xa9, 0x9f, 0xd6, 0x82, 0x2c, 0x85, 0x58, 0x85, 0x4c, 0xcd, 0xe3, 0x9a, 0x56, 0x84, 0xe7, 0xa5, 0x6d, 0xa2, 0x7d}}, Signature: MultiSignature{IsSr25519: true, AsSr25519: Signature{0x5c, 0x77, 0x1d, 0xd5, 0x6a, 0xe0, 0xce, 0xed, 0x68, 0xd, 0xb3, 0xbb, 0x4c, 0x40, 0x7a, 0x38, 0x96, 0x99, 0x97, 0xae, 0xb6, 0xa, 0x2c, 0x62, 0x39, 0x1, 0x6, 0x2f, 0x7f, 0x8e, 0xbf, 0x2f, 0xe7, 0x73, 0x3a, 0x61, 0x3c, 0xf1, 0x6b, 0x78, 0xf6, 0x10, 0xc6, 0x52, 0x32, 0xa2, 0x3c, 0xc5, 0xce, 0x25, 0xda, 0x29, 0xa3, 0xd5, 0x84, 0x85, 0xd8, 0x7b, 0xd8, 0x3d, 0xb8, 0x18, 0x3f, 0x8}}, Era: ExtrinsicEra{IsImmortalEra: true, IsMortalEra: false, AsMortalEra: MortalEra{First: 0x0, Second: 0x0}}, Nonce: UCompact(*big.NewInt(1)), Tip: UCompact(*big.NewInt(2))}, Method: Call{CallIndex: CallIndex{SectionIndex: 0x3, MethodIndex: 0x0}, Args: Args{0xff, 0x8e, 0xaf, 0x4, 0x15, 0x16, 0x87, 0x73, 0x63, 0x26, 0xc9, 0xfe, 0xa1, 0x7e, 0x25, 0xfc, 0x52, 0x87, 0x61, 0x36, 0x93, 0xc9, 0x12, 0x90, 0x9c, 0xb2, 0x26, 0xaa, 0x47, 0x94, 0xf2, 0x6a, 0x48, 0xe5, 0x6c}}} //nolint:lll diff --git a/types/extrinsic_mode.go b/types/extrinsic_mode.go new file mode 100644 index 00000000..08484418 --- /dev/null +++ b/types/extrinsic_mode.go @@ -0,0 +1,38 @@ +package types + +import ( + "errors" + "github.com/centrifuge/go-substrate-rpc-client/v4/scale" +) + +type CheckMetadataMode byte + +var ( + CheckMetadataModeDisabled CheckMetadataMode = 0 + CheckMetadataModeEnabled CheckMetadataMode = 1 +) + +func (m CheckMetadataMode) Encode(encoder scale.Encoder) error { + switch m { + case 0: + return encoder.PushByte(0) + case 1: + return encoder.PushByte(1) + default: + return errors.New("unsupported check metadata mode") + } +} + +type CheckMetadataHash struct { + Hash Option[H256] +} + +func (c CheckMetadataHash) Encode(encoder *scale.Encoder) error { + if c.Hash.HasValue() { + _, hash := c.Hash.Unwrap() + + return encoder.Encode(hash) + } + + return encoder.PushByte(0) +} diff --git a/types/extrinsic_payload.go b/types/extrinsic_payload.go index 2a9894f8..38424a18 100644 --- a/types/extrinsic_payload.go +++ b/types/extrinsic_payload.go @@ -160,3 +160,74 @@ func (e ExtrinsicPayloadV4) Encode(encoder scale.Encoder) error { func (e *ExtrinsicPayloadV4) Decode(decoder scale.Decoder) error { return fmt.Errorf("decoding of ExtrinsicPayloadV4 is not supported") } + +type ExtrinsicPayloadV5 struct { + ExtrinsicPayloadV4 + CheckMetadataMode CheckMetadataMode + CheckMetadataHash CheckMetadataHash +} + +// Sign the extrinsic payload with the given derivation path +func (e ExtrinsicPayloadV5) Sign(signer signature.KeyringPair) (Signature, error) { + b, err := codec.Encode(e) + if err != nil { + return Signature{}, err + } + + sig, err := signature.Sign(b, signer.URI) + return NewSignature(sig), err +} + +func (e ExtrinsicPayloadV5) Encode(encoder scale.Encoder) error { + err := encoder.Encode(e.Method) + if err != nil { + return err + } + + err = encoder.Encode(e.Era) + if err != nil { + return err + } + + err = encoder.Encode(e.Nonce) + if err != nil { + return err + } + + err = encoder.Encode(e.CheckMetadataMode) + if err != nil { + return err + } + + err = encoder.Encode(e.Tip) + if err != nil { + return err + } + + err = encoder.Encode(e.SpecVersion) + if err != nil { + return err + } + + err = encoder.Encode(e.TransactionVersion) + if err != nil { + return err + } + + err = encoder.Encode(e.GenesisHash) + if err != nil { + return err + } + + err = encoder.Encode(e.BlockHash) + if err != nil { + return err + } + + err = encoder.Encode(e.CheckMetadataHash) + if err != nil { + return err + } + + return nil +} diff --git a/types/extrinsic_signature.go b/types/extrinsic_signature.go index 3f8cc5c3..b5b79596 100644 --- a/types/extrinsic_signature.go +++ b/types/extrinsic_signature.go @@ -32,12 +32,23 @@ type ExtrinsicSignatureV4 struct { Tip UCompact // extra via balances::TakeFees (Compact where Balance is u128)) } +type ExtrinsicSignatureV5 struct { + Signer MultiAddress + Signature MultiSignature + Era ExtrinsicEra // extra via system::CheckEra + Nonce UCompact // extra via system::CheckNonce (Compact where Index is u32)) + Tip UCompact // extra via balances::TakeFees (Compact where Balance is u128)) + CheckMetadataMode CheckMetadataMode // additional via frame_metadata_hash_extension::CheckMetadataHash +} + type SignatureOptions struct { - Era ExtrinsicEra // extra via system::CheckEra - Nonce UCompact // extra via system::CheckNonce (Compact where Index is u32) - Tip UCompact // extra via balances::TakeFees (Compact where Balance is u128) - SpecVersion U32 // additional via system::CheckSpecVersion - GenesisHash Hash // additional via system::CheckGenesis - BlockHash Hash // additional via system::CheckEra - TransactionVersion U32 // additional via system::CheckTxVersion + Era ExtrinsicEra // extra via system::CheckEra + Nonce UCompact // extra via system::CheckNonce (Compact where Index is u32) + Tip UCompact // extra via balances::TakeFees (Compact where Balance is u128) + SpecVersion U32 // additional via system::CheckSpecVersion + GenesisHash Hash // additional via system::CheckGenesis + BlockHash Hash // additional via system::CheckEra + TransactionVersion U32 // additional via system::CheckTxVersion + CheckMetadataMode CheckMetadataMode // additional via frame_metadata_hash_extension::CheckMetadataHash + CheckMetadataHash CheckMetadataHash // additional via frame_metadata_hash_extension::CheckMetadataHash} }