aboutsummaryrefslogtreecommitdiffstats
path: root/accounts/abi/type.go
diff options
context:
space:
mode:
authorVedhavyas Singareddi <vedhavyas.singareddi@gmail.com>2018-12-04 22:27:55 +0800
committerGuillaume Ballet <gballet@gmail.com>2018-12-04 22:27:55 +0800
commit92639b676aaa7f262d19081256c43cdb78aa0efd (patch)
tree8eaa518265c07c5beeb8a8e98092ef415b5e5096 /accounts/abi/type.go
parentf74077b4c24a6d1490dc12564d001df57d2a41fe (diff)
downloadgo-tangerine-92639b676aaa7f262d19081256c43cdb78aa0efd.tar.gz
go-tangerine-92639b676aaa7f262d19081256c43cdb78aa0efd.tar.zst
go-tangerine-92639b676aaa7f262d19081256c43cdb78aa0efd.zip
Add packing for dynamic array and slice types (#18051)
* added tests for new abi encoding features (#4) * added tests from bytes32[][] and string[] * added offset to other types * formatting * Abi/dynamic types (#5) * Revert "Abi/dynamic types (#5)" (#6) This reverts commit dabca31d797623d43bd780721fc0ad461d24be53. * Abi/dynamic types (#7) * some cleanup * Apply suggestions from code review apply suggestions Co-Authored-By: vedhavyas <vedhavyas.singareddi@gmail.com> * added better formatting (#8) * review chnages * better comments
Diffstat (limited to 'accounts/abi/type.go')
-rw-r--r--accounts/abi/type.go58
1 files changed, 49 insertions, 9 deletions
diff --git a/accounts/abi/type.go b/accounts/abi/type.go
index dce89d2b4..6bfaabf5a 100644
--- a/accounts/abi/type.go
+++ b/accounts/abi/type.go
@@ -183,23 +183,39 @@ func (t Type) pack(v reflect.Value) ([]byte, error) {
return nil, err
}
- if t.T == SliceTy || t.T == ArrayTy {
- var packed []byte
+ switch t.T {
+ case SliceTy, ArrayTy:
+ var ret []byte
+ if t.requiresLengthPrefix() {
+ // append length
+ ret = append(ret, packNum(reflect.ValueOf(v.Len()))...)
+ }
+
+ // calculate offset if any
+ offset := 0
+ offsetReq := isDynamicType(*t.Elem)
+ if offsetReq {
+ offset = getDynamicTypeOffset(*t.Elem) * v.Len()
+ }
+ var tail []byte
for i := 0; i < v.Len(); i++ {
val, err := t.Elem.pack(v.Index(i))
if err != nil {
return nil, err
}
- packed = append(packed, val...)
- }
- if t.T == SliceTy {
- return packBytesSlice(packed, v.Len()), nil
- } else if t.T == ArrayTy {
- return packed, nil
+ if !offsetReq {
+ ret = append(ret, val...)
+ continue
+ }
+ ret = append(ret, packNum(reflect.ValueOf(offset))...)
+ offset += len(val)
+ tail = append(tail, val...)
}
+ return append(ret, tail...), nil
+ default:
+ return packElement(t, v), nil
}
- return packElement(t, v), nil
}
// requireLengthPrefix returns whether the type requires any sort of length
@@ -207,3 +223,27 @@ func (t Type) pack(v reflect.Value) ([]byte, error) {
func (t Type) requiresLengthPrefix() bool {
return t.T == StringTy || t.T == BytesTy || t.T == SliceTy
}
+
+// isDynamicType returns true if the type is dynamic.
+// StringTy, BytesTy, and SliceTy(irrespective of slice element type) are dynamic types
+// ArrayTy is considered dynamic if and only if the Array element is a dynamic type.
+// This function recursively checks the type for slice and array elements.
+func isDynamicType(t Type) bool {
+ // dynamic types
+ // array is also a dynamic type if the array type is dynamic
+ return t.T == StringTy || t.T == BytesTy || t.T == SliceTy || (t.T == ArrayTy && isDynamicType(*t.Elem))
+}
+
+// getDynamicTypeOffset returns the offset for the type.
+// See `isDynamicType` to know which types are considered dynamic.
+// If the type t is an array and element type is not a dynamic type, then we consider it a static type and
+// return 32 * size of array since length prefix is not required.
+// If t is a dynamic type or element type(for slices and arrays) is dynamic, then we simply return 32 as offset.
+func getDynamicTypeOffset(t Type) int {
+ // if it is an array and there are no dynamic types
+ // then the array is static type
+ if t.T == ArrayTy && !isDynamicType(*t.Elem) {
+ return 32 * t.Size
+ }
+ return 32
+}