Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for MultiAddress #128

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions teste2e/author_submit_extrinsic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func TestChain_SubmitExtrinsic(t *testing.T) {
panic(err)
}

bob, err := types.NewAddressFromHexAccountID("0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48")
bob, err := types.NewMultiAddressFromHexAccountID("0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48")
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -133,12 +133,12 @@ func TestChain_SubmitExtrinsic(t *testing.T) {
for i := uint32(0); i < 4; i++ {
o := types.SignatureOptions{
// BlockHash: blockHash,
BlockHash: genesisHash, // BlockHash needs to == GenesisHash if era is immortal. // TODO: add an error?
Era: era,
GenesisHash: genesisHash,
Nonce: types.NewUCompactFromUInt(uint64(nonce + i)),
SpecVersion: rv.SpecVersion,
Tip: types.NewUCompactFromUInt(0),
BlockHash: genesisHash, // BlockHash needs to == GenesisHash if era is immortal. // TODO: add an error?
Era: era,
GenesisHash: genesisHash,
Nonce: types.NewUCompactFromUInt(uint64(nonce + i)),
SpecVersion: rv.SpecVersion,
Tip: types.NewUCompactFromUInt(0),
TransactionVersion: rv.TransactionVersion,
}

Expand Down
2 changes: 1 addition & 1 deletion types/extrinsic.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func (e *Extrinsic) Sign(signer signature.KeyringPair, o SignatureOptions) error
TransactionVersion: o.TransactionVersion,
}

signerPubKey := NewAddressFromAccountID(signer.PublicKey)
signerPubKey := NewMultiAddressFromAccountID(signer.PublicKey)

sig, err := payload.Sign(signer)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion types/extrinsic_examplary.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ package types

import "math/big"

var ExamplaryExtrinsic = Extrinsic{Version: 0x84, Signature: ExtrinsicSignatureV4{Signer: Address{IsAccountID: true, AsAccountID: 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}, IsAccountIndex: false, AsAccountIndex: 0x0}, 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
2 changes: 1 addition & 1 deletion types/extrinsic_signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type ExtrinsicSignatureV3 struct {
}

type ExtrinsicSignatureV4 struct {
Copy link
Contributor Author

@vgeddes vgeddes Jan 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency with polkadot-js/types, I've not added a ExtrinsicSignatureV5 and have just updated the V4 struct.

Signer Address
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will break for all the chains without the multiaddress.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, there are a couple of chains also using substrate master who for reasons of simplicity prefer not to use MultiAddress.

We could this solve this by making ExtrinsicSignatureV4.Signer an interface type:

type ExtrinsicSignatureV4 {
    Signer interface{}
    ...
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could abstract out the Signerwith Address and MultiAddress as default implementations. This wouldn't break the compatibility

Signer MultiAddress
Signature MultiSignature
Era ExtrinsicEra // extra via system::CheckEra
Nonce UCompact // extra via system::CheckNonce (Compact<Index> where Index is u32))
Expand Down
125 changes: 125 additions & 0 deletions types/multi_address.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package types

import (
"fmt"

"github.com/centrifuge/go-substrate-rpc-client/v2/scale"
)

type MultiAddress struct {
IsID bool
AsID AccountID
IsIndex bool
AsIndex AccountIndex
IsRaw bool
AsRaw []byte
IsAddress32 bool
AsAddress32 [32]byte
IsAddress20 bool
AsAddress20 [20]byte
}

// NewMultiAddressFromAccountID creates an Address from the given AccountID (public key)
func NewMultiAddressFromAccountID(b []byte) MultiAddress {
return MultiAddress{
IsID: true,
AsID: NewAccountID(b),
}
}

// NewMultiAddressFromHexAccountID creates an Address from the given hex string that contains an AccountID (public key)
func NewMultiAddressFromHexAccountID(str string) (MultiAddress, error) {
b, err := HexDecodeString(str)
if err != nil {
return MultiAddress{}, err
}
return NewMultiAddressFromAccountID(b), nil
}

func (m MultiAddress) Encode(encoder scale.Encoder) error {
var err error
switch {
case m.IsID:
err = encoder.PushByte(0)
if err != nil {
return err
}
err = encoder.Encode(m.AsID)
if err != nil {
return err
}
case m.IsIndex:
err = encoder.PushByte(1)
if err != nil {
return err
}
err = encoder.Encode(m.AsIndex)
if err != nil {
return err
}
case m.IsRaw:
err = encoder.PushByte(2)
if err != nil {
return err
}
err = encoder.Encode(m.AsRaw)
if err != nil {
return err
}
case m.IsAddress32:
err = encoder.PushByte(3)
if err != nil {
return err
}
err = encoder.Encode(m.AsAddress32)
if err != nil {
return err
}
case m.IsAddress20:
err = encoder.PushByte(4)
if err != nil {
return err
}
err = encoder.Encode(m.AsAddress20)
if err != nil {
return err
}
default:
return fmt.Errorf("Invalid variant for MultiAddress")
}

return nil
}

func (m MultiAddress) Decode(decoder scale.Decoder) error {
tag, err := decoder.ReadOneByte()
if err != nil {
return err
}

switch tag {
case 0:
m.IsID = true
err = decoder.Decode(&m.AsID)
case 1:
m.IsIndex = true
err = decoder.Decode(&m.AsIndex)
case 2:
m.IsRaw = true
err = decoder.Decode(&m.AsRaw)
case 3:
m.IsAddress32 = true
err = decoder.Decode(&m.AsAddress32)
case 4:
m.IsAddress20 = true
err = decoder.Decode(&m.AsAddress20)
default:
return fmt.Errorf("Invalid variant for MultiAddress")
}

if err != nil {
return err
}

return nil
}