accounts/abi: include fixed array size in offset for dynamic type

This commit is contained in:
Yondon Fu 2017-10-12 10:58:53 -04:00
parent 8d8034fe59
commit a5330fe0c5
2 changed files with 62 additions and 1 deletions

View File

@ -367,6 +367,56 @@ func TestInputVariableInputLength(t *testing.T) {
} }
} }
func TestInputFixedArrayAndVariableInputLength(t *testing.T) {
const definition = `[
{ "type" : "function", "name" : "fixedArrStr", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "fixedArr", "type" : "uint256[2]" } ] },
{ "type" : "function", "name" : "fixedArrBytes", "constant" : true, "inputs" : [ { "name" : "str", "type" : "bytes" }, { "name" : "fixedArr", "type" : "uint256[2]" } ] }
]`
abi, err := JSON(strings.NewReader(definition))
if err != nil {
t.Error(err)
}
// test fixed array of uint256 and a string
arrin := [2]*big.Int{big.NewInt(1), big.NewInt(2)}
strin := "hello world"
fixedArrStrPack, err := abi.Pack("fixedArrStr", strin, arrin)
if err != nil {
t.Error(err)
}
offset := make([]byte, 32)
offset[31] = 96
length := make([]byte, 32)
length[31] = byte(len(strin))
strvalue := common.RightPadBytes([]byte(strin), 32)
arrinvalue1 := common.LeftPadBytes(arrin[0].Bytes(), 32)
arrinvalue2 := common.LeftPadBytes(arrin[1].Bytes(), 32)
exp := append(offset, arrinvalue1...)
exp = append(exp, arrinvalue2...)
exp = append(exp, append(length, strvalue...)...)
// ignore first 4 bytes of the output. This is the function identifier
fixedArrStrPack = fixedArrStrPack[4:]
if !bytes.Equal(fixedArrStrPack, exp) {
t.Errorf("expected %x, got %x\n", exp, fixedArrStrPack)
}
// test fixed array of uint256 and a byte array
bytesin := []byte(strin)
fixedArrBytesPack, err := abi.Pack("fixedArrBytes", bytesin, arrin)
if err != nil {
t.Error(err)
}
// ignore first 4 bytes of the output. This is the function identifier
fixedArrBytesPack = fixedArrBytesPack[4:]
if !bytes.Equal(fixedArrBytesPack, exp) {
t.Errorf("expected %x, got %x\n", exp, fixedArrBytesPack)
}
}
func TestDefaultFunctionParsing(t *testing.T) { func TestDefaultFunctionParsing(t *testing.T) {
const definition = `[{ "name" : "balance" }]` const definition = `[{ "name" : "balance" }]`

View File

@ -48,6 +48,16 @@ func (method Method) pack(args ...interface{}) ([]byte, error) {
// output. This is used for strings and bytes types input. // output. This is used for strings and bytes types input.
var variableInput []byte var variableInput []byte
// input offset is the bytes offset for packed output
inputOffset := 0
for _, input := range method.Inputs {
if input.Type.IsArray {
inputOffset += (32 * input.Type.SliceSize)
} else {
inputOffset += 32
}
}
var ret []byte var ret []byte
for i, a := range args { for i, a := range args {
input := method.Inputs[i] input := method.Inputs[i]
@ -60,7 +70,8 @@ func (method Method) pack(args ...interface{}) ([]byte, error) {
// check for a slice type (string, bytes, slice) // check for a slice type (string, bytes, slice)
if input.Type.requiresLengthPrefix() { if input.Type.requiresLengthPrefix() {
// calculate the offset // calculate the offset
offset := len(method.Inputs)*32 + len(variableInput) offset := inputOffset + len(variableInput)
// set the offset // set the offset
ret = append(ret, packNum(reflect.ValueOf(offset))...) ret = append(ret, packNum(reflect.ValueOf(offset))...)
// Append the packed output to the variable input. The variable input // Append the packed output to the variable input. The variable input