github.com/stafiprotocol/go-substrate-rpc-client@v1.4.7/pkg/scale/codec.go (about)

     1  // Copyright 2018 Jsgenesis
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package scale
    16  
    17  import (
    18  	"bytes"
    19  	"encoding/binary"
    20  	"errors"
    21  	"fmt"
    22  	"io"
    23  	"log"
    24  	"math"
    25  	"math/big"
    26  	"reflect"
    27  )
    28  
    29  // Implementation for Parity codec in Go.
    30  // Derived from https://github.com/paritytech/parity-codec/
    31  // While Rust implementation uses Rust type system and is highly optimized, this one
    32  // has to rely on Go's reflection and thus is notably slower.
    33  // Feature parity is almost full, apart from the lack of support for u128 (which are missing in Go).
    34  
    35  const maxUint = ^uint(0)
    36  const maxInt = int(maxUint >> 1)
    37  
    38  // Encoder is a wrapper around a Writer that allows encoding data items to a stream.
    39  // Allows passing encoding options
    40  type Encoder struct {
    41  	writer io.Writer
    42  }
    43  
    44  func NewEncoder(writer io.Writer) *Encoder {
    45  	return &Encoder{writer: writer}
    46  }
    47  
    48  // Write several bytes to the encoder.
    49  func (pe Encoder) Write(bytes []byte) error {
    50  	c, err := pe.writer.Write(bytes)
    51  	if err != nil {
    52  		return err
    53  	}
    54  	if c < len(bytes) {
    55  		return fmt.Errorf("Could not write %d bytes to writer", len(bytes))
    56  	}
    57  	return nil
    58  }
    59  
    60  // PushByte writes a single byte to an encoder.
    61  func (pe Encoder) PushByte(b byte) error {
    62  	return pe.Write([]byte{b})
    63  }
    64  
    65  // EncodeUintCompact writes an unsigned integer to the stream using the compact encoding.
    66  // A typical usage is storing the length of a collection.
    67  // Definition of compact encoding:
    68  // 0b00 00 00 00 / 00 00 00 00 / 00 00 00 00 / 00 00 00 00
    69  //
    70  //	xx xx xx 00															(0 ... 2**6 - 1)		(u8)
    71  //	yL yL yL 01 / yH yH yH yL												(2**6 ... 2**14 - 1)	(u8, u16)  low LH high
    72  //	zL zL zL 10 / zM zM zM zL / zM zM zM zM / zH zH zH zM					(2**14 ... 2**30 - 1)	(u16, u32)  low LMMH high
    73  //	nn nn nn 11 [ / zz zz zz zz ]{4 + n}									(2**30 ... 2**536 - 1)	(u32, u64, u128, U256, U512, U520) straight LE-encoded
    74  //
    75  // Rust implementation: see impl<'a> Encode for CompactRef<'a, u64>
    76  func (pe Encoder) EncodeUintCompact(v big.Int) error {
    77  	if v.Sign() == -1 {
    78  		return errors.New("Assertion error: EncodeUintCompact cannot process negative numbers")
    79  	}
    80  
    81  	if v.IsUint64() {
    82  		if v.Uint64() < 1<<30 {
    83  			if v.Uint64() < 1<<6 {
    84  				err := pe.PushByte(byte(v.Uint64()) << 2)
    85  				if err != nil {
    86  					return err
    87  				}
    88  			} else if v.Uint64() < 1<<14 {
    89  				err := binary.Write(pe.writer, binary.LittleEndian, uint16(v.Uint64()<<2)+1)
    90  				if err != nil {
    91  					return err
    92  				}
    93  			} else {
    94  				err := binary.Write(pe.writer, binary.LittleEndian, uint32(v.Uint64()<<2)+2)
    95  				if err != nil {
    96  					return err
    97  				}
    98  			}
    99  			return nil
   100  		}
   101  	}
   102  
   103  	numBytes := len(v.Bytes())
   104  	if numBytes > 255 {
   105  		return errors.New("Assertion error: numBytes>255 exeeds allowed for length prefix")
   106  	}
   107  	topSixBits := uint8(numBytes - 4)
   108  	lengthByte := topSixBits<<2 + 3
   109  
   110  	if topSixBits > 63 {
   111  		return errors.New("Assertion error: n<=63 needed to compact-encode substrate unsigned big integer")
   112  	}
   113  	err := pe.PushByte(lengthByte)
   114  	if err != nil {
   115  		return err
   116  	}
   117  	buf := v.Bytes()
   118  	Reverse(buf)
   119  	err = pe.Write(buf)
   120  	if err != nil {
   121  		return err
   122  	}
   123  	return nil
   124  }
   125  
   126  // Encode a value to the stream.
   127  func (pe Encoder) Encode(value interface{}) error {
   128  	t := reflect.TypeOf(value)
   129  
   130  	// If the type implements encodeable, use that implementation
   131  	encodeable := reflect.TypeOf((*Encodeable)(nil)).Elem()
   132  	if t.Implements(encodeable) {
   133  		err := value.(Encodeable).Encode(pe)
   134  		if err != nil {
   135  			return err
   136  		}
   137  		return nil
   138  	}
   139  
   140  	tk := t.Kind()
   141  	switch tk {
   142  
   143  	// Boolean and numbers are trivially encoded via binary.Write
   144  	// It will use reflection again and take a performance hit
   145  	// TODO: consider handling every case directly
   146  	case reflect.Bool:
   147  		fallthrough
   148  	case reflect.Int8:
   149  		fallthrough
   150  	case reflect.Uint8:
   151  		fallthrough
   152  	case reflect.Int:
   153  		fallthrough
   154  	case reflect.Int16:
   155  		fallthrough
   156  	case reflect.Int32:
   157  		fallthrough
   158  	case reflect.Int64:
   159  		fallthrough
   160  	case reflect.Uint:
   161  		fallthrough
   162  	case reflect.Uint16:
   163  		fallthrough
   164  	case reflect.Uint32:
   165  		fallthrough
   166  	case reflect.Uint64:
   167  		fallthrough
   168  	case reflect.Uintptr:
   169  		fallthrough
   170  	case reflect.Float32:
   171  		fallthrough
   172  	case reflect.Float64:
   173  		err := binary.Write(pe.writer, binary.LittleEndian, value)
   174  		if err != nil {
   175  			return err
   176  		}
   177  	case reflect.Ptr:
   178  		rv := reflect.ValueOf(value)
   179  		if rv.IsNil() {
   180  			return errors.New("Encoding null pointers not supported; consider using Option type")
   181  		} else {
   182  			dereferenced := rv.Elem()
   183  			err := pe.Encode(dereferenced.Interface())
   184  			if err != nil {
   185  				return err
   186  			}
   187  		}
   188  
   189  	// Arrays: no compact-encoded length prefix
   190  	case reflect.Array:
   191  		rv := reflect.ValueOf(value)
   192  		l := rv.Len()
   193  		for i := 0; i < l; i++ {
   194  			err := pe.Encode(rv.Index(i).Interface())
   195  			if err != nil {
   196  				return err
   197  			}
   198  		}
   199  
   200  	// Slices: first compact-encode length, then each item individually
   201  	case reflect.Slice:
   202  		rv := reflect.ValueOf(value)
   203  		l := rv.Len()
   204  		len64 := uint64(l)
   205  		if len64 > math.MaxUint32 {
   206  			return errors.New("Attempted to serialize a collection with too many elements.")
   207  		}
   208  		err := pe.EncodeUintCompact(*big.NewInt(0).SetUint64(len64))
   209  		if err != nil {
   210  			return err
   211  		}
   212  		for i := 0; i < l; i++ {
   213  			err = pe.Encode(rv.Index(i).Interface())
   214  			if err != nil {
   215  				return err
   216  			}
   217  		}
   218  
   219  	// Strings are encoded as UTF-8 byte slices, just as in Rust
   220  	case reflect.String:
   221  		s := reflect.ValueOf(value).String()
   222  		err := pe.Encode([]byte(s))
   223  		if err != nil {
   224  			return err
   225  		}
   226  
   227  	case reflect.Struct:
   228  		rv := reflect.ValueOf(value)
   229  		for i := 0; i < rv.NumField(); i++ {
   230  			ft := rv.Type().Field(i)
   231  			tv, ok := ft.Tag.Lookup("scale")
   232  			if ok && tv == "-" {
   233  				continue
   234  			}
   235  			err := pe.Encode(rv.Field(i).Interface())
   236  			if err != nil {
   237  				return fmt.Errorf("type %s does not support Encodeable interface and could not be "+
   238  					"encoded field by field, error: %v", t, err)
   239  			}
   240  		}
   241  
   242  	// Currently unsupported types
   243  	case reflect.Complex64:
   244  		fallthrough
   245  	case reflect.Complex128:
   246  		fallthrough
   247  	case reflect.Chan:
   248  		fallthrough
   249  	case reflect.Func:
   250  		fallthrough
   251  	case reflect.Interface:
   252  		fallthrough
   253  	case reflect.Map:
   254  		fallthrough
   255  	case reflect.UnsafePointer:
   256  		fallthrough
   257  	case reflect.Invalid:
   258  		return fmt.Errorf("Type %s cannot be encoded", t.Kind())
   259  	default:
   260  		log.Println("not captured")
   261  	}
   262  	return nil
   263  }
   264  
   265  // EncodeOption stores optionally present value to the stream.
   266  func (pe Encoder) EncodeOption(hasValue bool, value interface{}) error {
   267  	if !hasValue {
   268  		err := pe.PushByte(0)
   269  		if err != nil {
   270  			return err
   271  		}
   272  	} else {
   273  		err := pe.PushByte(1)
   274  		if err != nil {
   275  			return err
   276  		}
   277  		err = pe.Encode(value)
   278  		if err != nil {
   279  			return err
   280  		}
   281  	}
   282  	return nil
   283  }
   284  
   285  // Decoder is a wraper around a Reader that allows decoding data items from a stream.
   286  type Decoder struct {
   287  	reader io.Reader
   288  }
   289  
   290  func NewDecoder(reader io.Reader) *Decoder {
   291  	return &Decoder{reader: reader}
   292  }
   293  
   294  // Read reads bytes from a stream into a buffer
   295  func (pd Decoder) Read(bytes []byte) error {
   296  	c, err := pd.reader.Read(bytes)
   297  	if err != nil {
   298  		return err
   299  	}
   300  	if c < len(bytes) {
   301  		return fmt.Errorf("Cannot read the required number of bytes %d, only %d available", len(bytes), c)
   302  	}
   303  	return nil
   304  }
   305  
   306  // ReadOneByte reads a next byte from the stream.
   307  // Named so to avoid a linter warning about a clash with io.ByteReader.ReadByte
   308  func (pd Decoder) ReadOneByte() (byte, error) {
   309  	buf := []byte{0}
   310  	err := pd.Read(buf)
   311  	if err != nil {
   312  		return buf[0], err
   313  	}
   314  	return buf[0], nil
   315  }
   316  
   317  // Decode takes a pointer to a decodable value and populates it from the stream.
   318  func (pd Decoder) Decode(target interface{}) error {
   319  	t0 := reflect.TypeOf(target)
   320  	if t0.Kind() != reflect.Ptr {
   321  		return errors.New("Target must be a pointer, but was " + fmt.Sprint(t0))
   322  	}
   323  	val := reflect.ValueOf(target)
   324  	if val.IsNil() {
   325  		return errors.New("Target is a nil pointer")
   326  	}
   327  	return pd.DecodeIntoReflectValue(val.Elem())
   328  }
   329  
   330  // DecodeIntoReflectValue populates a writable reflect.Value from the stream
   331  func (pd Decoder) DecodeIntoReflectValue(target reflect.Value) error {
   332  	t := target.Type()
   333  	if !target.CanSet() {
   334  		return fmt.Errorf("Unsettable value %v", t)
   335  	}
   336  
   337  	// If the type implements decodeable, use that implementation
   338  	decodeable := reflect.TypeOf((*Decodeable)(nil)).Elem()
   339  	ptrType := reflect.PtrTo(t)
   340  	if ptrType.Implements(decodeable) {
   341  		var holder reflect.Value
   342  		if t.Kind() == reflect.Slice || t.Kind() == reflect.Array {
   343  			slice := reflect.MakeSlice(t, target.Len(), target.Len())
   344  			holder = reflect.New(t)
   345  			holder.Elem().Set(slice)
   346  		} else {
   347  			holder = reflect.New(t)
   348  		}
   349  
   350  		err := holder.Interface().(Decodeable).Decode(pd)
   351  		if err != nil {
   352  			return err
   353  		}
   354  		target.Set(holder.Elem())
   355  		return nil
   356  	}
   357  
   358  	switch t.Kind() {
   359  
   360  	// Boolean and numbers are trivially decoded via binary.Read
   361  	// It will use reflection again and take a performance hit
   362  	// TODO: consider handling every case directly
   363  	case reflect.Bool:
   364  		fallthrough
   365  	case reflect.Int8:
   366  		fallthrough
   367  	case reflect.Uint8:
   368  		fallthrough
   369  	case reflect.Int:
   370  		fallthrough
   371  	case reflect.Int16:
   372  		fallthrough
   373  	case reflect.Int32:
   374  		fallthrough
   375  	case reflect.Int64:
   376  		fallthrough
   377  	case reflect.Uint:
   378  		fallthrough
   379  	case reflect.Uint16:
   380  		fallthrough
   381  	case reflect.Uint32:
   382  		fallthrough
   383  	case reflect.Uint64:
   384  		fallthrough
   385  	case reflect.Uintptr:
   386  		fallthrough
   387  	case reflect.Float32:
   388  		fallthrough
   389  	case reflect.Float64:
   390  		intHolder := reflect.New(t)
   391  		intPointer := intHolder.Interface()
   392  		err := binary.Read(pd.reader, binary.LittleEndian, intPointer)
   393  		if err == io.EOF {
   394  			return errors.New("expected more bytes, but could not decode any more")
   395  		}
   396  		if err != nil {
   397  			return err
   398  		}
   399  		target.Set(intHolder.Elem())
   400  
   401  	// If you want to replicate Option<T> behavior in Rust, see OptionBool and an
   402  	// example type OptionInt8 in tests.
   403  	case reflect.Ptr:
   404  		isNil := target.IsNil()
   405  		if isNil {
   406  			// target.set
   407  			// return nil
   408  		}
   409  		ptr := target.Elem()
   410  		err := pd.DecodeIntoReflectValue(ptr)
   411  		if err != nil {
   412  			return err
   413  		}
   414  
   415  	// Arrays: derive the length from the array length
   416  	case reflect.Array:
   417  		targetLen := target.Len()
   418  		for i := 0; i < targetLen; i++ {
   419  			err := pd.DecodeIntoReflectValue(target.Index(i))
   420  			if err != nil {
   421  				return err
   422  			}
   423  		}
   424  
   425  	// Slices: first compact-encode length, then each item individually
   426  	case reflect.Slice:
   427  		codedLen64, _ := pd.DecodeUintCompact()
   428  		if codedLen64.Uint64() > math.MaxUint32 {
   429  			return errors.New("Encoded array length is higher than allowed by the protocol (32-bit unsigned integer)")
   430  		}
   431  		if codedLen64.Uint64() > uint64(maxInt) {
   432  			return errors.New("Encoded array length is higher than allowed by the platform")
   433  		}
   434  		codedLen := int(codedLen64.Uint64())
   435  		targetLen := target.Len()
   436  		if codedLen != targetLen {
   437  			if int(codedLen) > target.Cap() {
   438  				newSlice := reflect.MakeSlice(t, int(codedLen), int(codedLen))
   439  				target.Set(newSlice)
   440  			} else {
   441  				target.SetLen(int(codedLen))
   442  			}
   443  		}
   444  		for i := 0; i < codedLen; i++ {
   445  			err := pd.DecodeIntoReflectValue(target.Index(i))
   446  			if err != nil {
   447  				return err
   448  			}
   449  		}
   450  
   451  	// Strings are encoded as UTF-8 byte slices, just as in Rust
   452  	case reflect.String:
   453  		var b []byte
   454  		err := pd.Decode(&b)
   455  		if err != nil {
   456  			return err
   457  		}
   458  		target.SetString(string(b))
   459  
   460  	case reflect.Struct:
   461  		for i := 0; i < target.NumField(); i++ {
   462  			ft := target.Type().Field(i)
   463  			tv, ok := ft.Tag.Lookup("scale")
   464  			if ok && tv == "-" {
   465  				continue
   466  			}
   467  			err := pd.DecodeIntoReflectValue(target.Field(i))
   468  			if err != nil {
   469  				return fmt.Errorf("type %s does not support Decodeable interface and could not be "+
   470  					"decoded field by field, error: %v", ptrType, err)
   471  			}
   472  		}
   473  
   474  	// Currently unsupported types
   475  	case reflect.Complex64:
   476  		fallthrough
   477  	case reflect.Complex128:
   478  		fallthrough
   479  	case reflect.Chan:
   480  		fallthrough
   481  	case reflect.Func:
   482  		fallthrough
   483  	case reflect.Interface:
   484  		fallthrough
   485  	case reflect.Map:
   486  		fallthrough
   487  	case reflect.UnsafePointer:
   488  		fallthrough
   489  	case reflect.Invalid:
   490  		return fmt.Errorf("Type %s cannot be decoded", t.Kind())
   491  	}
   492  	return nil
   493  }
   494  
   495  // DecodeUintCompact decodes a compact-encoded integer. See EncodeUintCompact method.
   496  func (pd Decoder) DecodeUintCompact() (*big.Int, error) {
   497  	b, _ := pd.ReadOneByte()
   498  	mode := b & 3
   499  	switch mode {
   500  	case 0:
   501  		// right shift to remove mode bits
   502  		return big.NewInt(0).SetUint64(uint64(b >> 2)), nil
   503  	case 1:
   504  		bb, err := pd.ReadOneByte()
   505  		if err != nil {
   506  			return nil, err
   507  		}
   508  		r := uint64(bb)
   509  		// * 2^6
   510  		r <<= 6
   511  		// right shift to remove mode bits and add to prev
   512  		r += uint64(b >> 2)
   513  		return big.NewInt(0).SetUint64(r), nil
   514  	case 2:
   515  		// value = 32 bits + mode
   516  		buf := make([]byte, 4)
   517  		buf[0] = b
   518  		err := pd.Read(buf[1:4])
   519  		if err != nil {
   520  			return nil, err
   521  		}
   522  		// set the buffer in little endian order
   523  		r := binary.LittleEndian.Uint32(buf)
   524  		// remove the last 2 mode bits
   525  		r >>= 2
   526  		return big.NewInt(0).SetUint64(uint64(r)), nil
   527  	case 3:
   528  		// remove mode bits
   529  		l := b >> 2
   530  
   531  		if l > 63 { // Max upper bound of 536 is (67 - 4)
   532  			return nil, errors.New("Not supported: l>63 encountered when decoding a compact-encoded uint")
   533  		}
   534  		buf := make([]byte, l+4)
   535  		err := pd.Read(buf)
   536  		if err != nil {
   537  			return nil, err
   538  		}
   539  		Reverse(buf)
   540  		return new(big.Int).SetBytes(buf), nil
   541  	default:
   542  		return nil, errors.New("Code should be unreachable")
   543  	}
   544  }
   545  
   546  // Reverse reverses bytes in place (manipulates the underlying array)
   547  func Reverse(b []byte) {
   548  	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
   549  		b[i], b[j] = b[j], b[i]
   550  	}
   551  }
   552  
   553  // DecodeOption decodes a optionally available value into a boolean presence field and a value.
   554  func (pd Decoder) DecodeOption(hasValue *bool, valuePointer interface{}) error {
   555  	b, _ := pd.ReadOneByte()
   556  	switch b {
   557  	case 0:
   558  		*hasValue = false
   559  	case 1:
   560  		*hasValue = true
   561  		err := pd.Decode(valuePointer)
   562  		if err != nil {
   563  			return err
   564  		}
   565  	default:
   566  		return fmt.Errorf("Unknown byte prefix for encoded OptionBool: %d", b)
   567  	}
   568  	return nil
   569  }
   570  
   571  // Encodeable is an interface that defines a custom encoding rules for a data type.
   572  // Should be defined for structs (not pointers to them).
   573  // See OptionBool for an example implementation.
   574  type Encodeable interface {
   575  	// ParityEncode encodes and write this structure into a stream
   576  	Encode(encoder Encoder) error
   577  }
   578  
   579  // Decodeable is an interface that defines a custom encoding rules for a data type.
   580  // Should be defined for pointers to structs.
   581  // See OptionBool for an example implementation.
   582  type Decodeable interface {
   583  	// ParityDecode populates this structure from a stream (overwriting the current contents), return false on failure
   584  	Decode(decoder Decoder) error
   585  }
   586  
   587  // OptionBool is a structure that can store a boolean or a missing value.
   588  // Note that encoding rules are slightly different from other "Option" fields.
   589  type OptionBool struct {
   590  	hasValue bool
   591  	value    bool
   592  }
   593  
   594  // NewOptionBoolEmpty creates an OptionBool without a value.
   595  func NewOptionBoolEmpty() OptionBool {
   596  	return OptionBool{false, false}
   597  }
   598  
   599  // NewOptionBool creates an OptionBool with a value.
   600  func NewOptionBool(value bool) OptionBool {
   601  	return OptionBool{true, value}
   602  }
   603  
   604  // ParityEncode implements encoding for OptionBool as per Rust implementation.
   605  func (o OptionBool) Encode(encoder Encoder) error {
   606  	var err error
   607  	if !o.hasValue {
   608  		err = encoder.PushByte(0)
   609  	} else {
   610  		if o.value {
   611  			err = encoder.PushByte(1)
   612  		} else {
   613  			err = encoder.PushByte(2)
   614  		}
   615  	}
   616  	if err != nil {
   617  		return err
   618  	}
   619  	return nil
   620  }
   621  
   622  // ParityDecode implements decoding for OptionBool as per Rust implementation.
   623  func (o *OptionBool) Decode(decoder Decoder) error {
   624  	b, _ := decoder.ReadOneByte()
   625  	switch b {
   626  	case 0:
   627  		o.hasValue = false
   628  		o.value = false
   629  	case 1:
   630  		o.hasValue = true
   631  		o.value = true
   632  	case 2:
   633  		o.hasValue = true
   634  		o.value = false
   635  	default:
   636  		return fmt.Errorf("Unknown byte prefix for encoded OptionBool: %d", b)
   637  	}
   638  	return nil
   639  }
   640  
   641  // ToKeyedVec replicates the behaviour of Rust's to_keyed_vec helper.
   642  func ToKeyedVec(value interface{}, prependKey []byte) ([]byte, error) {
   643  	var buffer = bytes.NewBuffer(prependKey)
   644  	err := Encoder{buffer}.Encode(value)
   645  	if err != nil {
   646  		return nil, err
   647  	}
   648  	return buffer.Bytes(), nil
   649  }