github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/core/wavm/abi.go (about)

     1  // Copyright 2019 The go-vnt Authors
     2  // This file is part of the go-vnt library.
     3  //
     4  // The go-vnt library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-vnt library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-vnt library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package wavm
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/binary"
    22  	"errors"
    23  	"fmt"
    24  	"math/big"
    25  	"reflect"
    26  
    27  	"github.com/vntchain/go-vnt/accounts/abi"
    28  	"github.com/vntchain/go-vnt/common"
    29  	"github.com/vntchain/vnt-wasm/wasm"
    30  )
    31  
    32  var (
    33  	errBadBool = errors.New("abi: improperly encoded boolean value")
    34  )
    35  
    36  func GetAbi(abibyte []byte) (abi.ABI, error) {
    37  	buf := bytes.NewBuffer(abibyte)
    38  	res, err := abi.JSON(buf)
    39  	return res, err
    40  }
    41  
    42  // reads the integer based on its kind
    43  func readInteger(kind reflect.Kind, b []byte) interface{} {
    44  	switch kind {
    45  	case reflect.Uint8:
    46  		return uint64(b[len(b)-1])
    47  	case reflect.Uint16:
    48  		return uint64(binary.BigEndian.Uint16(b[len(b)-2:]))
    49  	case reflect.Uint32:
    50  		return uint64(binary.BigEndian.Uint32(b[len(b)-4:]))
    51  	case reflect.Uint64:
    52  		return uint64(binary.BigEndian.Uint64(b[len(b)-8:]))
    53  	case reflect.Int8:
    54  		return uint64(b[len(b)-1])
    55  	case reflect.Int16:
    56  		return uint64(binary.BigEndian.Uint16(b[len(b)-2:]))
    57  	case reflect.Int32:
    58  		return uint64(binary.BigEndian.Uint32(b[len(b)-4:]))
    59  	case reflect.Int64:
    60  		return uint64(binary.BigEndian.Uint64(b[len(b)-8:]))
    61  	default:
    62  		return new(big.Int).SetBytes(b)
    63  	}
    64  }
    65  
    66  // reads a bool
    67  func readBool(word []byte) (uint64, error) {
    68  	for _, b := range word[:31] {
    69  		if b != 0 {
    70  			return uint64(0), errBadBool
    71  		}
    72  	}
    73  	switch word[31] {
    74  	case 0:
    75  		return uint64(0), nil
    76  	case 1:
    77  		return uint64(1), nil
    78  	default:
    79  		return uint64(0), errBadBool
    80  	}
    81  }
    82  
    83  // packNum packs the given number (using the reflect value) and will cast it to appropriate number representation
    84  func packNum(value reflect.Value) ([]byte, error) {
    85  	switch kind := value.Kind(); kind {
    86  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
    87  		return abi.U256(new(big.Int).SetUint64(value.Uint())), nil
    88  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    89  		return abi.U256(big.NewInt(value.Int())), nil
    90  	case reflect.Ptr:
    91  		return abi.U256(value.Interface().(*big.Int)), nil
    92  	default:
    93  		return nil, fmt.Errorf("abi: fatal error")
    94  	}
    95  }
    96  
    97  func packBytesSlice(bytes []byte, l int) ([]byte, error) {
    98  	len, err := packNum(reflect.ValueOf(l))
    99  	return append(len, common.RightPadBytes(bytes, (l+31)/32*32)...), err
   100  }
   101  
   102  func lengthPrefixPointsTo(index int, output []byte) (start int, length int, err error) {
   103  	bigOffsetEnd := big.NewInt(0).SetBytes(output[index : index+32])
   104  	bigOffsetEnd.Add(bigOffsetEnd, common.Big32)
   105  	outputLength := big.NewInt(int64(len(output)))
   106  	if bigOffsetEnd.Cmp(outputLength) > 0 {
   107  		return 0, 0, fmt.Errorf("abi: cannot marshal in to go slice: offset %v would go over slice boundary (len=%v)", bigOffsetEnd, outputLength)
   108  	}
   109  
   110  	if bigOffsetEnd.BitLen() > 63 {
   111  		return 0, 0, fmt.Errorf("abi offset larger than int64: %v", bigOffsetEnd)
   112  	}
   113  
   114  	offsetEnd := int(bigOffsetEnd.Uint64())
   115  	lengthBig := big.NewInt(0).SetBytes(output[offsetEnd-32 : offsetEnd])
   116  
   117  	totalSize := big.NewInt(0)
   118  	totalSize.Add(totalSize, bigOffsetEnd)
   119  	totalSize.Add(totalSize, lengthBig)
   120  	if totalSize.BitLen() > 63 {
   121  		return 0, 0, fmt.Errorf("abi length larger than int64: %v", totalSize)
   122  	}
   123  
   124  	if totalSize.Cmp(outputLength) > 0 {
   125  		return 0, 0, fmt.Errorf("abi: cannot marshal in to go type: length insufficient %v require %v", outputLength, totalSize)
   126  	}
   127  	start = int(bigOffsetEnd.Uint64())
   128  	length = int(lengthBig.Uint64())
   129  	return
   130  }
   131  
   132  func MutableFunction(abi abi.ABI, module *wasm.Module) Mutable {
   133  	mutable := Mutable{}
   134  	for k, v := range module.Export.Entries {
   135  		if m, ok := abi.Methods[k]; ok {
   136  			mutable[v.Index] = !m.Const
   137  		}
   138  	}
   139  	return mutable
   140  }