github.com/stafiprotocol/go-substrate-rpc-client@v1.4.7/types/extrinsic.go (about)

     1  // Go Substrate RPC Client (GSRPC) provides APIs and types around Polkadot and any Substrate-based chain RPC calls
     2  //
     3  // Copyright 2020 Stafi Protocol
     4  //
     5  // Licensed under the Apache License, Version 2.0 (the "License");
     6  // you may not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  
    17  package types
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/json"
    22  	"fmt"
    23  	"io"
    24  	"math/big"
    25  	"strings"
    26  
    27  	"github.com/stafiprotocol/go-substrate-rpc-client/pkg/scale"
    28  	"github.com/stafiprotocol/go-substrate-rpc-client/signature"
    29  )
    30  
    31  const (
    32  	ExtrinsicBitSigned      = 0x80
    33  	ExtrinsicBitUnsigned    = 0
    34  	ExtrinsicUnmaskVersion  = 0x7f
    35  	ExtrinsicDefaultVersion = 1
    36  	ExtrinsicVersionUnknown = 0 // v0 is unknown
    37  	ExtrinsicVersion1       = 1
    38  	ExtrinsicVersion2       = 2
    39  	ExtrinsicVersion3       = 3
    40  	ExtrinsicVersion4       = 4
    41  )
    42  
    43  // Extrinsic is a piece of Args bundled into a block that expresses something from the "external" (i.e. off-chain)
    44  // world. There are, broadly speaking, two types of extrinsic: transactions (which tend to be signed) and
    45  // inherents (which don't).
    46  type Extrinsic struct {
    47  	// Version is the encoded version flag (which encodes the raw transaction version and signing information in one byte)
    48  	Version byte
    49  	// Signature is the ExtrinsicSignatureV4, it's presence depends on the Version flag
    50  	Signature ExtrinsicSignatureV4
    51  	// Method is the call this extrinsic wraps
    52  	Method Call
    53  }
    54  
    55  // NewExtrinsic creates a new Extrinsic from the provided Call
    56  func NewExtrinsic(c Call) Extrinsic {
    57  	return Extrinsic{
    58  		Version: ExtrinsicVersion4,
    59  		Method:  c,
    60  	}
    61  }
    62  
    63  // UnmarshalJSON fills Extrinsic with the JSON encoded byte array given by bz
    64  func (e *Extrinsic) UnmarshalJSON(bz []byte) error {
    65  	var tmp string
    66  	if err := json.Unmarshal(bz, &tmp); err != nil {
    67  		return err
    68  	}
    69  
    70  	// HACK 11 Jan 2019 - before https://github.com/paritytech/substrate/pull/1388
    71  	// extrinsics didn't have the length, cater for both approaches. This is very
    72  	// inconsistent with any other `Vec<u8>` implementation
    73  	var l UCompact
    74  	err := DecodeFromHexString(tmp, &l)
    75  	if err != nil {
    76  		return err
    77  	}
    78  
    79  	prefix, err := EncodeToHexString(l)
    80  	if err != nil {
    81  		return err
    82  	}
    83  
    84  	// determine whether length prefix is there
    85  	if strings.HasPrefix(tmp, prefix) {
    86  		return DecodeFromHexString(tmp, e)
    87  	}
    88  
    89  	// not there, prepend with compact encoded length prefix
    90  	dec, err := HexDecodeString(tmp)
    91  	if err != nil {
    92  		return err
    93  	}
    94  	length := NewUCompactFromUInt(uint64(len(dec)))
    95  	bprefix, err := EncodeToBytes(length)
    96  	if err != nil {
    97  		return err
    98  	}
    99  	prefixed := append(bprefix, dec...)
   100  	return DecodeFromBytes(prefixed, e)
   101  }
   102  
   103  // MarshalJSON returns a JSON encoded byte array of Extrinsic
   104  func (e Extrinsic) MarshalJSON() ([]byte, error) {
   105  	s, err := EncodeToHexString(e)
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  	return json.Marshal(s)
   110  }
   111  
   112  // IsSigned returns true if the extrinsic is signed
   113  func (e Extrinsic) IsSigned() bool {
   114  	return e.Version&ExtrinsicBitSigned == ExtrinsicBitSigned
   115  }
   116  
   117  // Type returns the raw transaction version (not flagged with signing information)
   118  func (e Extrinsic) Type() uint8 {
   119  	return e.Version & ExtrinsicUnmaskVersion
   120  }
   121  
   122  // Sign adds a signature to the extrinsic
   123  func (e *Extrinsic) Sign(signer signature.KeyringPair, o SignatureOptions) error {
   124  	if e.Type() != ExtrinsicVersion4 {
   125  		return fmt.Errorf("unsupported extrinsic version: %v (isSigned: %v, type: %v)", e.Version, e.IsSigned(), e.Type())
   126  	}
   127  
   128  	mb, err := EncodeToBytes(e.Method)
   129  	if err != nil {
   130  		return err
   131  	}
   132  
   133  	era := o.Era
   134  	if !o.Era.IsMortalEra {
   135  		era = ExtrinsicEra{IsImmortalEra: true}
   136  	}
   137  
   138  	payload := ExtrinsicPayloadV4{
   139  		ExtrinsicPayloadV3: ExtrinsicPayloadV3{
   140  			Method:      mb,
   141  			Era:         era,
   142  			Nonce:       o.Nonce,
   143  			Tip:         o.Tip,
   144  			SpecVersion: o.SpecVersion,
   145  			GenesisHash: o.GenesisHash,
   146  			BlockHash:   o.BlockHash,
   147  		},
   148  		TransactionVersion: o.TransactionVersion,
   149  	}
   150  
   151  	signerPubKey := NewAddressFromAccountID(signer.PublicKey)
   152  
   153  	sig, err := payload.Sign(signer)
   154  	if err != nil {
   155  		return err
   156  	}
   157  
   158  	extSig := ExtrinsicSignatureV4{
   159  		Signer:    signerPubKey,
   160  		Signature: MultiSignature{IsSr25519: true, AsSr25519: sig},
   161  		Era:       era,
   162  		Nonce:     o.Nonce,
   163  		Tip:       o.Tip,
   164  	}
   165  
   166  	e.Signature = extSig
   167  
   168  	// mark the extrinsic as signed
   169  	e.Version |= ExtrinsicBitSigned
   170  
   171  	return nil
   172  }
   173  
   174  func (e *Extrinsic) Decode(decoder scale.Decoder) error {
   175  	// compact length encoding (1, 2, or 4 bytes) (may not be there for Extrinsics older than Jan 11 2019)
   176  	_, err := decoder.DecodeUintCompact()
   177  	if err != nil {
   178  		return err
   179  	}
   180  
   181  	// version, signature bitmask (1 byte)
   182  	err = decoder.Decode(&e.Version)
   183  	if err != nil {
   184  		return err
   185  	}
   186  
   187  	// signature
   188  	if e.IsSigned() {
   189  		if e.Type() != ExtrinsicVersion4 {
   190  			return fmt.Errorf("unsupported extrinsic version: %v (isSigned: %v, type: %v)", e.Version, e.IsSigned(),
   191  				e.Type())
   192  		}
   193  
   194  		err = decoder.Decode(&e.Signature)
   195  		if err != nil {
   196  			return err
   197  		}
   198  	}
   199  
   200  	// call
   201  	err = decoder.Decode(&e.Method)
   202  	if err != nil {
   203  		return err
   204  	}
   205  
   206  	return nil
   207  }
   208  
   209  func (e Extrinsic) Encode(encoder scale.Encoder) error {
   210  	if e.Type() != ExtrinsicVersion4 {
   211  		return fmt.Errorf("unsupported extrinsic version: %v (isSigned: %v, type: %v)", e.Version, e.IsSigned(),
   212  			e.Type())
   213  	}
   214  
   215  	// create a temporary buffer that will receive the plain encoded transaction (version, signature (optional),
   216  	// method/call)
   217  	var bb = bytes.Buffer{}
   218  	tempEnc := scale.NewEncoder(&bb)
   219  
   220  	// encode the version of the extrinsic
   221  	err := tempEnc.Encode(e.Version)
   222  	if err != nil {
   223  		return err
   224  	}
   225  
   226  	// encode the signature if signed
   227  	if e.IsSigned() {
   228  		err = tempEnc.Encode(e.Signature)
   229  		if err != nil {
   230  			return err
   231  		}
   232  	}
   233  
   234  	// encode the method
   235  	err = tempEnc.Encode(e.Method)
   236  	if err != nil {
   237  		return err
   238  	}
   239  
   240  	// take the temporary buffer to determine length, write that as prefix
   241  	eb := bb.Bytes()
   242  	err = encoder.EncodeUintCompact(*big.NewInt(0).SetUint64(uint64(len(eb))))
   243  	if err != nil {
   244  		return err
   245  	}
   246  
   247  	// write the actual encoded transaction
   248  	err = encoder.Write(eb)
   249  	if err != nil {
   250  		return err
   251  	}
   252  
   253  	return nil
   254  }
   255  
   256  // Call is the extrinsic function descriptor
   257  type Call struct {
   258  	CallIndex CallIndex
   259  	Args      Args
   260  }
   261  
   262  func NewCall(m *Metadata, call string, args ...interface{}) (Call, error) {
   263  	c, err := m.FindCallIndex(call)
   264  	if err != nil {
   265  		return Call{}, err
   266  	}
   267  
   268  	var a []byte
   269  	for _, arg := range args {
   270  		e, err := EncodeToBytes(arg)
   271  		if err != nil {
   272  			return Call{}, err
   273  		}
   274  		a = append(a, e...)
   275  	}
   276  
   277  	return Call{c, a}, nil
   278  }
   279  
   280  func NewCallWithCallIndex(ci CallIndex, call string, args ...interface{}) (Call, error) {
   281  	var a []byte
   282  	for _, arg := range args {
   283  		e, err := EncodeToBytes(arg)
   284  		if err != nil {
   285  			return Call{}, err
   286  		}
   287  		a = append(a, e...)
   288  	}
   289  
   290  	return Call{ci, a}, nil
   291  }
   292  
   293  // Callindex is a 16 bit wrapper around the `[sectionIndex, methodIndex]` value that uniquely identifies a method
   294  type CallIndex struct {
   295  	SectionIndex uint8
   296  	MethodIndex  uint8
   297  }
   298  
   299  func (m *CallIndex) Decode(decoder scale.Decoder) error {
   300  	err := decoder.Decode(&m.SectionIndex)
   301  	if err != nil {
   302  		return err
   303  	}
   304  
   305  	err = decoder.Decode(&m.MethodIndex)
   306  	if err != nil {
   307  		return err
   308  	}
   309  
   310  	return nil
   311  }
   312  
   313  func (m CallIndex) Encode(encoder scale.Encoder) error {
   314  	err := encoder.Encode(m.SectionIndex)
   315  	if err != nil {
   316  		return err
   317  	}
   318  
   319  	err = encoder.Encode(m.MethodIndex)
   320  	if err != nil {
   321  		return err
   322  	}
   323  
   324  	return nil
   325  }
   326  
   327  // Args are the encoded arguments for a Call
   328  type Args []byte
   329  
   330  // Encode implements encoding for Args, which just unwraps the bytes of Args
   331  func (a Args) Encode(encoder scale.Encoder) error {
   332  	return encoder.Write(a)
   333  }
   334  
   335  // Decode implements decoding for Args, which just reads all the remaining bytes into Args
   336  func (a *Args) Decode(decoder scale.Decoder) error {
   337  	for i := 0; true; i++ {
   338  		b, err := decoder.ReadOneByte()
   339  		if err == io.EOF {
   340  			break
   341  		}
   342  		if err != nil {
   343  			return err
   344  		}
   345  		*a = append((*a)[:i], b)
   346  	}
   347  	return nil
   348  }
   349  
   350  type Justification Bytes
   351  
   352  type SignaturePayload struct {
   353  	Address        Address
   354  	BlockHash      Hash
   355  	BlockNumber    BlockNumber
   356  	Era            ExtrinsicEra
   357  	GenesisHash    Hash
   358  	Method         Call
   359  	Nonce          UCompact
   360  	RuntimeVersion RuntimeVersion
   361  	Tip            UCompact
   362  	Version        uint8
   363  }