github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/accounts/abi/unpack.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //版权所有2017 Go Ethereum作者
    10  //此文件是Go以太坊库的一部分。
    11  //
    12  //Go-Ethereum库是免费软件:您可以重新分发它和/或修改
    13  //根据GNU发布的较低通用公共许可证的条款
    14  //自由软件基金会,或者许可证的第3版,或者
    15  //(由您选择)任何更高版本。
    16  //
    17  //Go以太坊图书馆的发行目的是希望它会有用,
    18  //但没有任何保证;甚至没有
    19  //适销性或特定用途的适用性。见
    20  //GNU较低的通用公共许可证,了解更多详细信息。
    21  //
    22  //你应该收到一份GNU较低级别的公共许可证副本
    23  //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。
    24  
    25  package abi
    26  
    27  import (
    28  	"encoding/binary"
    29  	"fmt"
    30  	"math/big"
    31  	"reflect"
    32  
    33  	"github.com/ethereum/go-ethereum/common"
    34  )
    35  
    36  //根据整数的类型读取整数
    37  func readInteger(kind reflect.Kind, b []byte) interface{} {
    38  	switch kind {
    39  	case reflect.Uint8:
    40  		return b[len(b)-1]
    41  	case reflect.Uint16:
    42  		return binary.BigEndian.Uint16(b[len(b)-2:])
    43  	case reflect.Uint32:
    44  		return binary.BigEndian.Uint32(b[len(b)-4:])
    45  	case reflect.Uint64:
    46  		return binary.BigEndian.Uint64(b[len(b)-8:])
    47  	case reflect.Int8:
    48  		return int8(b[len(b)-1])
    49  	case reflect.Int16:
    50  		return int16(binary.BigEndian.Uint16(b[len(b)-2:]))
    51  	case reflect.Int32:
    52  		return int32(binary.BigEndian.Uint32(b[len(b)-4:]))
    53  	case reflect.Int64:
    54  		return int64(binary.BigEndian.Uint64(b[len(b)-8:]))
    55  	default:
    56  		return new(big.Int).SetBytes(b)
    57  	}
    58  }
    59  
    60  //读BoL
    61  func readBool(word []byte) (bool, error) {
    62  	for _, b := range word[:31] {
    63  		if b != 0 {
    64  			return false, errBadBool
    65  		}
    66  	}
    67  	switch word[31] {
    68  	case 0:
    69  		return false, nil
    70  	case 1:
    71  		return true, nil
    72  	default:
    73  		return false, errBadBool
    74  	}
    75  }
    76  
    77  //函数类型只是在末尾带有函数选择签名的地址。
    78  //这通过始终将其显示为24个数组(address+sig=24字节)来强制执行该标准。
    79  func readFunctionType(t Type, word []byte) (funcTy [24]byte, err error) {
    80  	if t.T != FunctionTy {
    81  		return [24]byte{}, fmt.Errorf("abi: invalid type in call to make function type byte array")
    82  	}
    83  	if garbage := binary.BigEndian.Uint64(word[24:32]); garbage != 0 {
    84  		err = fmt.Errorf("abi: got improperly encoded function type, got %v", word)
    85  	} else {
    86  		copy(funcTy[:], word[0:24])
    87  	}
    88  	return
    89  }
    90  
    91  //通过反射,创建要从中读取的固定数组
    92  func readFixedBytes(t Type, word []byte) (interface{}, error) {
    93  	if t.T != FixedBytesTy {
    94  		return nil, fmt.Errorf("abi: invalid type in call to make fixed byte array")
    95  	}
    96  //转换
    97  	array := reflect.New(t.Type).Elem()
    98  
    99  	reflect.Copy(array, reflect.ValueOf(word[0:t.Size]))
   100  	return array.Interface(), nil
   101  
   102  }
   103  
   104  func getFullElemSize(elem *Type) int {
   105  //所有其他元素都应计为32(切片有指向各个元素的指针)
   106  	size := 32
   107  //数组将其包装,每个元素的大小相同
   108  	for elem.T == ArrayTy {
   109  		size *= elem.Size
   110  		elem = elem.Elem
   111  	}
   112  	return size
   113  }
   114  
   115  //迭代解包元素
   116  func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error) {
   117  	if size < 0 {
   118  		return nil, fmt.Errorf("cannot marshal input to array, size is negative (%d)", size)
   119  	}
   120  	if start+32*size > len(output) {
   121  		return nil, fmt.Errorf("abi: cannot marshal in to go array: offset %d would go over slice boundary (len=%d)", len(output), start+32*size)
   122  	}
   123  
   124  //此值将成为切片或数组,具体取决于类型
   125  	var refSlice reflect.Value
   126  
   127  	if t.T == SliceTy {
   128  //申报我们的切片
   129  		refSlice = reflect.MakeSlice(t.Type, size, size)
   130  	} else if t.T == ArrayTy {
   131  //声明我们的数组
   132  		refSlice = reflect.New(t.Type).Elem()
   133  	} else {
   134  		return nil, fmt.Errorf("abi: invalid type in array/slice unpacking stage")
   135  	}
   136  
   137  //数组具有压缩元素,从而导致较长的解包步骤。
   138  //每个元素的切片只有32个字节(指向内容)。
   139  	elemSize := 32
   140  	if t.T == ArrayTy {
   141  		elemSize = getFullElemSize(t.Elem)
   142  	}
   143  
   144  	for i, j := start, 0; j < size; i, j = i+elemSize, j+1 {
   145  
   146  		inter, err := toGoType(i, *t.Elem, output)
   147  		if err != nil {
   148  			return nil, err
   149  		}
   150  
   151  //将项目附加到反射切片
   152  		refSlice.Index(j).Set(reflect.ValueOf(inter))
   153  	}
   154  
   155  //返回接口
   156  	return refSlice.Interface(), nil
   157  }
   158  
   159  //togotype解析输出字节并递归地分配这些字节的值
   160  //符合ABI规范的GO类型。
   161  func toGoType(index int, t Type, output []byte) (interface{}, error) {
   162  	if index+32 > len(output) {
   163  		return nil, fmt.Errorf("abi: cannot marshal in to go type: length insufficient %d require %d", len(output), index+32)
   164  	}
   165  
   166  	var (
   167  		returnOutput []byte
   168  		begin, end   int
   169  		err          error
   170  	)
   171  
   172  //如果需要长度前缀,请查找返回的起始单词和大小。
   173  	if t.requiresLengthPrefix() {
   174  		begin, end, err = lengthPrefixPointsTo(index, output)
   175  		if err != nil {
   176  			return nil, err
   177  		}
   178  	} else {
   179  		returnOutput = output[index : index+32]
   180  	}
   181  
   182  	switch t.T {
   183  	case SliceTy:
   184  		return forEachUnpack(t, output, begin, end)
   185  	case ArrayTy:
   186  		return forEachUnpack(t, output, index, t.Size)
   187  case StringTy: //变量数组写在返回字节的末尾
   188  		return string(output[begin : begin+end]), nil
   189  	case IntTy, UintTy:
   190  		return readInteger(t.Kind, returnOutput), nil
   191  	case BoolTy:
   192  		return readBool(returnOutput)
   193  	case AddressTy:
   194  		return common.BytesToAddress(returnOutput), nil
   195  	case HashTy:
   196  		return common.BytesToHash(returnOutput), nil
   197  	case BytesTy:
   198  		return output[begin : begin+end], nil
   199  	case FixedBytesTy:
   200  		return readFixedBytes(t, returnOutput)
   201  	case FunctionTy:
   202  		return readFunctionType(t, returnOutput)
   203  	default:
   204  		return nil, fmt.Errorf("abi: unknown type %v", t.T)
   205  	}
   206  }
   207  
   208  //将一个32字节的切片解释为一个偏移量,然后确定要寻找哪一个指示来解码该类型。
   209  func lengthPrefixPointsTo(index int, output []byte) (start int, length int, err error) {
   210  	bigOffsetEnd := big.NewInt(0).SetBytes(output[index : index+32])
   211  	bigOffsetEnd.Add(bigOffsetEnd, common.Big32)
   212  	outputLength := big.NewInt(int64(len(output)))
   213  
   214  	if bigOffsetEnd.Cmp(outputLength) > 0 {
   215  		return 0, 0, fmt.Errorf("abi: cannot marshal in to go slice: offset %v would go over slice boundary (len=%v)", bigOffsetEnd, outputLength)
   216  	}
   217  
   218  	if bigOffsetEnd.BitLen() > 63 {
   219  		return 0, 0, fmt.Errorf("abi offset larger than int64: %v", bigOffsetEnd)
   220  	}
   221  
   222  	offsetEnd := int(bigOffsetEnd.Uint64())
   223  	lengthBig := big.NewInt(0).SetBytes(output[offsetEnd-32 : offsetEnd])
   224  
   225  	totalSize := big.NewInt(0)
   226  	totalSize.Add(totalSize, bigOffsetEnd)
   227  	totalSize.Add(totalSize, lengthBig)
   228  	if totalSize.BitLen() > 63 {
   229  		return 0, 0, fmt.Errorf("abi length larger than int64: %v", totalSize)
   230  	}
   231  
   232  	if totalSize.Cmp(outputLength) > 0 {
   233  		return 0, 0, fmt.Errorf("abi: cannot marshal in to go type: length insufficient %v require %v", outputLength, totalSize)
   234  	}
   235  	start = int(bigOffsetEnd.Uint64())
   236  	length = int(lengthBig.Uint64())
   237  	return
   238  }