Merge branch 'develop' into qt5.4
This commit is contained in:
		
						commit
						8284bef072
					
				
							
								
								
									
										155
									
								
								accounts/abi/abi.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								accounts/abi/abi.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,155 @@ | ||||
| package abi | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| ) | ||||
| 
 | ||||
| // Callable method given a `Name` and whether the method is a constant.
 | ||||
| // If the method is `Const` no transaction needs to be created for this
 | ||||
| // particular Method call. It can easily be simulated using a local VM.
 | ||||
| // For example a `Balance()` method only needs to retrieve something
 | ||||
| // from the storage and therefor requires no Tx to be send to the
 | ||||
| // network. A method such as `Transact` does require a Tx and thus will
 | ||||
| // be flagged `true`.
 | ||||
| // Input specifies the required input parameters for this gives method.
 | ||||
| type Method struct { | ||||
| 	Name   string | ||||
| 	Const  bool | ||||
| 	Input  []Argument | ||||
| 	Return Type // not yet implemented
 | ||||
| } | ||||
| 
 | ||||
| // Returns the methods string signature according to the ABI spec.
 | ||||
| //
 | ||||
| // Example
 | ||||
| //
 | ||||
| //     function foo(uint32 a, int b)    =    "foo(uint32,int256)"
 | ||||
| //
 | ||||
| // Please note that "int" is substitute for its canonical representation "int256"
 | ||||
