mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-23 21:26:42 +00:00
account fixes
* etherbase defaults to first created account * etherbase cli option now allows account index * introduce ethereum.SetEtherbase and miner.setEtherbase * use slightly modified ISO8601 standard * remove obsolete crypto code adapt tests * remove unused abi from accounts
This commit is contained in:
parent
68cf225c4b
commit
bb0f997d57
15 changed files with 88 additions and 896 deletions
|
|
@ -1,155 +0,0 @@
|
|||
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
|
||||
}
|
||||
|
|
@ -1,330 +0,0 @@
|
|||
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)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
// 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
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
package abi
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"reflect"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
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 common.LeftPadBytes(common.U256(n).Bytes(), 32)
|
||||
}
|
||||
|
||||
func S256(n *big.Int) []byte {
|
||||
sint := common.S256(n)
|
||||
ret := common.LeftPadBytes(sint.Bytes(), 32)
|
||||
if sint.Cmp(common.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
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
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()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,190 +0,0 @@
|
|||
package abi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
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(common.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 common.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 common.LeftPadBytes(common.Big1.Bytes(), 32), nil
|
||||
} else {
|
||||
return common.LeftPadBytes(common.Big0.Bytes(), 32), nil
|
||||
}
|
||||
}
|
||||
|
||||
panic("unreached")
|
||||
}
|
||||
|
|
@ -461,22 +461,7 @@ func execJSFiles(ctx *cli.Context) {
|
|||
|
||||
func unlockAccount(ctx *cli.Context, am *accounts.Manager, addr string, i int) (addrHex, auth string) {
|
||||
var err error
|
||||
// Load startup keys. XXX we are going to need a different format
|
||||
|
||||
if !((len(addr) == 40) || (len(addr) == 42)) { // with or without 0x
|
||||
var index int
|
||||
index, err = strconv.Atoi(addr)
|
||||
if err != nil {
|
||||
utils.Fatalf("Invalid account address '%s'", addr)
|
||||
}
|
||||
|
||||
addrHex, err = am.AddressByIndex(index)
|
||||
if err != nil {
|
||||
utils.Fatalf("%v", err)
|
||||
}
|
||||
} else {
|
||||
addrHex = addr
|
||||
}
|
||||
addrHex = utils.ParamToAddress(addr, am)
|
||||
// Attempt to unlock the account 3 times
|
||||
attempts := 3
|
||||
for tries := 0; tries < attempts; tries++ {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
|
||||
|
|
@ -122,8 +123,8 @@ var (
|
|||
}
|
||||
EtherbaseFlag = cli.StringFlag{
|
||||
Name: "etherbase",
|
||||
Usage: "Public address for block mining rewards. By default the address of your primary account is used",
|
||||
Value: "primary",
|
||||
Usage: "Public address for block mining rewards. By default the address first created is used",
|
||||
Value: "0",
|
||||
}
|
||||
GasPriceFlag = cli.StringFlag{
|
||||
Name: "gasprice",
|
||||
|
|
@ -351,6 +352,8 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
|
|||
if len(customName) > 0 {
|
||||
clientID += "/" + customName
|
||||
}
|
||||
am := MakeAccountManager(ctx)
|
||||
|
||||
return ð.Config{
|
||||
Name: common.MakeName(clientID, version),
|
||||
DataDir: ctx.GlobalString(DataDirFlag.Name),
|
||||
|
|
@ -361,9 +364,9 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
|
|||
LogFile: ctx.GlobalString(LogFileFlag.Name),
|
||||
Verbosity: ctx.GlobalInt(VerbosityFlag.Name),
|
||||
LogJSON: ctx.GlobalString(LogJSONFlag.Name),
|
||||
Etherbase: ctx.GlobalString(EtherbaseFlag.Name),
|
||||
Etherbase: common.HexToAddress(ParamToAddress(ctx.GlobalString(EtherbaseFlag.Name), am)),
|
||||
MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name),
|
||||
AccountManager: MakeAccountManager(ctx),
|
||||
AccountManager: am,
|
||||
VmDebug: ctx.GlobalBool(VMDebugFlag.Name),
|
||||
MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name),
|
||||
MaxPendingPeers: ctx.GlobalInt(MaxPendingPeersFlag.Name),
|
||||
|
|
@ -488,3 +491,20 @@ func StartPProf(ctx *cli.Context) {
|
|||
log.Println(http.ListenAndServe(address, nil))
|
||||
}()
|
||||
}
|
||||
|
||||
func ParamToAddress(addr string, am *accounts.Manager) (addrHex string) {
|
||||
if !((len(addr) == 40) || (len(addr) == 42)) { // with or without 0x
|
||||
index, err := strconv.Atoi(addr)
|
||||
if err != nil {
|
||||
Fatalf("Invalid account address '%s'", addr)
|
||||
}
|
||||
|
||||
addrHex, err = am.AddressByIndex(index)
|
||||
if err != nil {
|
||||
Fatalf("%v", err)
|
||||
}
|
||||
} else {
|
||||
addrHex = addr
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ func toISO8601(t time.Time) string {
|
|||
} else {
|
||||
tz = fmt.Sprintf("%03d00", offset/3600)
|
||||
}
|
||||
return fmt.Sprintf("%04d-%02d-%02dT%02d:%02d:%02d.%09d%s", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), tz)
|
||||
return fmt.Sprintf("%04d-%02d-%02dT%02d-%02d-%02d.%09d%s", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), tz)
|
||||
}
|
||||
|
||||
func getKeyAddresses(keysDirPath string) (addresses []common.Address, err error) {
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ type Config struct {
|
|||
Shh bool
|
||||
Dial bool
|
||||
|
||||
Etherbase string
|
||||
Etherbase common.Address
|
||||
GasPrice *big.Int
|
||||
MinerThreads int
|
||||
AccountManager *accounts.Manager
|
||||
|
|
@ -322,7 +322,7 @@ func New(config *Config) (*Ethereum, error) {
|
|||
eventMux: &event.TypeMux{},
|
||||
accountManager: config.AccountManager,
|
||||
DataDir: config.DataDir,
|
||||
etherbase: common.HexToAddress(config.Etherbase),
|
||||
etherbase: config.Etherbase,
|
||||
clientVersion: config.Name, // TODO should separate from Name
|
||||
netVersionId: config.NetworkId,
|
||||
NatSpec: config.NatSpec,
|
||||
|
|
@ -469,6 +469,11 @@ func (s *Ethereum) Etherbase() (eb common.Address, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// set in js console via admin interface or wrapper from cli flags
|
||||
func (self *Ethereum) SetEtherbase(etherbase common.Address) {
|
||||
self.etherbase = etherbase
|
||||
}
|
||||
|
||||
func (s *Ethereum) StopMining() { s.miner.Stop() }
|
||||
func (s *Ethereum) IsMining() bool { return s.miner.Mining() }
|
||||
func (s *Ethereum) Miner() *miner.Miner { return s.miner }
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ var (
|
|||
"miner_makeDAG": (*minerApi).MakeDAG,
|
||||
"miner_setExtra": (*minerApi).SetExtra,
|
||||
"miner_setGasPrice": (*minerApi).SetGasPrice,
|
||||
"admin_setEtherbase": (*minerApi).SetEtherbase,
|
||||
"miner_startAutoDAG": (*minerApi).StartAutoDAG,
|
||||
"miner_start": (*minerApi).StartMiner,
|
||||
"miner_stopAutoDAG": (*minerApi).StopAutoDAG,
|
||||
|
|
@ -119,6 +120,15 @@ func (self *minerApi) SetGasPrice(req *shared.Request) (interface{}, error) {
|
|||
return true, nil
|
||||
}
|
||||
|
||||
func (self *minerApi) SetEtherbase(req *shared.Request) (interface{}, error) {
|
||||
args := new(SetEtherbaseArgs)
|
||||
if err := self.codec.Decode(req.Params, &args); err != nil {
|
||||
return false, err
|
||||
}
|
||||
self.ethereum.SetEtherbase(args.Etherbase)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *minerApi) StartAutoDAG(req *shared.Request) (interface{}, error) {
|
||||
self.ethereum.StartAutoDAG()
|
||||
return true, nil
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/rpc/shared"
|
||||
)
|
||||
|
||||
|
|
@ -76,6 +77,31 @@ func (args *GasPriceArgs) UnmarshalJSON(b []byte) (err error) {
|
|||
return shared.NewInvalidTypeError("Price", "not a string")
|
||||
}
|
||||
|
||||
type SetEtherbaseArgs struct {
|
||||
Etherbase common.Address
|
||||
}
|
||||
|
||||
func (args *SetEtherbaseArgs) UnmarshalJSON(b []byte) (err error) {
|
||||
var obj []interface{}
|
||||
if err := json.Unmarshal(b, &obj); err != nil {
|
||||
return shared.NewDecodeParamError(err.Error())
|
||||
}
|
||||
|
||||
if len(obj) < 1 {
|
||||
return shared.NewInsufficientParamsError(len(obj), 1)
|
||||
}
|
||||
|
||||
if addr, ok := obj[0].(string); ok {
|
||||
args.Etherbase = common.HexToAddress(addr)
|
||||
if (args.Etherbase == common.Address{}) {
|
||||
return shared.NewInvalidTypeError("Etherbase", "not a valid address")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return shared.NewInvalidTypeError("Etherbase", "not a string")
|
||||
}
|
||||
|
||||
type MakeDAGArgs struct {
|
||||
BlockNumber int64
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,13 @@ web3._extend({
|
|||
inputFormatter: [web3._extend.formatters.formatInputInt],
|
||||
outputFormatter: web3._extend.formatters.formatOutputBool
|
||||
}),
|
||||
new web3._extend.Method({
|
||||
name: 'setEtherbase',
|
||||
call: 'miner_setEtherbase',
|
||||
params: 1,
|
||||
inputFormatter: [web3._extend.formatters.formatInputInt],
|
||||
outputFormatter: web3._extend.formatters.formatOutputBool
|
||||
}),
|
||||
new web3._extend.Method({
|
||||
name: 'setExtra',
|
||||
call: 'miner_setExtra',
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ func (test *BlockTest) makeEthConfig() *eth.Config {
|
|||
return ð.Config{
|
||||
DataDir: common.DefaultDataDir(),
|
||||
Verbosity: 5,
|
||||
Etherbase: "primary",
|
||||
Etherbase: common.Address{},
|
||||
AccountManager: accounts.NewManager(ks),
|
||||
NewDB: func(path string) (common.Database, error) { return ethdb.NewMemDatabase() },
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package tests
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
|
|
@ -147,13 +148,12 @@ func runStateTest(test VmTest) error {
|
|||
|
||||
func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.Logs, *big.Int, error) {
|
||||
var (
|
||||
keyPair, _ = crypto.NewKeyPairFromSec([]byte(common.Hex2Bytes(tx["secretKey"])))
|
||||
data = common.FromHex(tx["data"])
|
||||
gas = common.Big(tx["gasLimit"])
|
||||
price = common.Big(tx["gasPrice"])
|
||||
value = common.Big(tx["value"])
|
||||
nonce = common.Big(tx["nonce"]).Uint64()
|
||||
caddr = common.HexToAddress(env["currentCoinbase"])
|
||||
data = common.FromHex(tx["data"])
|
||||
gas = common.Big(tx["gasLimit"])
|
||||
price = common.Big(tx["gasPrice"])
|
||||
value = common.Big(tx["value"])
|
||||
nonce = common.Big(tx["nonce"]).Uint64()
|
||||
caddr = common.HexToAddress(env["currentCoinbase"])
|
||||
)
|
||||
|
||||
var to *common.Address
|
||||
|
|
@ -168,9 +168,11 @@ func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.
|
|||
coinbase := statedb.GetOrNewStateObject(caddr)
|
||||
coinbase.SetGasLimit(common.Big(env["currentGasLimit"]))
|
||||
|
||||
message := NewMessage(common.BytesToAddress(keyPair.Address()), to, data, value, gas, price, nonce)
|
||||
key, _ := hex.DecodeString(tx["secretKey"])
|
||||
addr := crypto.PubkeyToAddress(crypto.ToECDSA(key).PublicKey)
|
||||
message := NewMessage(addr, to, data, value, gas, price, nonce)
|
||||
vmenv := NewEnvFromMap(statedb, env, tx)
|
||||
vmenv.origin = common.BytesToAddress(keyPair.Address())
|
||||
vmenv.origin = addr
|
||||
ret, _, err := core.ApplyMessage(vmenv, message, coinbase)
|
||||
if core.IsNonceErr(err) || core.IsInvalidTxErr(err) || state.IsGasLimitErr(err) {
|
||||
statedb.Set(snapshot)
|
||||
|
|
|
|||
Loading…
Reference in a new issue