Browse Source

Merge pull request #19269 from holiman/alt_18957

bind: Static byte arrays should be right-padded
Péter Szilágyi 6 years ago
parent
commit
e270a753be
3 changed files with 118 additions and 3 deletions
  1. 9 1
      accounts/abi/bind/bind_test.go
  2. 6 2
      accounts/abi/bind/topics.go
  3. 103 0
      accounts/abi/bind/topics_test.go

File diff suppressed because it is too large
+ 9 - 1
accounts/abi/bind/bind_test.go


+ 6 - 2
accounts/abi/bind/topics.go

@@ -83,8 +83,10 @@ func makeTopics(query ...[]interface{}) ([][]common.Hash, error) {
 				val := reflect.ValueOf(rule)
 
 				switch {
+
+				// static byte array
 				case val.Kind() == reflect.Array && reflect.TypeOf(rule).Elem().Kind() == reflect.Uint8:
-					reflect.Copy(reflect.ValueOf(topic[common.HashLength-val.Len():]), val)
+					reflect.Copy(reflect.ValueOf(topic[:val.Len()]), val)
 
 				default:
 					return nil, fmt.Errorf("unsupported indexed type: %T", rule)
@@ -175,8 +177,10 @@ func parseTopics(out interface{}, fields abi.Arguments, topics []common.Hash) er
 			default:
 				// Ran out of custom types, try the crazies
 				switch {
+
+				// static byte array
 				case arg.Type.T == abi.FixedBytesTy:
-					reflect.Copy(field, reflect.ValueOf(topics[0][common.HashLength-arg.Type.Size:]))
+					reflect.Copy(field, reflect.ValueOf(topics[0][:arg.Type.Size]))
 
 				default:
 					return fmt.Errorf("unsupported indexed type: %v", arg.Type)

+ 103 - 0
accounts/abi/bind/topics_test.go

@@ -0,0 +1,103 @@
+// Copyright 2018 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package bind
+
+import (
+	"reflect"
+	"testing"
+
+	"github.com/ethereum/go-ethereum/accounts/abi"
+	"github.com/ethereum/go-ethereum/common"
+)
+
+func TestMakeTopics(t *testing.T) {
+	type args struct {
+		query [][]interface{}
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    [][]common.Hash
+		wantErr bool
+	}{
+		{
+			"support fixed byte types, right padded to 32 bytes",
+			args{[][]interface{}{{[5]byte{1, 2, 3, 4, 5}}}},
+			[][]common.Hash{{common.Hash{1, 2, 3, 4, 5}}},
+			false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, err := makeTopics(tt.args.query...)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("makeTopics() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("makeTopics() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestParseTopics(t *testing.T) {
+	type bytesStruct struct {
+		StaticBytes [5]byte
+	}
+	bytesType, _ := abi.NewType("bytes5", nil)
+	type args struct {
+		createObj func() interface{}
+		resultObj func() interface{}
+		fields    abi.Arguments
+		topics    []common.Hash
+	}
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		{
+			name: "support fixed byte types, right padded to 32 bytes",
+			args: args{
+				createObj: func() interface{} { return &bytesStruct{} },
+				resultObj: func() interface{} { return &bytesStruct{StaticBytes: [5]byte{1, 2, 3, 4, 5}} },
+				fields: abi.Arguments{abi.Argument{
+					Name:    "staticBytes",
+					Type:    bytesType,
+					Indexed: true,
+				}},
+				topics: []common.Hash{
+					{1, 2, 3, 4, 5},
+				},
+			},
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			createObj := tt.args.createObj()
+			if err := parseTopics(createObj, tt.args.fields, tt.args.topics); (err != nil) != tt.wantErr {
+				t.Errorf("parseTopics() error = %v, wantErr %v", err, tt.wantErr)
+			}
+			resultObj := tt.args.resultObj()
+			if !reflect.DeepEqual(createObj, resultObj) {
+				t.Errorf("parseTopics() = %v, want %v", createObj, resultObj)
+			}
+		})
+	}
+}

Some files were not shown because too many files changed in this diff