| func (m Method) String() (out string) { | ||||
| 	out += m.Name | ||||
| 	types := make([]string, len(m.Input)) | ||||
| 	i := 0 | ||||
| 	for _, input := range m.Input { | ||||
| 		types[i] = input.Type.String() | ||||
| 		i++ | ||||
| 	} | ||||
| 	out += "(" + strings.Join(types, ",") + ")" | ||||
| 
 | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (m Method) Id() []byte { | ||||
| 	return crypto.Sha3([]byte(m.String()))[:4] | ||||
| } | ||||
| 
 | ||||
| // Argument holds the name of the argument and the corresponding type.
 | ||||
| // Types are used when packing and testing arguments.
 | ||||
| type Argument struct { | ||||
| 	Name string | ||||
| 	Type Type | ||||
| } | ||||
| 
 | ||||
| func (a *Argument) UnmarshalJSON(data []byte) error { | ||||
| 	var extarg struct { | ||||
| 		Name string | ||||
| 		Type string | ||||
| 	} | ||||
| 	err := json.Unmarshal(data, &extarg) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("argument json err: %v", err) | ||||
| 	} | ||||
| 
 | ||||
| 	a.Type, err = NewType(extarg.Type) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	a.Name = extarg.Name | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // The ABI holds information about a contract's context and available
 | ||||
| // invokable methods. It will allow you to type check function calls and
 | ||||
| // packs data accordingly.
 | ||||
| type ABI struct { | ||||
| 	Methods map[string]Method | ||||
| } | ||||
| 
 | ||||
| // tests, tests whether the given input would result in a successful
 | ||||
| // call. Checks argument list count and matches input to `input`.
 | ||||
| func (abi ABI) pack(name string, args ...interface{}) ([]byte, error) { | ||||
| 	method := abi.Methods[name] | ||||
| 
 | ||||
| 	var ret []byte | ||||
| 	for i, a := range args { | ||||
| 		input := method.Input[i] | ||||
| 
 | ||||
| 		packed, err := input.Type.pack(a) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("`%s` %v", name, err) | ||||
| 		} | ||||
| 		ret = append(ret, packed...) | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	return ret, nil | ||||
| } | ||||
| 
 | ||||
| // Pack the given method name to conform the ABI. Method call's data
 | ||||
| // will consist of method_id, args0, arg1, ... argN. Method id consists
 | ||||
| // of 4 bytes and arguments are all 32 bytes.
 | ||||
| // Method ids are created from the first 4 bytes of the hash of the
 | ||||
| // methods string signature. (signature = baz(uint32,string32))
 | ||||
| func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) { | ||||
| 	method, exist := abi.Methods[name] | ||||
| 	if !exist { | ||||
| 		return nil, fmt.Errorf("method '%s' not found", name) | ||||
| 	} | ||||
| 
 | ||||
| 	// start with argument count match
 | ||||
| 	if len(args) != len(method.Input) { | ||||
| 		return nil, fmt.Errorf("argument count mismatch: %d for %d", len(args), len(method.Input)) | ||||
| 	} | ||||
| 
 | ||||
| 	arguments, err := abi.pack(name, args...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Set function id
 | ||||
| 	packed := abi.Methods[name].Id() | ||||
| 	packed = append(packed, arguments...) | ||||
| 
 | ||||
| 	return packed, nil | ||||
| } | ||||
| 
 | ||||
| func (abi *ABI) UnmarshalJSON(data []byte) error { | ||||
| 	var methods []Method | ||||
| 	if err := json.Unmarshal(data, &methods); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	abi.Methods = make(map[string]Method) | ||||
| 	for _, method := range methods { | ||||
| 		abi.Methods[method.Name] = method | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func JSON(reader io.Reader) (ABI, error) { | ||||
| 	dec := json.NewDecoder(reader) | ||||
| 
 | ||||
| 	var abi ABI | ||||
| 	if err := dec.Decode(&abi); err != nil { | ||||
| 		return ABI{}, err | ||||
| 	} | ||||
| 
 | ||||
| 	return abi, nil | ||||
| } | ||||
							
								
								
									
										330
									
								
								accounts/abi/abi_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										330
									
								
								accounts/abi/abi_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,330 @@ | ||||
| package abi | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"math/big" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| ) | ||||
| 
 | ||||
| const jsondata = ` | ||||
| [ | ||||
| 	{ "name" : "balance", "const" : true }, | ||||
| 	{ "name" : "send", "const" : false, "input" : [ { "name" : "amount", "type" : "uint256" } ] } | ||||
| ]` | ||||
| 
 | ||||
| const jsondata2 = ` | ||||
| [ | ||||
| 	{ "name" : "balance", "const" : true }, | ||||
| 	{ "name" : "send", "const" : false, "input" : [ { "name" : "amount", "type" : "uint256" } ] }, | ||||
| 	{ "name" : "test", "const" : false, "input" : [ { "name" : "number", "type" : "uint32" } ] }, | ||||
| 	{ "name" : "string", "const" : false, "input" : [ { "name" : "input", "type" : "string" } ] }, | ||||
| 	{ "name" : "bool", "const" : false, "input" : [ { "name" : "input", "type" : "bool" } ] }, | ||||
| 	{ "name" : "address", "const" : false, "input" : [ { "name" : "input", "type" : "address" } ] }, | ||||
| 	{ "name" : "string32", "const" : false, "input" : [ { "name" : "input", "type" : "string32" } ] }, | ||||
| 	{ "name" : "uint64[2]", "const" : false, "input" : [ { "name" : "input", "type" : "uint64[2]" } ] }, | ||||
| 	{ "name" : "uint64[]", "const" : false, "input" : [ { "name" : "input", "type" : "uint64[]" } ] }, | ||||
| 	{ "name" : "foo", "const" : false, "input" : [ { "name" : "input", "type" : "uint32" } ] }, | ||||
| 	{ "name" : "bar", "const" : false, "input" : [ { "name" : "input", "type" : "uint32" }, { "name" : "string", "type" : "uint16" } ] }, | ||||
| 	{ "name" : "slice", "const" : false, "input" : [ { "name" : "input", "type" : "uint32[2]" } ] }, | ||||
| 	{ "name" : "slice256", "const" : false, "input" : [ { "name" : "input", "type" : "uint256[2]" } ] } | ||||
| ]` | ||||
| 
 | ||||
| func TestType(t *testing.T) { | ||||
| 	typ, err := NewType("uint32") | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
| 	if typ.Kind != reflect.Ptr { | ||||
| 		t.Error("expected uint32 to have kind Ptr") | ||||
| 	} | ||||
| 
 | ||||
| 	typ, err = NewType("uint32[]") | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
| 	if typ.Kind != reflect.Slice { | ||||
| 		t.Error("expected uint32[] to have type slice") | ||||
| 	} | ||||
| 	if typ.Type != ubig_ts { | ||||
| 		t.Error("expcted uith32[] to have type uint64") | ||||
| 	} | ||||
| 
 | ||||
| 	typ, err = NewType("uint32[2]") | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
| 	if typ.Kind != reflect.Slice { | ||||
| 		t.Error("expected uint32[2] to have kind slice") | ||||
| 	} | ||||
| 	if typ.Type != ubig_ts { | ||||
| 		t.Error("expcted uith32[2] to have type uint64") | ||||
| 	} | ||||
| 	if typ.Size != 2 { | ||||
| 		t.Error("expected uint32[2] to have a size of 2") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestReader(t *testing.T) { | ||||
| 	Uint256, _ := NewType("uint256") | ||||
| 	exp := ABI{ | ||||
| 		Methods: map[string]Method{ | ||||
| 			"balance": Method{ | ||||
| 				"balance", true, nil, Type{}, | ||||
| 			}, | ||||
| 			"send": Method{ | ||||
| 				"send", false, []Argument{ | ||||
| 					Argument{"amount", Uint256}, | ||||
| 				}, Type{}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	abi, err := JSON(strings.NewReader(jsondata)) | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
| 
 | ||||
| 	// deep equal fails for some reason
 | ||||
| 	t.Skip() | ||||
| 	if !reflect.DeepEqual(abi, exp) { | ||||
| 		t.Errorf("\nabi: %v\ndoes not match exp: %v", abi, exp) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestTestNumbers(t *testing.T) { | ||||
| 	abi, err := JSON(strings.NewReader(jsondata2)) | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 		t.FailNow() | ||||
| 	} | ||||
| 
 | ||||
| 	if _, err := abi.Pack("balance"); err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
| 
 | ||||
| 	if _, err := abi.Pack("balance", 1); err == nil { | ||||
| 		t.Error("expected error for balance(1)") | ||||
| 	} | ||||
| 
 | ||||
| 	if _, err := abi.Pack("doesntexist", nil); err == nil { | ||||
| 		t.Errorf("doesntexist shouldn't exist") | ||||
| 	} | ||||
| 
 | ||||
| 	if _, err := abi.Pack("doesntexist", 1); err == nil { | ||||
| 		t.Errorf("doesntexist(1) shouldn't exist") | ||||
| 	} | ||||
| 
 | ||||
| 	if _, err := abi.Pack("send", big.NewInt(1000)); err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
| 
 | ||||
| 	i := new(int) | ||||
| 	*i = 1000 | ||||
| 	if _, err := abi.Pack("send", i); err == nil { | ||||
| 		t.Errorf("expected send( ptr ) to throw, requires *big.Int instead of *int") | ||||
| 	} | ||||
| 
 | ||||
| 	if _, err := abi.Pack("send", 1000); err != nil { | ||||
| 		t.Error("expected send(1000) to cast to big") | ||||
| 	} | ||||
| 
 | ||||
| 	if _, err := abi.Pack("test", uint32(1000)); err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestTestString(t *testing.T) { | ||||
| 	abi, err := JSON(strings.NewReader(jsondata2)) | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 		t.FailNow() | ||||
| 	} | ||||
| 
 | ||||
| 	if _, err := abi.Pack("string", "hello world"); err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
| 
 | ||||
| 	str10 := string(make([]byte, 10)) | ||||
| 	if _, err := abi.Pack("string32", str10); err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
| 
 | ||||
| 	str32 := string(make([]byte, 32)) | ||||
| 	if _, err := abi.Pack("string32", str32); err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
| 
 | ||||
| 	str33 := string(make([]byte, 33)) | ||||
| 	if _, err := abi.Pack("string32", str33); err == nil { | ||||
| 		t.Error("expected str33 to throw out of bound error") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestTestBool(t *testing.T) { | ||||
| 	abi, err := JSON(strings.NewReader(jsondata2)) | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 		t.FailNow() | ||||
| 	} | ||||
| 
 | ||||
| 	if _, err := abi.Pack("bool", true); err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestTestSlice(t *testing.T) { | ||||
| 	abi, err := JSON(strings.NewReader(jsondata2)) | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 		t.FailNow() | ||||
| 	} | ||||
| 
 | ||||
| 	addr := make([]byte, 20) | ||||
| 	if _, err := abi.Pack("address", addr); err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
| 
 | ||||
| 	addr = make([]byte, 21) | ||||
| 	if _, err := abi.Pack("address", addr); err == nil { | ||||
| 		t.Error("expected address of 21 width to throw") | ||||
| 	} | ||||
| 
 | ||||
| 	slice := make([]byte, 2) | ||||
| 	if _, err := abi.Pack("uint64[2]", slice); err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
| 
 | ||||
| 	if _, err := abi.Pack("uint64[]", slice); err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestTestAddress(t *testing.T) { | ||||
| 	abi, err := JSON(strings.NewReader(jsondata2)) | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 		t.FailNow() | ||||
| 	} | ||||
| 
 | ||||
| 	addr := make([]byte, 20) | ||||
| 	if _, err := abi.Pack("address", addr); err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestMethodSignature(t *testing.T) { | ||||
| 	String, _ := NewType("string") | ||||
| 	String32, _ := NewType("string32") | ||||
| 	m := Method{"foo", false, []Argument{Argument{"bar", String32}, Argument{"baz", String}}, Type{}} | ||||
| 	exp := "foo(string32,string)" | ||||
| 	if m.String() != exp { | ||||
| 		t.Error("signature mismatch", exp, "!=", m.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	idexp := crypto.Sha3([]byte(exp))[:4] | ||||
| 	if !bytes.Equal(m.Id(), idexp) { | ||||
| 		t.Errorf("expected ids to match %x != %x", m.Id(), idexp) | ||||
| 	} | ||||
| 
 | ||||
| 	uintt, _ := NewType("uint") | ||||
| 	m = Method{"foo", false, []Argument{Argument{"bar", uintt}}, Type{}} | ||||
| 	exp = "foo(uint256)" | ||||
| 	if m.String() != exp { | ||||
| 		t.Error("signature mismatch", exp, "!=", m.String()) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestPack(t *testing.T) { | ||||
| 	abi, err := JSON(strings.NewReader(jsondata2)) | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 		t.FailNow() | ||||
| 	} | ||||
| 
 | ||||
| 	sig := crypto.Sha3([]byte("foo(uint32)"))[:4] | ||||
| 	sig = append(sig, make([]byte, 32)...) | ||||
| 	sig[35] = 10 | ||||
| 
 | ||||
| 	packed, err := abi.Pack("foo", uint32(10)) | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 		t.FailNow() | ||||
| 	} | ||||
| 
 | ||||
| 	if !bytes.Equal(packed, sig) { | ||||
| 		t.Errorf("expected %x got %x", sig, packed) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestMultiPack(t *testing.T) { | ||||
| 	abi, err := JSON(strings.NewReader(jsondata2)) | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 		t.FailNow() | ||||
| 	} | ||||
| 
 | ||||
| 	sig := crypto.Sha3([]byte("bar(uint32,uint16)"))[:4] | ||||
| 	sig = append(sig, make([]byte, 64)...) | ||||
| 	sig[35] = 10 | ||||
| 	sig[67] = 11 | ||||
| 
 | ||||
| 	packed, err := abi.Pack("bar", uint32(10), uint16(11)) | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 		t.FailNow() | ||||
| 	} | ||||
| 
 | ||||
| 	if !bytes.Equal(packed, sig) { | ||||
| 		t.Errorf("expected %x got %x", sig, packed) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestPackSlice(t *testing.T) { | ||||
| 	abi, err := JSON(strings.NewReader(jsondata2)) | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 		t.FailNow() | ||||
| 	} | ||||
| 
 | ||||
| 	sig := crypto.Sha3([]byte("slice(uint32[2])"))[:4] | ||||
| 	sig = append(sig, make([]byte, 64)...) | ||||
| 	sig[35] = 1 | ||||
| 	sig[67] = 2 | ||||
| 
 | ||||
| 	packed, err := abi.Pack("slice", []uint32{1, 2}) | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 		t.FailNow() | ||||
| 	} | ||||
| 
 | ||||
| 	if !bytes.Equal(packed, sig) { | ||||
| 		t.Errorf("expected %x got %x", sig, packed) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestPackSliceBig(t *testing.T) { | ||||
| 	abi, err := JSON(strings.NewReader(jsondata2)) | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 		t.FailNow() | ||||
| 	} | ||||
| 
 | ||||
| 	sig := crypto.Sha3([]byte("slice256(uint256[2])"))[:4] | ||||
| 	sig = append(sig, make([]byte, 64)...) | ||||
| 	sig[35] = 1 | ||||
| 	sig[67] = 2 | ||||
| 
 | ||||
| 	packed, err := abi.Pack("slice256", []*big.Int{big.NewInt(1), big.NewInt(2)}) | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 		t.FailNow() | ||||
| 	} | ||||
| 
 | ||||
| 	if !bytes.Equal(packed, sig) { | ||||
| 		t.Errorf("expected %x got %x", sig, packed) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										10
									
								
								accounts/abi/doc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								accounts/abi/doc.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| // Package abi implements the Ethereum ABI (Application Binary
 | ||||
| // Interface).
 | ||||
| //
 | ||||
| // The Ethereum ABI is strongly typed, known at compile time
 | ||||
| // and static. This ABI will handle basic type casting; unsigned
 | ||||
| // to signed and visa versa. It does not handle slice casting such
 | ||||
| // as unsigned slice to signed slice. Bit size type casting is also
 | ||||
| // handled. ints with a bit size of 32 will be properly cast to int256,
 | ||||
| // etc.
 | ||||
| package abi | ||||
							
								
								
									
										106
									
								
								accounts/abi/numbers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								accounts/abi/numbers.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,106 @@ | ||||
| package abi | ||||
| 
 | ||||
| import ( | ||||
| 	"math/big" | ||||
| 	"reflect" | ||||
| 
 | ||||
| 	"github.com/ethereum/go-ethereum/ethutil" | ||||
| ) | ||||
| 
 | ||||
| var big_t = reflect.TypeOf(&big.Int{}) | ||||
| var ubig_t = reflect.TypeOf(&big.Int{}) | ||||
| var byte_t = reflect.TypeOf(byte(0)) | ||||
| var byte_ts = reflect.TypeOf([]byte(nil)) | ||||
| var uint_t = reflect.TypeOf(uint(0)) | ||||
| var uint8_t = reflect.TypeOf(uint8(0)) | ||||
| var uint16_t = reflect.TypeOf(uint16(0)) | ||||
| var uint32_t = reflect.TypeOf(uint32(0)) | ||||
| var uint64_t = reflect.TypeOf(uint64(0)) | ||||
| var int_t = reflect.TypeOf(int(0)) | ||||
| var int8_t = reflect.TypeOf(int8(0)) | ||||
| var int16_t = reflect.TypeOf(int16(0)) | ||||
| var int32_t = reflect.TypeOf(int32(0)) | ||||
| var int64_t = reflect.TypeOf(int64(0)) | ||||
| 
 | ||||
| var uint_ts = reflect.TypeOf([]uint(nil)) | ||||
| var uint8_ts = reflect.TypeOf([]uint8(nil)) | ||||
| var uint16_ts = reflect.TypeOf([]uint16(nil)) | ||||
| var uint32_ts = reflect.TypeOf([]uint32(nil)) | ||||
| var uint64_ts = reflect.TypeOf([]uint64(nil)) | ||||
| var ubig_ts = reflect.TypeOf([]*big.Int(nil)) | ||||
| 
 | ||||
| var int_ts = reflect.TypeOf([]int(nil)) | ||||
| var int8_ts = reflect.TypeOf([]int8(nil)) | ||||
| var int16_ts = reflect.TypeOf([]int16(nil)) | ||||
| var int32_ts = reflect.TypeOf([]int32(nil)) | ||||
| var int64_ts = reflect.TypeOf([]int64(nil)) | ||||
| var big_ts = reflect.TypeOf([]*big.Int(nil)) | ||||
| 
 | ||||
| // U256 will ensure unsigned 256bit on big nums
 | ||||
| func U256(n *big.Int) []byte { | ||||
| 	return ethutil.LeftPadBytes(ethutil.U256(n).Bytes(), 32) | ||||
| } | ||||
| 
 | ||||
| func S256(n *big.Int) []byte { | ||||
| 	sint := ethutil.S256(n) | ||||
| 	ret := ethutil.LeftPadBytes(sint.Bytes(), 32) | ||||
| 	if sint.Cmp(ethutil.Big0) < 0 { | ||||
| 		for i, b := range ret { | ||||
| 			if b == 0 { | ||||
| 				ret[i] = 1 | ||||
| 				continue | ||||
| 			} | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return ret | ||||
| } | ||||
| 
 | ||||
| // S256 will ensure signed 256bit on big nums
 | ||||
| func U2U256(n uint64) []byte { | ||||
| 	return U256(big.NewInt(int64(n))) | ||||
| } | ||||
| 
 | ||||
| func S2S256(n int64) []byte { | ||||
| 	return S256(big.NewInt(n)) | ||||
| } | ||||
| 
 | ||||
| // packNum packs the given number (using the reflect value) and will cast it to appropriate number representation
 | ||||
| func packNum(value reflect.Value, to byte) []byte { | ||||
| 	switch kind := value.Kind(); kind { | ||||
| 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||||
| 		if to == UintTy { | ||||
| 			return U2U256(value.Uint()) | ||||
| 		} else { | ||||
| 			return S2S256(int64(value.Uint())) | ||||
| 		} | ||||
| 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||||
| 		if to == UintTy { | ||||
| 			return U2U256(uint64(value.Int())) | ||||
| 		} else { | ||||
| 			return S2S256(value.Int()) | ||||
| 		} | ||||
| 	case reflect.Ptr: | ||||
| 		// This only takes care of packing and casting. No type checking is done here. It should be done prior to using this function.
 | ||||
| 		if to == UintTy { | ||||
| 			return U256(value.Interface().(*big.Int)) | ||||
| 		} else { | ||||
| 			return S256(value.Interface().(*big.Int)) | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // checks whether the given reflect value is signed. This also works for slices with a number type
 | ||||
| func isSigned(v reflect.Value) bool { | ||||
| 	switch v.Type() { | ||||
| 	case ubig_ts, big_ts, big_t, ubig_t: | ||||
| 		return true | ||||
| 	case int_ts, int8_ts, int16_ts, int32_ts, int64_ts, int_t, int8_t, int16_t, int32_t, int64_t: | ||||
| 		return true | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
							
								
								
									
										72
									
								
								accounts/abi/numbers_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								accounts/abi/numbers_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,72 @@ | ||||
| package abi | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"math/big" | ||||
| 	"reflect" | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| func TestNumberTypes(t *testing.T) { | ||||
| 	ubytes := make([]byte, 32) | ||||
| 	ubytes[31] = 1 | ||||
| 	sbytesmin := []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} | ||||
| 
 | ||||
| 	unsigned := U256(big.NewInt(1)) | ||||
| 	if !bytes.Equal(unsigned, ubytes) { | ||||
| 		t.Error("expected %x got %x", ubytes, unsigned) | ||||
| 	} | ||||
| 
 | ||||
| 	signed := S256(big.NewInt(1)) | ||||
| 	if !bytes.Equal(signed, ubytes) { | ||||
| 		t.Error("expected %x got %x", ubytes, unsigned) | ||||
| 	} | ||||
| 
 | ||||
| 	signed = S256(big.NewInt(-1)) | ||||
| 	if !bytes.Equal(signed, sbytesmin) { | ||||
| 		t.Error("expected %x got %x", ubytes, unsigned) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestPackNumber(t *testing.T) { | ||||
| 	ubytes := make([]byte, 32) | ||||
| 	ubytes[31] = 1 | ||||
| 	sbytesmin := []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} | ||||
| 	maxunsigned := []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} | ||||
| 
 | ||||
| 	packed := packNum(reflect.ValueOf(1), IntTy) | ||||
| 	if !bytes.Equal(packed, ubytes) { | ||||
| 		t.Errorf("expected %x got %x", ubytes, packed) | ||||
| 	} | ||||
| 	packed = packNum(reflect.ValueOf(-1), IntTy) | ||||
| 	if !bytes.Equal(packed, sbytesmin) { | ||||
| 		t.Errorf("expected %x got %x", ubytes, packed) | ||||
| 	} | ||||
| 	packed = packNum(reflect.ValueOf(1), UintTy) | ||||
| 	if !bytes.Equal(packed, ubytes) { | ||||
| 		t.Errorf("expected %x got %x", ubytes, packed) | ||||
| 	} | ||||
| 	packed = packNum(reflect.ValueOf(-1), UintTy) | ||||
| 	if !bytes.Equal(packed, maxunsigned) { | ||||
| 		t.Errorf("expected %x got %x", maxunsigned, packed) | ||||
| 	} | ||||
| 
 | ||||
| 	packed = packNum(reflect.ValueOf("string"), UintTy) | ||||
| 	if packed != nil { | ||||
| 		t.Errorf("expected 'string' to pack to nil. got %x instead", packed) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestSigned(t *testing.T) { | ||||
| 	if isSigned(reflect.ValueOf(uint(10))) { | ||||
| 		t.Error() | ||||
| 	} | ||||
| 
 | ||||
| 	if !isSigned(reflect.ValueOf(int(10))) { | ||||
| 		t.Error() | ||||
| 	} | ||||
| 
 | ||||
| 	if !isSigned(reflect.ValueOf(big.NewInt(10))) { | ||||
| 		t.Error() | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										106
									
								
								accounts/abi/profile.cov
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								accounts/abi/profile.cov
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,106 @@ | ||||
| mode: set | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:27.39,31.32 4 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:35.2,37.8 2 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:31.32,34.3 2 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:40.29,42.2 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:51.53,57.16 3 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:61.2,62.16 2 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:65.2,67.12 2 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:57.16,59.3 1 0 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:62.16,64.3 1 0 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:79.71,83.25 3 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:94.2,94.17 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:83.25,87.17 3 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:90.3,90.31 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:87.17,89.4 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:102.71,104.12 2 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:109.2,109.36 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:113.2,114.16 2 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:119.2,122.20 3 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:104.12,106.3 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:109.36,111.3 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:114.16,116.3 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:125.50,127.55 2 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:131.2,132.33 2 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:136.2,136.12 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:127.55,129.3 1 0 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:132.33,134.3 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:139.42,143.41 3 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:147.2,147.17 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/abi.go:143.41,145.3 1 0 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:39.30,41.2 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:43.30,46.32 3 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:56.2,56.12 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:46.32,47.25 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:47.25,48.14 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:52.4,52.9 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:48.14,50.13 2 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:59.30,61.2 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:63.29,65.2 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:67.51,68.36 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:91.2,91.12 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:69.2,70.19 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:75.2,76.19 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:81.2,83.19 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:70.19,72.4 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:72.4,74.4 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:76.19,78.4 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:78.4,80.4 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:83.19,85.4 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:85.4,87.4 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:94.37,95.18 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:101.2,101.14 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:96.2,97.14 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/numbers.go:98.2,99.14 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:32.46,35.16 2 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:38.2,43.9 3 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:55.2,56.16 2 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:60.2,64.55 4 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:69.2,69.13 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:111.2,113.8 2 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:35.16,37.3 1 0 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:44.2,47.17 2 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:48.2,50.12 2 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:51.2,52.60 1 0 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:56.16,58.3 1 0 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:64.55,67.3 2 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:69.13,72.16 3 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:73.3,74.21 1 0 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:75.3,76.22 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:77.3,78.66 1 0 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:80.3,81.16 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:82.3,86.17 4 0 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:87.3,91.18 4 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:92.3,93.27 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:94.3,95.30 1 0 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:96.3,100.21 4 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:101.3,104.17 3 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:107.3,108.60 1 0 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:104.17,106.5 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:116.37,118.2 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:126.51,128.36 2 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:179.2,179.20 1 0 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:129.2,130.23 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:133.3,133.34 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:134.2,135.23 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:138.3,138.34 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:139.2,142.49 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:145.3,145.34 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:146.2,147.42 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:150.3,150.60 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:151.2,152.42 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:157.3,157.23 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:162.3,162.78 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:166.3,167.36 2 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:170.3,170.21 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:171.2,172.19 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:130.23,132.4 1 0 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:135.23,137.4 1 0 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:142.49,144.4 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:147.42,149.4 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:152.42,154.4 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:157.23,159.4 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:162.78,164.4 1 0 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:167.36,169.4 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:172.19,174.4 1 1 | ||||
| github.com/ethereum/go-ethereum/abi/type.go:174.4,176.4 1 0 | ||||
							
								
								
									
										190
									
								
								accounts/abi/type.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								accounts/abi/type.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,190 @@ | ||||
| package abi | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 	"regexp" | ||||
| 	"strconv" | ||||
| 
 | ||||
| 	"github.com/ethereum/go-ethereum/ethutil" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	IntTy byte = iota | ||||
| 	UintTy | ||||
| 	BoolTy | ||||
| 	SliceTy | ||||
| 	AddressTy | ||||
| 	RealTy | ||||
| ) | ||||
| 
 | ||||
| // Type is the reflection of the supported argument type
 | ||||
| type Type struct { | ||||
| 	Kind       reflect.Kind | ||||
| 	Type       reflect.Type | ||||
| 	Size       int | ||||
| 	T          byte   // Our own type checking
 | ||||
| 	stringKind string // holds the unparsed string for deriving signatures
 | ||||
| } | ||||
| 
 | ||||
| // New type returns a fully parsed Type given by the input string or an error if it  can't be parsed.
 | ||||
| //
 | ||||
| // Strings can be in the format of:
 | ||||
| //
 | ||||
| // 	Input  = Type [ "[" [ Number ] "]" ] Name .
 | ||||
| // 	Type   = [ "u" ] "int" [ Number ] .
 | ||||
| //
 | ||||
| // Examples:
 | ||||
| //
 | ||||
| //      string     int       uint       real
 | ||||
| //      string32   int8      uint8      uint[]
 | ||||
| //      address    int256    uint256    real[2]
 | ||||
| func NewType(t string) (typ Type, err error) { | ||||
| 	// 1. full string 2. type 3. (opt.) is slice 4. (opt.) size
 | ||||
| 	freg, err := regexp.Compile("([a-zA-Z0-9]+)(\\[([0-9]*)?\\])?") | ||||
| 	if err != nil { | ||||
| 		return Type{}, err | ||||
| 	} | ||||
| 	res := freg.FindAllStringSubmatch(t, -1)[0] | ||||
| 	var ( | ||||
| 		isslice bool | ||||
| 		size    int | ||||
| 	) | ||||
| 	switch { | ||||
| 	case res[3] != "": | ||||
| 		// err is ignored. Already checked for number through the regexp
 | ||||
| 		size, _ = strconv.Atoi(res[3]) | ||||
| 		isslice = true | ||||
| 	case res[2] != "": | ||||
| 		isslice = true | ||||
| 		size = -1 | ||||
| 	case res[0] == "": | ||||
| 		return Type{}, fmt.Errorf("type parse error for `%s`", t) | ||||
| 	} | ||||
| 
 | ||||
| 	treg, err := regexp.Compile("([a-zA-Z]+)([0-9]*)?") | ||||
| 	if err != nil { | ||||
| 		return Type{}, err | ||||
| 	} | ||||
| 
 | ||||
| 	parsedType := treg.FindAllStringSubmatch(res[1], -1)[0] | ||||
| 	vsize, _ := strconv.Atoi(parsedType[2]) | ||||
| 	vtype := parsedType[1] | ||||
| 	// substitute canonical representation
 | ||||
| 	if vsize == 0 && (vtype == "int" || vtype == "uint") { | ||||
| 		vsize = 256 | ||||
| 		t += "256" | ||||
| 	} | ||||
| 
 | ||||
| 	if isslice { | ||||
| 		typ.Kind = reflect.Slice | ||||
| 		typ.Size = size | ||||
| 		switch vtype { | ||||
| 		case "int": | ||||
| 			typ.Type = big_ts | ||||
| 		case "uint": | ||||
| 			typ.Type = ubig_ts | ||||
| 		default: | ||||
| 			return Type{}, fmt.Errorf("unsupported arg slice type: %s", t) | ||||
| 		} | ||||
| 	} else { | ||||
| 		switch vtype { | ||||
| 		case "int": | ||||
| 			typ.Kind = reflect.Ptr | ||||
| 			typ.Type = big_t | ||||
| 			typ.Size = 256 | ||||
| 			typ.T = IntTy | ||||
| 		case "uint": | ||||
| 			typ.Kind = reflect.Ptr | ||||
| 			typ.Type = ubig_t | ||||
| 			typ.Size = 256 | ||||
| 			typ.T = UintTy | ||||
| 		case "bool": | ||||
| 			typ.Kind = reflect.Bool | ||||
| 		case "real": // TODO
 | ||||
| 			typ.Kind = reflect.Invalid | ||||
| 		case "address": | ||||
| 			typ.Kind = reflect.Slice | ||||
| 			typ.Type = byte_ts | ||||
| 			typ.Size = 20 | ||||
| 			typ.T = AddressTy | ||||
| 		case "string": | ||||
| 			typ.Kind = reflect.String | ||||
| 			typ.Size = -1 | ||||
| 			if vsize > 0 { | ||||
| 				typ.Size = 32 | ||||
| 			} | ||||
| 		default: | ||||
| 			return Type{}, fmt.Errorf("unsupported arg type: %s", t) | ||||
| 		} | ||||
| 	} | ||||
| 	typ.stringKind = t | ||||
| 
 | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (t Type) String() (out string) { | ||||
| 	return t.stringKind | ||||
| } | ||||
| 
 | ||||
| // Test the given input parameter `v` and checks if it matches certain
 | ||||
| // criteria
 | ||||
| // * Big integers are checks for ptr types and if the given value is
 | ||||
| //   assignable
 | ||||
| // * Integer are checked for size
 | ||||
| // * Strings, addresses and bytes are checks for type and size
 | ||||
| func (t Type) pack(v interface{}) ([]byte, error) { | ||||
| 	value := reflect.ValueOf(v) | ||||
| 	switch kind := value.Kind(); kind { | ||||
| 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||||
| 		if t.Type != ubig_t { | ||||
| 			return nil, fmt.Errorf("type mismatch: %s for %T", t.Type, v) | ||||
| 		} | ||||
| 		return packNum(value, t.T), nil | ||||
| 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||||
| 		if t.Type != ubig_t { | ||||
| 			return nil, fmt.Errorf("type mismatch: %s for %T", t.Type, v) | ||||
| 		} | ||||
| 		return packNum(value, t.T), nil | ||||
| 	case reflect.Ptr: | ||||
| 		// If the value is a ptr do a assign check (only used by
 | ||||
| 		// big.Int for now)
 | ||||
| 		if t.Type == ubig_t && value.Type() != ubig_t { | ||||
| 			return nil, fmt.Errorf("type mismatch: %s for %T", t.Type, v) | ||||
| 		} | ||||
| 		return packNum(value, t.T), nil | ||||
| 	case reflect.String: | ||||
| 		if t.Size > -1 && value.Len() > t.Size { | ||||
| 			return nil, fmt.Errorf("%v out of bound. %d for %d", value.Kind(), value.Len(), t.Size) | ||||
| 		} | ||||
| 		return []byte(ethutil.LeftPadString(t.String(), 32)), nil | ||||
| 	case reflect.Slice: | ||||
| 		if t.Size > -1 && value.Len() > t.Size { | ||||
| 			return nil, fmt.Errorf("%v out of bound. %d for %d", value.Kind(), value.Len(), t.Size) | ||||
| 		} | ||||
| 
 | ||||
| 		// Address is a special slice. The slice acts as one rather than a list of elements.
 | ||||
| 		if t.T == AddressTy { | ||||
| 			return ethutil.LeftPadBytes(v.([]byte), 32), nil | ||||
| 		} | ||||
| 
 | ||||
| 		// Signed / Unsigned check
 | ||||
| 		if (t.T != IntTy && isSigned(value)) || (t.T == UintTy && isSigned(value)) { | ||||
| 			return nil, fmt.Errorf("slice of incompatible types.") | ||||
| 		} | ||||
| 
 | ||||
| 		var packed []byte | ||||
| 		for i := 0; i < value.Len(); i++ { | ||||
| 			packed = append(packed, packNum(value.Index(i), t.T)...) | ||||
| 		} | ||||
| 		return packed, nil | ||||
| 	case reflect.Bool: | ||||
| 		if value.Bool() { | ||||
| 			return ethutil.LeftPadBytes(ethutil.Big1.Bytes(), 32), nil | ||||
| 		} else { | ||||
| 			return ethutil.LeftPadBytes(ethutil.Big0.Bytes(), 32), nil | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	panic("unreached") | ||||
| } | ||||
							
								
								
									
										95
									
								
								accounts/account_manager.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								accounts/account_manager.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,95 @@ | ||||
| /* | ||||
| 	This file is part of go-ethereum | ||||
| 
 | ||||
| 	go-ethereum 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. | ||||
| 
 | ||||
| 	go-ethereum 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 General Public License for more details. | ||||
| 
 | ||||
| 	You should have received a copy of the GNU Lesser General Public License | ||||
| 	along with go-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
| */ | ||||
| /** | ||||
|  * @authors | ||||
|  * 	Gustav Simonsson <gustav.simonsson@gmail.com> | ||||
|  * @date 2015 | ||||
|  * | ||||
|  */ | ||||
| /* | ||||
| 
 | ||||
| This abstracts part of a user's interaction with an account she controls. | ||||
| It's not an abstraction of core Ethereum accounts data type / logic - | ||||
| for that see the core processing code of blocks / txs. | ||||
| 
 | ||||
| Currently this is pretty much a passthrough to the KeyStore2 interface, | ||||
| and accounts persistence is derived from stored keys' addresses | ||||
| 
 | ||||
| */ | ||||
| package accounts | ||||
| 
 | ||||
| import ( | ||||
| 	crand "crypto/rand" | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| ) | ||||
| 
 | ||||
| // TODO: better name for this struct?
 | ||||
| type Account struct { | ||||
| 	Address []byte | ||||
| } | ||||
| 
 | ||||
| type AccountManager struct { | ||||
| 	keyStore crypto.KeyStore2 | ||||
| } | ||||
| 
 | ||||
| // TODO: get key by addr - modify KeyStore2 GetKey to work with addr
 | ||||
| 
 | ||||
| // TODO: pass through passphrase for APIs which require access to private key?
 | ||||
| func NewAccountManager(keyStore crypto.KeyStore2) AccountManager { | ||||
| 	am := &AccountManager{ | ||||
| 		keyStore: keyStore, | ||||
| 	} | ||||
| 	return *am | ||||
| } | ||||
| 
 | ||||
| func (am *AccountManager) Sign(fromAccount *Account, keyAuth string, toSign []byte) (signature []byte, err error) { | ||||
| 	key, err := am.keyStore.GetKey(fromAccount.Address, keyAuth) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	signature, err = crypto.Sign(toSign, key.PrivateKey) | ||||
| 	return signature, err | ||||
| } | ||||
| 
 | ||||
| func (am AccountManager) NewAccount(auth string) (*Account, error) { | ||||
| 	key, err := am.keyStore.GenerateNewKey(crand.Reader, auth) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	ua := &Account{ | ||||
| 		Address: key.Address, | ||||
| 	} | ||||
| 	return ua, err | ||||
| } | ||||
| 
 | ||||
| // set of accounts == set of keys in given key store
 | ||||
| // TODO: do we need persistence of accounts as well?
 | ||||
| func (am *AccountManager) Accounts() ([]Account, error) { | ||||
| 	addresses, err := am.keyStore.GetKeyAddresses() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	accounts := make([]Account, len(addresses)) | ||||
| 
 | ||||
| 	for i, addr := range addresses { | ||||
| 		accounts[i] = Account{ | ||||
| 			Address: addr, | ||||
| 		} | ||||
| 	} | ||||
| 	return accounts, err | ||||
| } | ||||
							
								
								
									
										18
									
								
								accounts/accounts_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								accounts/accounts_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| package accounts | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| func TestAccountManager(t *testing.T) { | ||||
| 	ks := crypto.NewKeyStorePlain(crypto.DefaultDataDir()) | ||||
| 	am := NewAccountManager(ks) | ||||
| 	pass := "" // not used but required by API
 | ||||
| 	a1, err := am.NewAccount(pass) | ||||
| 	toSign := crypto.GetEntropyCSPRNG(32) | ||||
| 	_, err = am.Sign(a1, pass, toSign) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| } | ||||
| @ -133,8 +133,7 @@ func ImportPreSaleKey(keyStore KeyStore2, keyJSON []byte, password string) (*Key | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	id := uuid.NewRandom() | ||||
| 	key.Id = &id | ||||
| 	key.Id = uuid.NewRandom() | ||||
| 	err = keyStore.StoreKey(key, password) | ||||
| 	return key, err | ||||
| } | ||||
| @ -167,9 +166,10 @@ func decryptPreSaleKey(fileContent []byte, password string) (key *Key, err error | ||||
| 	ecKey := ToECDSA(ethPriv) | ||||
| 	key = &Key{ | ||||
| 		Id:         nil, | ||||
| 		Address:    PubkeyToAddress(ecKey.PublicKey), | ||||
| 		PrivateKey: ecKey, | ||||
| 	} | ||||
| 	derivedAddr := ethutil.Bytes2Hex(key.Address()) | ||||
| 	derivedAddr := ethutil.Bytes2Hex(key.Address) | ||||
| 	expectedAddr := preSaleKeyStruct.EthAddr | ||||
| 	if derivedAddr != expectedAddr { | ||||
| 		err = errors.New("decrypted addr not equal to expected addr") | ||||
| @ -223,3 +223,8 @@ func PKCS7Unpad(in []byte) []byte { | ||||
| 	} | ||||
| 	return in[:len(in)-int(padding)] | ||||
| } | ||||
| 
 | ||||
| func PubkeyToAddress(p ecdsa.PublicKey) []byte { | ||||
| 	pubBytes := FromECDSAPub(&p) | ||||
| 	return Sha3(pubBytes[1:])[12:] | ||||
| } | ||||
|  | ||||
| @ -33,7 +33,9 @@ import ( | ||||
| ) | ||||
| 
 | ||||
| type Key struct { | ||||
| 	Id *uuid.UUID // Version 4 "random" for unique id not derived from key data
 | ||||
| 	Id uuid.UUID // Version 4 "random" for unique id not derived from key data
 | ||||
| 	// to simplify lookups we also store the address
 | ||||
| 	Address []byte | ||||
| 	// we only store privkey as pubkey/address can be derived from it
 | ||||
| 	// privkey in this struct is always in plaintext
 | ||||
| 	PrivateKey *ecdsa.PrivateKey | ||||
| @ -41,6 +43,7 @@ type Key struct { | ||||
| 
 | ||||
| type plainKeyJSON struct { | ||||
| 	Id         []byte | ||||
| 	Address    []byte | ||||
| 	PrivateKey []byte | ||||
| } | ||||
| 
 | ||||
| @ -51,18 +54,15 @@ type cipherJSON struct { | ||||
| } | ||||
| 
 | ||||
| type encryptedKeyJSON struct { | ||||
| 	Id     []byte | ||||
| 	Crypto cipherJSON | ||||
| } | ||||
| 
 | ||||
| func (k *Key) Address() []byte { | ||||
| 	pubBytes := FromECDSAPub(&k.PrivateKey.PublicKey) | ||||
| 	return Sha3(pubBytes[1:])[12:] | ||||
| 	Id      []byte | ||||
| 	Address []byte | ||||
| 	Crypto  cipherJSON | ||||
| } | ||||
| 
 | ||||
| func (k *Key) MarshalJSON() (j []byte, err error) { | ||||
| 	jStruct := plainKeyJSON{ | ||||
| 		*k.Id, | ||||
| 		k.Id, | ||||
| 		k.Address, | ||||
| 		FromECDSA(k.PrivateKey), | ||||
| 	} | ||||
| 	j, err = json.Marshal(jStruct) | ||||
| @ -78,8 +78,8 @@ func (k *Key) UnmarshalJSON(j []byte) (err error) { | ||||
| 
 | ||||
| 	u := new(uuid.UUID) | ||||
| 	*u = keyJSON.Id | ||||
| 	k.Id = u | ||||
| 
 | ||||
| 	k.Id = *u | ||||
| 	k.Address = keyJSON.Address | ||||
| 	k.PrivateKey = ToECDSA(keyJSON.PrivateKey) | ||||
| 
 | ||||
| 	return err | ||||
| @ -101,7 +101,8 @@ func NewKey(rand io.Reader) *Key { | ||||
| 
 | ||||
| 	id := uuid.NewRandom() | ||||
| 	key := &Key{ | ||||
| 		Id:         &id, | ||||
| 		Id:         id, | ||||
| 		Address:    PubkeyToAddress(privateKeyECDSA.PublicKey), | ||||
| 		PrivateKey: privateKeyECDSA, | ||||
| 	} | ||||
| 	return key | ||||
|  | ||||
| @ -69,6 +69,7 @@ import ( | ||||
| 	"crypto/aes" | ||||
| 	"crypto/cipher" | ||||
| 	crand "crypto/rand" | ||||
| 	"encoding/hex" | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"io" | ||||
| @ -96,21 +97,26 @@ func (ks keyStorePassphrase) GenerateNewKey(rand io.Reader, auth string) (key *K | ||||
| 	return GenerateNewKeyDefault(ks, rand, auth) | ||||
| } | ||||
| 
 | ||||
| func (ks keyStorePassphrase) GetKey(keyId *uuid.UUID, auth string) (key *Key, err error) { | ||||
| 	keyBytes, err := DecryptKey(ks, keyId, auth) | ||||
| func (ks keyStorePassphrase) GetKey(keyAddr []byte, auth string) (key *Key, err error) { | ||||
| 	keyBytes, keyId, err := DecryptKey(ks, keyAddr, auth) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	key = &Key{ | ||||
| 		Id:         keyId, | ||||
| 		Id:         uuid.UUID(keyId), | ||||
| 		Address:    keyAddr, | ||||
| 		PrivateKey: ToECDSA(keyBytes), | ||||
| 	} | ||||
| 	return key, err | ||||
| } | ||||
| 
 | ||||
| func (ks keyStorePassphrase) GetKeyAddresses() (addresses [][]byte, err error) { | ||||
| 	return GetKeyAddresses(ks.keysDirPath) | ||||
| } | ||||
| 
 | ||||
| func (ks keyStorePassphrase) StoreKey(key *Key, auth string) (err error) { | ||||
| 	authArray := []byte(auth) | ||||
| 	salt := getEntropyCSPRNG(32) | ||||
| 	salt := GetEntropyCSPRNG(32) | ||||
| 	derivedKey, err := scrypt.Key(authArray, salt, scryptN, scryptr, scryptp, scryptdkLen) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| @ -125,7 +131,7 @@ func (ks keyStorePassphrase) StoreKey(key *Key, auth string) (err error) { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	iv := getEntropyCSPRNG(aes.BlockSize) // 16
 | ||||
| 	iv := GetEntropyCSPRNG(aes.BlockSize) // 16
 | ||||
| 	AES256CBCEncrypter := cipher.NewCBCEncrypter(AES256Block, iv) | ||||
| 	cipherText := make([]byte, len(toEncrypt)) | ||||
| 	AES256CBCEncrypter.CryptBlocks(cipherText, toEncrypt) | ||||
| @ -136,7 +142,8 @@ func (ks keyStorePassphrase) StoreKey(key *Key, auth string) (err error) { | ||||
| 		cipherText, | ||||
| 	} | ||||
| 	keyStruct := encryptedKeyJSON{ | ||||
| 		*key.Id, | ||||
| 		key.Id, | ||||
| 		key.Address, | ||||
| 		cipherStruct, | ||||
| 	} | ||||
| 	keyJSON, err := json.Marshal(keyStruct) | ||||
| @ -144,54 +151,53 @@ func (ks keyStorePassphrase) StoreKey(key *Key, auth string) (err error) { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return WriteKeyFile(key.Id.String(), ks.keysDirPath, keyJSON) | ||||
| 	return WriteKeyFile(key.Address, ks.keysDirPath, keyJSON) | ||||
| } | ||||
| 
 | ||||
| func (ks keyStorePassphrase) DeleteKey(keyId *uuid.UUID, auth string) (err error) { | ||||
| func (ks keyStorePassphrase) DeleteKey(keyAddr []byte, auth string) (err error) { | ||||
| 	// only delete if correct passphrase is given
 | ||||
| 	_, err = DecryptKey(ks, keyId, auth) | ||||
| 	_, _, err = DecryptKey(ks, keyAddr, auth) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	keyDirPath := path.Join(ks.keysDirPath, keyId.String()) | ||||
| 	keyDirPath := path.Join(ks.keysDirPath, hex.EncodeToString(keyAddr)) | ||||
| 	return os.RemoveAll(keyDirPath) | ||||
| } | ||||
| 
 | ||||
| func DecryptKey(ks keyStorePassphrase, keyId *uuid.UUID, auth string) (keyBytes []byte, err error) { | ||||
| 	fileContent, err := GetKeyFile(ks.keysDirPath, keyId) | ||||
| func DecryptKey(ks keyStorePassphrase, keyAddr []byte, auth string) (keyBytes []byte, keyId []byte, err error) { | ||||
| 	fileContent, err := GetKeyFile(ks.keysDirPath, keyAddr) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	keyProtected := new(encryptedKeyJSON) | ||||
| 	err = json.Unmarshal(fileContent, keyProtected) | ||||
| 
 | ||||
| 	keyId = keyProtected.Id | ||||
| 	salt := keyProtected.Crypto.Salt | ||||
| 
 | ||||
| 	iv := keyProtected.Crypto.IV | ||||
| 
 | ||||
| 	cipherText := keyProtected.Crypto.CipherText | ||||
| 
 | ||||
| 	authArray := []byte(auth) | ||||
| 	derivedKey, err := scrypt.Key(authArray, salt, scryptN, scryptr, scryptp, scryptdkLen) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	plainText, err := aesCBCDecrypt(derivedKey, cipherText, iv) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	keyBytes = plainText[:len(plainText)-32] | ||||
| 	keyBytesHash := plainText[len(plainText)-32:] | ||||
| 	if !bytes.Equal(Sha3(keyBytes), keyBytesHash) { | ||||
| 		err = errors.New("Decryption failed: checksum mismatch") | ||||
| 		return nil, err | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	return keyBytes, err | ||||
| 	return keyBytes, keyId, err | ||||
| } | ||||
| 
 | ||||
| func getEntropyCSPRNG(n int) []byte { | ||||
| func GetEntropyCSPRNG(n int) []byte { | ||||
| 	mainBuff := make([]byte, n) | ||||
| 	_, err := io.ReadFull(crand.Reader, mainBuff) | ||||
| 	if err != nil { | ||||
|  | ||||
| @ -24,7 +24,7 @@ | ||||
| package crypto | ||||
| 
 | ||||
| import ( | ||||
| 	"code.google.com/p/go-uuid/uuid" | ||||
| 	"encoding/hex" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| @ -38,9 +38,10 @@ import ( | ||||
| type KeyStore2 interface { | ||||
| 	// create new key using io.Reader entropy source and optionally using auth string
 | ||||
| 	GenerateNewKey(io.Reader, string) (*Key, error) | ||||
| 	GetKey(*uuid.UUID, string) (*Key, error) // key from id and auth string
 | ||||
| 	StoreKey(*Key, string) error             // store key optionally using auth string
 | ||||
| 	DeleteKey(*uuid.UUID, string) error      // delete key by id and auth string
 | ||||
| 	GetKey([]byte, string) (*Key, error) // key from addr and auth string
 | ||||
| 	GetKeyAddresses() ([][]byte, error)  // get all addresses
 | ||||
| 	StoreKey(*Key, string) error         // store key optionally using auth string
 | ||||
| 	DeleteKey([]byte, string) error      // delete key by addr and auth string
 | ||||
| } | ||||
| 
 | ||||
| type keyStorePlain struct { | ||||
| @ -72,8 +73,8 @@ func GenerateNewKeyDefault(ks KeyStore2, rand io.Reader, auth string) (key *Key, | ||||
| 	return key, err | ||||
| } | ||||
| 
 | ||||
| func (ks keyStorePlain) GetKey(keyId *uuid.UUID, auth string) (key *Key, err error) { | ||||
| 	fileContent, err := GetKeyFile(ks.keysDirPath, keyId) | ||||
| func (ks keyStorePlain) GetKey(keyAddr []byte, auth string) (key *Key, err error) { | ||||
| 	fileContent, err := GetKeyFile(ks.keysDirPath, keyAddr) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -83,32 +84,50 @@ func (ks keyStorePlain) GetKey(keyId *uuid.UUID, auth string) (key *Key, err err | ||||
| 	return key, err | ||||
| } | ||||
| 
 | ||||
| func (ks keyStorePlain) GetKeyAddresses() (addresses [][]byte, err error) { | ||||
| 	return GetKeyAddresses(ks.keysDirPath) | ||||
| } | ||||
| 
 | ||||
| func (ks keyStorePlain) StoreKey(key *Key, auth string) (err error) { | ||||
| 	keyJSON, err := json.Marshal(key) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	err = WriteKeyFile(key.Id.String(), ks.keysDirPath, keyJSON) | ||||
| 	err = WriteKeyFile(key.Address, ks.keysDirPath, keyJSON) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func (ks keyStorePlain) DeleteKey(keyId *uuid.UUID, auth string) (err error) { | ||||
| 	keyDirPath := path.Join(ks.keysDirPath, keyId.String()) | ||||
| func (ks keyStorePlain) DeleteKey(keyAddr []byte, auth string) (err error) { | ||||
| 	keyDirPath := path.Join(ks.keysDirPath, hex.EncodeToString(keyAddr)) | ||||
| 	err = os.RemoveAll(keyDirPath) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func GetKeyFile(keysDirPath string, keyId *uuid.UUID) (fileContent []byte, err error) { | ||||
| 	id := keyId.String() | ||||
| 	return ioutil.ReadFile(path.Join(keysDirPath, id, id)) | ||||
| func GetKeyFile(keysDirPath string, keyAddr []byte) (fileContent []byte, err error) { | ||||
| 	fileName := hex.EncodeToString(keyAddr) | ||||
| 	return ioutil.ReadFile(path.Join(keysDirPath, fileName, fileName)) | ||||
| } | ||||
| 
 | ||||
| func WriteKeyFile(id string, keysDirPath string, content []byte) (err error) { | ||||
| 	keyDirPath := path.Join(keysDirPath, id) | ||||
| 	keyFilePath := path.Join(keyDirPath, id) | ||||
| func WriteKeyFile(addr []byte, keysDirPath string, content []byte) (err error) { | ||||
| 	addrHex := hex.EncodeToString(addr) | ||||
| 	keyDirPath := path.Join(keysDirPath, addrHex) | ||||
| 	keyFilePath := path.Join(keyDirPath, addrHex) | ||||
| 	err = os.MkdirAll(keyDirPath, 0700) // read, write and dir search for user
 | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return ioutil.WriteFile(keyFilePath, content, 0600) // read, write for user
 | ||||
| } | ||||
| 
 | ||||
| func GetKeyAddresses(keysDirPath string) (addresses [][]byte, err error) { | ||||
| 	fileInfos, err := ioutil.ReadDir(keysDirPath) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	addresses = make([][]byte, len(fileInfos)) | ||||
| 	for i, fileInfo := range fileInfos { | ||||
| 		addresses[i] = make([]byte, 40) | ||||
| 		addresses[i] = []byte(fileInfo.Name()) | ||||
| 	} | ||||
| 	return addresses, err | ||||
| } | ||||
|  | ||||
| @ -15,12 +15,12 @@ func TestKeyStorePlain(t *testing.T) { | ||||
| 	} | ||||
| 
 | ||||
| 	k2 := new(Key) | ||||
| 	k2, err = ks.GetKey(k1.Id, pass) | ||||
| 	k2, err = ks.GetKey(k1.Address, pass) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	if !reflect.DeepEqual(k1.Id, k2.Id) { | ||||
| 	if !reflect.DeepEqual(k1.Address, k2.Address) { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| @ -28,7 +28,7 @@ func TestKeyStorePlain(t *testing.T) { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	err = ks.DeleteKey(k2.Id, pass) | ||||
| 	err = ks.DeleteKey(k2.Address, pass) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| @ -42,11 +42,11 @@ func TestKeyStorePassphrase(t *testing.T) { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	k2 := new(Key) | ||||
| 	k2, err = ks.GetKey(k1.Id, pass) | ||||
| 	k2, err = ks.GetKey(k1.Address, pass) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	if !reflect.DeepEqual(k1.Id, k2.Id) { | ||||
| 	if !reflect.DeepEqual(k1.Address, k2.Address) { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| @ -54,7 +54,7 @@ func TestKeyStorePassphrase(t *testing.T) { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	err = ks.DeleteKey(k2.Id, pass) // also to clean up created files
 | ||||
| 	err = ks.DeleteKey(k2.Address, pass) // also to clean up created files
 | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| @ -68,17 +68,17 @@ func TestKeyStorePassphraseDecryptionFail(t *testing.T) { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	_, err = ks.GetKey(k1.Id, "bar") // wrong passphrase
 | ||||
| 	_, err = ks.GetKey(k1.Address, "bar") // wrong passphrase
 | ||||
| 	if err == nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	err = ks.DeleteKey(k1.Id, "bar") // wrong passphrase
 | ||||
| 	err = ks.DeleteKey(k1.Address, "bar") // wrong passphrase
 | ||||
| 	if err == nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	err = ks.DeleteKey(k1.Id, pass) // to clean up
 | ||||
| 	err = ks.DeleteKey(k1.Address, pass) // to clean up
 | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| @ -15,7 +15,7 @@ if ls $dir/*.go &> /dev/null; then | ||||
|     # echo $dir | ||||
|     if [[ $dir != "./tests/vm" ]] | ||||
|     then | ||||
|         go test -covermode=count -coverprofile=$dir/profile.tmp $dir | ||||
|         $GOROOT/bin/go test -covermode=count -coverprofile=$dir/profile.tmp $dir | ||||
|     fi | ||||
|     if [ -f $dir/profile.tmp ] | ||||
|     then | ||||
| @ -25,7 +25,7 @@ if ls $dir/*.go &> /dev/null; then | ||||
| fi | ||||
| done | ||||
| 
 | ||||
| go tool cover -func profile.cov | ||||
| $GOROOT/bin/go tool cover -func profile.cov | ||||
| 
 | ||||
| # To submit the test coverage result to coveralls.io, | ||||
| # use goveralls (https://github.com/mattn/goveralls) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user