/
pack.go
78 lines (70 loc) · 2.45 KB
/
pack.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package abi
import (
"github.com/vitelabs/go-vite/common/helper"
"math/big"
"reflect"
)
// packBytesSlice packs the given bytes as [L, V] as the canonical representation
// bytes slice
func packBytesSlice(bytes []byte, l int) ([]byte, error) {
len, err := packNum(reflect.ValueOf(l))
if err != nil {
return nil, err
}
return append(len, helper.RightPadBytes(bytes, (l+helper.WordSize-1)/helper.WordSize*helper.WordSize)...), nil
}
// packElement packs the given reflect value according to the abi specification in
// t.
func packElement(t Type, reflectValue reflect.Value) ([]byte, error) {
switch t.T {
case IntTy, UintTy:
return packNum(reflectValue)
case StringTy:
return packBytesSlice([]byte(reflectValue.String()), reflectValue.Len())
case AddressTy:
if reflectValue.Kind() == reflect.Array {
reflectValue = mustArrayToByteSlice(reflectValue)
}
return helper.LeftPadBytes(reflectValue.Bytes(), helper.WordSize), nil
case GidTy:
if reflectValue.Kind() == reflect.Array {
reflectValue = mustArrayToByteSlice(reflectValue)
}
return helper.LeftPadBytes(reflectValue.Bytes(), helper.WordSize), nil
case TokenIdTy:
if reflectValue.Kind() == reflect.Array {
reflectValue = mustArrayToByteSlice(reflectValue)
}
return helper.LeftPadBytes(reflectValue.Bytes(), helper.WordSize), nil
case BoolTy:
if reflectValue.Bool() {
return helper.PaddedBigBytes(helper.Big1, helper.WordSize), nil
}
return helper.PaddedBigBytes(helper.Big0, helper.WordSize), nil
case BytesTy:
if reflectValue.Kind() == reflect.Array {
reflectValue = mustArrayToByteSlice(reflectValue)
}
return packBytesSlice(reflectValue.Bytes(), reflectValue.Len())
case FixedBytesTy:
if reflectValue.Kind() == reflect.Array {
reflectValue = mustArrayToByteSlice(reflectValue)
}
return helper.RightPadBytes(reflectValue.Bytes(), helper.WordSize), nil
default:
return nil, errPackFailed
}
}
// packNum packs the given number (using the reflect value) and will cast it to appropriate number representation
func packNum(value reflect.Value) ([]byte, error) {
switch kind := value.Kind(); kind {
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return U256(new(big.Int).SetUint64(value.Uint())), nil
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return U256(big.NewInt(value.Int())), nil
case reflect.Ptr:
return U256(value.Interface().(*big.Int)), nil
default:
return nil, errPackFailed
}
}