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 }