diff --git a/accounts/abi/abi.go b/accounts/abi/abi.go index 627a2a0c4c..3d1010229c 100644 --- a/accounts/abi/abi.go +++ b/accounts/abi/abi.go @@ -17,6 +17,7 @@ package abi import ( + "encoding/binary" "encoding/json" "fmt" "io" @@ -129,16 +130,15 @@ func toGoSlice(i int, t Argument, output []byte) (interface{}, error) { var size int var offset int if t.Type.IsSlice { - // get the offset which determines the start of this array ... - offset = int(common.BytesToBig(output[index : index+32]).Uint64()) + offset = int(binary.BigEndian.Uint64(output[index+24 : index+32])) if offset+32 > len(output) { return nil, fmt.Errorf("abi: cannot marshal in to go slice: offset %d would go over slice boundary (len=%d)", len(output), offset+32) } slice = output[offset:] // ... starting with the size of the array in elements ... - size = int(common.BytesToBig(slice[:32]).Uint64()) + size = int(binary.BigEndian.Uint64(slice[24:32])) slice = slice[32:] // ... and make sure that we've at the very least the amount of bytes // available in the buffer. @@ -147,7 +147,7 @@ func toGoSlice(i int, t Argument, output []byte) (interface{}, error) { } // reslice to match the required size - slice = slice[:(size * 32)] + slice = slice[:size*32] } else if t.Type.IsArray { //get the number of elements in the array size = t.Type.SliceSize @@ -165,33 +165,12 @@ func toGoSlice(i int, t Argument, output []byte) (interface{}, error) { inter interface{} // interface type returnOutput = slice[i*32 : i*32+32] // the return output ) - // set inter to the correct type (cast) switch elem.T { case IntTy, UintTy: - bigNum := common.BytesToBig(returnOutput) - switch t.Type.Kind { - case reflect.Uint8: - inter = uint8(bigNum.Uint64()) - case reflect.Uint16: - inter = uint16(bigNum.Uint64()) - case reflect.Uint32: - inter = uint32(bigNum.Uint64()) - case reflect.Uint64: - inter = bigNum.Uint64() - case reflect.Int8: - inter = int8(bigNum.Int64()) - case reflect.Int16: - inter = int16(bigNum.Int64()) - case reflect.Int32: - inter = int32(bigNum.Int64()) - case reflect.Int64: - inter = bigNum.Int64() - default: - inter = common.BytesToBig(returnOutput) - } + inter = readInteger(t.Type.Kind, returnOutput) case BoolTy: - inter = common.BytesToBig(returnOutput).Uint64() > 0 + inter = !allZero(returnOutput) case AddressTy: inter = common.BytesToAddress(returnOutput) case HashTy: @@ -207,6 +186,38 @@ func toGoSlice(i int, t Argument, output []byte) (interface{}, error) { return refSlice.Interface(), nil } +func readInteger(kind reflect.Kind, b []byte) interface{} { + switch kind { + case reflect.Uint8: + return uint8(b[len(b)-1]) + case reflect.Uint16: + return binary.BigEndian.Uint16(b[len(b)-2:]) + case reflect.Uint32: + return binary.BigEndian.Uint32(b[len(b)-4:]) + case reflect.Uint64: + return binary.BigEndian.Uint64(b[len(b)-8:]) + case reflect.Int8: + return int8(b[len(b)-1]) + case reflect.Int16: + return int16(binary.BigEndian.Uint16(b[len(b)-2:])) + case reflect.Int32: + return int32(binary.BigEndian.Uint32(b[len(b)-4:])) + case reflect.Int64: + return int64(binary.BigEndian.Uint64(b[len(b)-8:])) + default: + return new(big.Int).SetBytes(b) + } +} + +func allZero(b []byte) bool { + for _, byte := range b { + if byte != 0 { + return false + } + } + return true +} + // toGoType parses the input and casts it to the proper type defined by the ABI // argument in T. func toGoType(i int, t Argument, output []byte) (interface{}, error) { @@ -226,12 +237,12 @@ func toGoType(i int, t Argument, output []byte) (interface{}, error) { switch t.Type.T { case StringTy, BytesTy: // variable arrays are written at the end of the return bytes // parse offset from which we should start reading - offset := int(common.BytesToBig(output[index : index+32]).Uint64()) + offset := int(binary.BigEndian.Uint64(output[index+24 : index+32])) if offset+32 > len(output) { return nil, fmt.Errorf("abi: cannot marshal in to go type: length insufficient %d require %d", len(output), offset+32) } // parse the size up until we should be reading - size := int(common.BytesToBig(output[offset : offset+32]).Uint64()) + size := int(binary.BigEndian.Uint64(output[offset+24 : offset+32])) if offset+32+size > len(output) { return nil, fmt.Errorf("abi: cannot marshal in to go type: length insufficient %d require %d", len(output), offset+32+size) } @@ -245,32 +256,9 @@ func toGoType(i int, t Argument, output []byte) (interface{}, error) { // convert the bytes to whatever is specified by the ABI. switch t.Type.T { case IntTy, UintTy: - bigNum := common.BytesToBig(returnOutput) - - // If the type is a integer convert to the integer type - // specified by the ABI. - switch t.Type.Kind { - case reflect.Uint8: - return uint8(bigNum.Uint64()), nil - case reflect.Uint16: - return uint16(bigNum.Uint64()), nil - case reflect.Uint32: - return uint32(bigNum.Uint64()), nil - case reflect.Uint64: - return uint64(bigNum.Uint64()), nil - case reflect.Int8: - return int8(bigNum.Int64()), nil - case reflect.Int16: - return int16(bigNum.Int64()), nil - case reflect.Int32: - return int32(bigNum.Int64()), nil - case reflect.Int64: - return int64(bigNum.Int64()), nil - case reflect.Ptr: - return bigNum, nil - } + return readInteger(t.Type.Kind, returnOutput), nil case BoolTy: - return common.BytesToBig(returnOutput).Uint64() > 0, nil + return !allZero(returnOutput), nil case AddressTy: return common.BytesToAddress(returnOutput), nil case HashTy: diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 1c34ba0e79..5e2fcbae76 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -25,6 +25,7 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -244,7 +245,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM } // Set infinite balance to the fake caller account. from := statedb.GetOrNewStateObject(call.From) - from.SetBalance(common.MaxBig) + from.SetBalance(math.MaxBig256) // Execute the call. msg := callmsg{call} @@ -252,7 +253,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM // Create a new environment which holds all relevant information // about the transaction and calling mechanisms. vmenv := vm.NewEVM(evmContext, statedb, chainConfig, vm.Config{}) - gaspool := new(core.GasPool).AddGas(common.MaxBig) + gaspool := new(core.GasPool).AddGas(math.MaxBig256) ret, gasUsed, _, err := core.NewStateTransition(vmenv, msg, gaspool).TransitionDb() return ret, gasUsed, err } diff --git a/accounts/abi/numbers.go b/accounts/abi/numbers.go index 3d58422925..36fb6705e6 100644 --- a/accounts/abi/numbers.go +++ b/accounts/abi/numbers.go @@ -21,6 +21,7 @@ import ( "reflect" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" ) var ( @@ -58,7 +59,7 @@ var ( // U256 converts a big Int into a 256bit EVM number. func U256(n *big.Int) []byte { - return common.LeftPadBytes(common.U256(n).Bytes(), 32) + return common.LeftPadBytes(math.U256(n).Bytes(), 32) } // packNum packs the given number (using the reflect value) and will cast it to appropriate number representation diff --git a/cmd/evm/main.go b/cmd/evm/main.go index 86e2493ca1..a489efbfc8 100644 --- a/cmd/evm/main.go +++ b/cmd/evm/main.go @@ -20,6 +20,7 @@ package main import ( "fmt" "io/ioutil" + "math/big" "os" goruntime "runtime" "time" @@ -51,20 +52,20 @@ var ( Name: "codefile", Usage: "file containing EVM code", } - GasFlag = cli.StringFlag{ + GasFlag = cli.Uint64Flag{ Name: "gas", Usage: "gas limit for the evm", - Value: "10000000000", + Value: 10000000000, } - PriceFlag = cli.StringFlag{ + PriceFlag = utils.BigFlag{ Name: "price", Usage: "price set for the evm", - Value: "0", + Value: new(big.Int), } - ValueFlag = cli.StringFlag{ + ValueFlag = utils.BigFlag{ Name: "value", Usage: "value set for the evm", - Value: "0", + Value: new(big.Int), } DumpFlag = cli.BoolFlag{ Name: "dump", @@ -160,9 +161,9 @@ func run(ctx *cli.Context) error { ret, _, err = runtime.Create(input, &runtime.Config{ Origin: sender.Address(), State: statedb, - GasLimit: common.Big(ctx.GlobalString(GasFlag.Name)).Uint64(), - GasPrice: common.Big(ctx.GlobalString(PriceFlag.Name)), - Value: common.Big(ctx.GlobalString(ValueFlag.Name)), + GasLimit: ctx.GlobalUint64(GasFlag.Name), + GasPrice: utils.GlobalBig(ctx, PriceFlag.Name), + Value: utils.GlobalBig(ctx, ValueFlag.Name), EVMConfig: vm.Config{ Tracer: logger, Debug: ctx.GlobalBool(DebugFlag.Name), @@ -177,9 +178,9 @@ func run(ctx *cli.Context) error { ret, err = runtime.Call(receiverAddress, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), &runtime.Config{ Origin: sender.Address(), State: statedb, - GasLimit: common.Big(ctx.GlobalString(GasFlag.Name)).Uint64(), - GasPrice: common.Big(ctx.GlobalString(PriceFlag.Name)), - Value: common.Big(ctx.GlobalString(ValueFlag.Name)), + GasLimit: ctx.GlobalUint64(GasFlag.Name), + GasPrice: utils.GlobalBig(ctx, PriceFlag.Name), + Value: utils.GlobalBig(ctx, ValueFlag.Name), EVMConfig: vm.Config{ Tracer: logger, Debug: ctx.GlobalBool(DebugFlag.Name), diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index 062b9c50de..843cb5b4e7 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -23,11 +23,9 @@ import ( "io" "os" "os/signal" - "regexp" "runtime" "strings" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/internal/debug" @@ -82,19 +80,6 @@ func StartNode(stack *node.Node) { }() } -func FormatTransactionData(data string) []byte { - d := common.StringToByteFunc(data, func(s string) (ret []byte) { - slice := regexp.MustCompile(`\n|\s`).Split(s, 1000000000) - for _, dataItem := range slice { - d := common.FormatData(dataItem) - ret = append(ret, d...) - } - return - }) - - return d -} - func ImportChain(chain *core.BlockChain, fn string) error { // Watch for Ctrl-C while the import is running. // If a signal is received, the import will stop at the next batch. diff --git a/cmd/utils/customflags.go b/cmd/utils/customflags.go index 52cd7b8c72..00f28f2ecf 100644 --- a/cmd/utils/customflags.go +++ b/cmd/utils/customflags.go @@ -17,12 +17,17 @@ package utils import ( + "errors" "flag" "fmt" + "math/big" "os" "os/user" "path" "strings" + + "github.com/ethereum/go-ethereum/common/math" + "gopkg.in/urfave/cli.v1" ) // Custom type which is registered in the flags library which cli uses for @@ -44,10 +49,9 @@ func (self *DirectoryString) Set(value string) error { // Custom cli.Flag type which expand the received string to an absolute path. // e.g. ~/.ethereum -> /home/username/.ethereum type DirectoryFlag struct { - Name string - Value DirectoryString - Usage string - EnvVar string + Name string + Value DirectoryString + Usage string } func (self DirectoryFlag) String() string { @@ -55,7 +59,7 @@ func (self DirectoryFlag) String() string { if len(self.Value.Value) > 0 { fmtString = "%s \"%v\"\t%v" } - return withEnvHint(self.EnvVar, fmt.Sprintf(fmtString, prefixedNames(self.Name), self.Value.Value, self.Usage)) + return fmt.Sprintf(fmtString, prefixedNames(self.Name), self.Value.Value, self.Usage) } func eachName(longName string, fn func(string)) { @@ -69,21 +73,65 @@ func eachName(longName string, fn func(string)) { // called by cli library, grabs variable from environment (if in env) // and adds variable to flag set for parsing. func (self DirectoryFlag) Apply(set *flag.FlagSet) { - if self.EnvVar != "" { - for _, envVar := range strings.Split(self.EnvVar, ",") { - envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { - self.Value.Value = envVal - break - } - } - } - eachName(self.Name, func(name string) { set.Var(&self.Value, self.Name, self.Usage) }) } +// BigFlag is a command line flag that accepts 256 bit big integers in decimal or +// hexadecimal syntax. +type BigFlag struct { + Name string + Value *big.Int + Usage string +} + +// bigValue turns *big.Int into a flag.Value +type bigValue big.Int + +func (b *bigValue) String() string { + if b == nil { + return "" + } + return (*big.Int)(b).String() +} + +func (b *bigValue) Set(s string) error { + int, ok := math.ParseBig256(s) + if !ok { + return errors.New("invalid integer syntax") + } + *b = (bigValue)(*int) + return nil +} + +func (f BigFlag) GetName() string { + return f.Name +} + +func (f BigFlag) String() string { + fmtString := "%s %v\t%v" + if f.Value != nil { + fmtString = "%s \"%v\"\t%v" + } + return fmt.Sprintf(fmtString, prefixedNames(f.Name), f.Value, f.Usage) +} + +func (f BigFlag) Apply(set *flag.FlagSet) { + eachName(f.Name, func(name string) { + set.Var((*bigValue)(f.Value), f.Name, f.Usage) + }) +} + +// GlobalBig returns the value of a BigFlag from the global flag set. +func GlobalBig(ctx *cli.Context, name string) *big.Int { + val := ctx.GlobalGeneric(name) + if val == nil { + return nil + } + return (*big.Int)(val.(*bigValue)) +} + func prefixFor(name string) (prefix string) { if len(name) == 1 { prefix = "-" @@ -106,14 +154,6 @@ func prefixedNames(fullName string) (prefixed string) { return } -func withEnvHint(envVar, str string) string { - envText := "" - if envVar != "" { - envText = fmt.Sprintf(" [$%s]", strings.Join(strings.Split(envVar, ","), ", $")) - } - return str + envText -} - func (self DirectoryFlag) GetName() string { return self.Name } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index a2e4ac8148..25c3a1ada7 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -179,10 +179,10 @@ var ( Usage: "Number of CPU threads to use for mining", Value: runtime.NumCPU(), } - TargetGasLimitFlag = cli.StringFlag{ + TargetGasLimitFlag = cli.Uint64Flag{ Name: "targetgaslimit", Usage: "Target gas limit sets the artificial target gas floor for the blocks to mine", - Value: params.GenesisGasLimit.String(), + Value: params.GenesisGasLimit.Uint64(), } AutoDAGFlag = cli.BoolFlag{ Name: "autodag", @@ -193,10 +193,10 @@ var ( Usage: "Public address for block mining rewards (default = first account created)", Value: "0", } - GasPriceFlag = cli.StringFlag{ + GasPriceFlag = BigFlag{ Name: "gasprice", Usage: "Minimal gas price to accept for mining a transactions", - Value: new(big.Int).Mul(big.NewInt(20), common.Shannon).String(), + Value: big.NewInt(20 * params.Shannon), } ExtraDataFlag = cli.StringFlag{ Name: "extradata", @@ -382,15 +382,15 @@ var ( } // Gas price oracle settings - GpoMinGasPriceFlag = cli.StringFlag{ + GpoMinGasPriceFlag = BigFlag{ Name: "gpomin", Usage: "Minimum suggested gas price", - Value: new(big.Int).Mul(big.NewInt(20), common.Shannon).String(), + Value: big.NewInt(20 * params.Shannon), } - GpoMaxGasPriceFlag = cli.StringFlag{ + GpoMaxGasPriceFlag = BigFlag{ Name: "gpomax", Usage: "Maximum suggested gas price", - Value: new(big.Int).Mul(big.NewInt(500), common.Shannon).String(), + Value: big.NewInt(500 * params.Shannon), } GpoFullBlockRatioFlag = cli.IntFlag{ Name: "gpofull", @@ -741,9 +741,9 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) { MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name), ExtraData: MakeMinerExtra(extra, ctx), DocRoot: ctx.GlobalString(DocRootFlag.Name), - GasPrice: common.String2Big(ctx.GlobalString(GasPriceFlag.Name)), - GpoMinGasPrice: common.String2Big(ctx.GlobalString(GpoMinGasPriceFlag.Name)), - GpoMaxGasPrice: common.String2Big(ctx.GlobalString(GpoMaxGasPriceFlag.Name)), + GasPrice: GlobalBig(ctx, GasPriceFlag.Name), + GpoMinGasPrice: GlobalBig(ctx, GpoMinGasPriceFlag.Name), + GpoMaxGasPrice: GlobalBig(ctx, GpoMaxGasPriceFlag.Name), GpoFullBlockRatio: ctx.GlobalInt(GpoFullBlockRatioFlag.Name), GpobaseStepDown: ctx.GlobalInt(GpobaseStepDownFlag.Name), GpobaseStepUp: ctx.GlobalInt(GpobaseStepUpFlag.Name), @@ -819,7 +819,7 @@ func RegisterEthStatsService(stack *node.Node, url string) { // SetupNetwork configures the system for either the main net or some test network. func SetupNetwork(ctx *cli.Context) { - params.TargetGasLimit = common.String2Big(ctx.GlobalString(TargetGasLimitFlag.Name)) + params.TargetGasLimit = new(big.Int).SetUint64(ctx.GlobalUint64(TargetGasLimitFlag.Name)) } // MakeChainConfig reads the chain configuration from the database in ctx.Datadir. diff --git a/common/.gitignore b/common/.gitignore deleted file mode 100644 index f725d58d14..0000000000 --- a/common/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -# See http://help.github.com/ignore-files/ for more about ignoring files. -# -# If you find yourself ignoring temporary files generated by your text editor -# or operating system, you probably want to add a global ignore instead: -# git config --global core.excludesfile ~/.gitignore_global - -/tmp -*/**/*un~ -*un~ -.DS_Store -*/**/.DS_Store - diff --git a/common/.travis.yml b/common/.travis.yml deleted file mode 100644 index 69359072d9..0000000000 --- a/common/.travis.yml +++ /dev/null @@ -1,3 +0,0 @@ -language: go -go: - - 1.2 diff --git a/common/README.md b/common/README.md deleted file mode 100644 index adea022b7f..0000000000 --- a/common/README.md +++ /dev/null @@ -1,140 +0,0 @@ -# common - -[![Build -Status](https://travis-ci.org/ethereum/go-ethereum.png?branch=master)](https://travis-ci.org/ethereum/go-ethereum) - -The common package contains the ethereum utility library. - -# Installation - -As a subdirectory the main go-ethereum repository, you get it with -`go get github.com/ethereum/go-ethereum`. - -# Usage - -## RLP (Recursive Linear Prefix) Encoding - -RLP Encoding is an encoding scheme used by the Ethereum project. It -encodes any native value or list to a string. - -More in depth information about the encoding scheme see the -[Wiki](http://wiki.ethereum.org/index.php/RLP) article. - -```go -rlp := common.Encode("doge") -fmt.Printf("%q\n", rlp) // => "\0x83dog" - -rlp = common.Encode([]interface{}{"dog", "cat"}) -fmt.Printf("%q\n", rlp) // => "\0xc8\0x83dog\0x83cat" -decoded := common.Decode(rlp) -fmt.Println(decoded) // => ["dog" "cat"] -``` - -## Patricia Trie - -Patricie Tree is a merkle trie used by the Ethereum project. - -More in depth information about the (modified) Patricia Trie can be -found on the [Wiki](http://wiki.ethereum.org/index.php/Patricia_Tree). - -The patricia trie uses a db as backend and could be anything as long as -it satisfies the Database interface found in `common/db.go`. - -```go -db := NewDatabase() - -// db, root -trie := common.NewTrie(db, "") - -trie.Put("puppy", "dog") -trie.Put("horse", "stallion") -trie.Put("do", "verb") -trie.Put("doge", "coin") - -// Look up the key "do" in the trie -out := trie.Get("do") -fmt.Println(out) // => verb - -trie.Delete("puppy") -``` - -The patricia trie, in combination with RLP, provides a robust, -cryptographically authenticated data structure that can be used to store -all (key, value) bindings. - -```go -// ... Create db/trie - -// Note that RLP uses interface slices as list -value := common.Encode([]interface{}{"one", 2, "three", []interface{}{42}}) -// Store the RLP encoded value of the list -trie.Put("mykey", value) -``` - -## Value - -Value is a Generic Value which is used in combination with RLP data or -`([])interface{}` structures. It may serve as a bridge between RLP data -and actual real values and takes care of all the type checking and -casting. Unlike Go's `reflect.Value` it does not panic if it's unable to -cast to the requested value. It simple returns the base value of that -type (e.g. `Slice()` returns []interface{}, `Uint()` return 0, etc). - -### Creating a new Value - -`NewEmptyValue()` returns a new \*Value with it's initial value set to a -`[]interface{}` - -`AppendList()` appends a list to the current value. - -`Append(v)` appends the value (v) to the current value/list. - -```go -val := common.NewEmptyValue().Append(1).Append("2") -val.AppendList().Append(3) -``` - -### Retrieving values - -`Get(i)` returns the `i` item in the list. - -`Uint()` returns the value as an unsigned int64. - -`Slice()` returns the value as a interface slice. - -`Str()` returns the value as a string. - -`Bytes()` returns the value as a byte slice. - -`Len()` assumes current to be a slice and returns its length. - -`Byte()` returns the value as a single byte. - -```go -val := common.NewValue([]interface{}{1,"2",[]interface{}{3}}) -val.Get(0).Uint() // => 1 -val.Get(1).Str() // => "2" -s := val.Get(2) // => Value([]interface{}{3}) -s.Get(0).Uint() // => 3 -``` - -## Decoding - -Decoding streams of RLP data is simplified - -```go -val := common.NewValueFromBytes(rlpData) -val.Get(0).Uint() -``` - -## Encoding - -Encoding from Value to RLP is done with the `Encode` method. The -underlying value can be anything RLP can encode (int, str, lists, bytes) - -```go -val := common.NewValue([]interface{}{1,"2",[]interface{}{3}}) -rlp := val.Encode() -// Store the rlp data -Store(rlp) -``` diff --git a/common/big.go b/common/big.go index 4ce87ee0c6..b552608bc7 100644 --- a/common/big.go +++ b/common/big.go @@ -20,137 +20,11 @@ import "math/big" // Common big integers often used var ( - Big1 = big.NewInt(1) - Big2 = big.NewInt(2) - Big3 = big.NewInt(3) - Big0 = big.NewInt(0) - BigTrue = Big1 - BigFalse = Big0 - Big32 = big.NewInt(32) - Big36 = big.NewInt(36) - Big97 = big.NewInt(97) - Big98 = big.NewInt(98) - Big256 = big.NewInt(0xff) - Big257 = big.NewInt(257) - MaxBig = String2Big("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + Big1 = big.NewInt(1) + Big2 = big.NewInt(2) + Big3 = big.NewInt(3) + Big0 = big.NewInt(0) + Big32 = big.NewInt(32) + Big256 = big.NewInt(0xff) + Big257 = big.NewInt(257) ) - -// Big pow -// -// Returns the power of two big integers -func BigPow(a, b int) *big.Int { - c := new(big.Int) - c.Exp(big.NewInt(int64(a)), big.NewInt(int64(b)), big.NewInt(0)) - - return c -} - -// Big -// -// Shortcut for new(big.Int).SetString(..., 0) -func Big(num string) *big.Int { - n := new(big.Int) - n.SetString(num, 0) - - return n -} - -// Bytes2Big -// -func BytesToBig(data []byte) *big.Int { - n := new(big.Int) - n.SetBytes(data) - - return n -} -func Bytes2Big(data []byte) *big.Int { return BytesToBig(data) } -func BigD(data []byte) *big.Int { return BytesToBig(data) } - -func String2Big(num string) *big.Int { - n := new(big.Int) - n.SetString(num, 0) - return n -} - -func BitTest(num *big.Int, i int) bool { - return num.Bit(i) > 0 -} - -// To256 -// -// "cast" the big int to a 256 big int (i.e., limit to) -var tt256 = new(big.Int).Lsh(big.NewInt(1), 256) -var tt256m1 = new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(1)) -var tt255 = new(big.Int).Lsh(big.NewInt(1), 255) - -func U256(x *big.Int) *big.Int { - //if x.Cmp(Big0) < 0 { - // return new(big.Int).Add(tt256, x) - // } - - x.And(x, tt256m1) - - return x -} - -func S256(x *big.Int) *big.Int { - if x.Cmp(tt255) < 0 { - return x - } else { - // We don't want to modify x, ever - return new(big.Int).Sub(x, tt256) - } -} - -func FirstBitSet(v *big.Int) int { - for i := 0; i < v.BitLen(); i++ { - if v.Bit(i) > 0 { - return i - } - } - - return v.BitLen() -} - -// Big to bytes -// -// Returns the bytes of a big integer with the size specified by **base** -// Attempts to pad the byte array with zeros. -func BigToBytes(num *big.Int, base int) []byte { - ret := make([]byte, base/8) - - if len(num.Bytes()) > base/8 { - return num.Bytes() - } - - return append(ret[:len(ret)-len(num.Bytes())], num.Bytes()...) -} - -// Big copy -// -// Creates a copy of the given big integer -func BigCopy(src *big.Int) *big.Int { - return new(big.Int).Set(src) -} - -// Big max -// -// Returns the maximum size big integer -func BigMax(x, y *big.Int) *big.Int { - if x.Cmp(y) < 0 { - return y - } - - return x -} - -// Big min -// -// Returns the minimum size big integer -func BigMin(x, y *big.Int) *big.Int { - if x.Cmp(y) > 0 { - return y - } - - return x -} diff --git a/common/big_test.go b/common/big_test.go deleted file mode 100644 index 4d04a8db36..0000000000 --- a/common/big_test.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2014 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package common - -import ( - "bytes" - "testing" -) - -func TestMisc(t *testing.T) { - a := Big("10") - b := Big("57896044618658097711785492504343953926634992332820282019728792003956564819968") - c := []byte{1, 2, 3, 4} - z := BitTest(a, 1) - - if !z { - t.Error("Expected true got", z) - } - - U256(a) - S256(a) - - U256(b) - S256(b) - - BigD(c) -} - -func TestBigMax(t *testing.T) { - a := Big("10") - b := Big("5") - - max1 := BigMax(a, b) - if max1 != a { - t.Errorf("Expected %d got %d", a, max1) - } - - max2 := BigMax(b, a) - if max2 != a { - t.Errorf("Expected %d got %d", a, max2) - } -} - -func TestBigMin(t *testing.T) { - a := Big("10") - b := Big("5") - - min1 := BigMin(a, b) - if min1 != b { - t.Errorf("Expected %d got %d", b, min1) - } - - min2 := BigMin(b, a) - if min2 != b { - t.Errorf("Expected %d got %d", b, min2) - } -} - -func TestBigCopy(t *testing.T) { - a := Big("10") - b := BigCopy(a) - c := Big("1000000000000") - y := BigToBytes(b, 16) - ybytes := []byte{0, 10} - z := BigToBytes(c, 16) - zbytes := []byte{232, 212, 165, 16, 0} - - if !bytes.Equal(y, ybytes) { - t.Error("Got", ybytes) - } - - if !bytes.Equal(z, zbytes) { - t.Error("Got", zbytes) - } -} diff --git a/common/bytes.go b/common/bytes.go index cbceea8b5c..0342083a1e 100644 --- a/common/bytes.go +++ b/common/bytes.go @@ -18,12 +18,7 @@ package common import ( - "bytes" - "encoding/binary" "encoding/hex" - "fmt" - "math/big" - "strings" ) func ToHex(b []byte) string { @@ -48,65 +43,6 @@ func FromHex(s string) []byte { return nil } -// Number to bytes -// -// Returns the number in bytes with the specified base -func NumberToBytes(num interface{}, bits int) []byte { - buf := new(bytes.Buffer) - err := binary.Write(buf, binary.BigEndian, num) - if err != nil { - fmt.Println("NumberToBytes failed:", err) - } - - return buf.Bytes()[buf.Len()-(bits/8):] -} - -// Bytes to number -// -// Attempts to cast a byte slice to a unsigned integer -func BytesToNumber(b []byte) uint64 { - var number uint64 - - // Make sure the buffer is 64bits - data := make([]byte, 8) - data = append(data[:len(b)], b...) - - buf := bytes.NewReader(data) - err := binary.Read(buf, binary.BigEndian, &number) - if err != nil { - fmt.Println("BytesToNumber failed:", err) - } - - return number -} - -// Read variable int -// -// Read a variable length number in big endian byte order -func ReadVarInt(buff []byte) (ret uint64) { - switch l := len(buff); { - case l > 4: - d := LeftPadBytes(buff, 8) - binary.Read(bytes.NewReader(d), binary.BigEndian, &ret) - case l > 2: - var num uint32 - d := LeftPadBytes(buff, 4) - binary.Read(bytes.NewReader(d), binary.BigEndian, &num) - ret = uint64(num) - case l > 1: - var num uint16 - d := LeftPadBytes(buff, 2) - binary.Read(bytes.NewReader(d), binary.BigEndian, &num) - ret = uint64(num) - default: - var num uint8 - binary.Read(bytes.NewReader(buff), binary.BigEndian, &num) - ret = uint64(num) - } - - return -} - // Copy bytes // // Returns an exact copy of the provided bytes @@ -152,53 +88,6 @@ func Hex2BytesFixed(str string, flen int) []byte { } } -func StringToByteFunc(str string, cb func(str string) []byte) (ret []byte) { - if len(str) > 1 && str[0:2] == "0x" && !strings.Contains(str, "\n") { - ret = Hex2Bytes(str[2:]) - } else { - ret = cb(str) - } - - return -} - -func FormatData(data string) []byte { - if len(data) == 0 { - return nil - } - // Simple stupid - d := new(big.Int) - if data[0:1] == "\"" && data[len(data)-1:] == "\"" { - return RightPadBytes([]byte(data[1:len(data)-1]), 32) - } else if len(data) > 1 && data[:2] == "0x" { - d.SetBytes(Hex2Bytes(data[2:])) - } else { - d.SetString(data, 0) - } - - return BigToBytes(d, 256) -} - -func ParseData(data ...interface{}) (ret []byte) { - for _, item := range data { - switch t := item.(type) { - case string: - var str []byte - if IsHex(t) { - str = Hex2Bytes(t[2:]) - } else { - str = []byte(t) - } - - ret = append(ret, RightPadBytes(str, 32)...) - case []byte: - ret = append(ret, LeftPadBytes(t, 32)...) - } - } - - return -} - func RightPadBytes(slice []byte, l int) []byte { if l < len(slice) { return slice @@ -220,47 +109,3 @@ func LeftPadBytes(slice []byte, l int) []byte { return padded } - -func LeftPadString(str string, l int) string { - if l < len(str) { - return str - } - - zeros := Bytes2Hex(make([]byte, (l-len(str))/2)) - - return zeros + str - -} - -func RightPadString(str string, l int) string { - if l < len(str) { - return str - } - - zeros := Bytes2Hex(make([]byte, (l-len(str))/2)) - - return str + zeros - -} - -func ToAddress(slice []byte) (addr []byte) { - if len(slice) < 20 { - addr = LeftPadBytes(slice, 20) - } else if len(slice) > 20 { - addr = slice[len(slice)-20:] - } else { - addr = slice - } - - addr = CopyBytes(addr) - - return -} - -func ByteSliceToInterface(slice [][]byte) (ret []interface{}) { - for _, i := range slice { - ret = append(ret, i) - } - - return -} diff --git a/common/bytes_test.go b/common/bytes_test.go index 98d402c489..fc164b13d6 100644 --- a/common/bytes_test.go +++ b/common/bytes_test.go @@ -27,54 +27,6 @@ type BytesSuite struct{} var _ = checker.Suite(&BytesSuite{}) -func (s *BytesSuite) TestNumberToBytes(c *checker.C) { - // data1 := int(1) - // res1 := NumberToBytes(data1, 16) - // c.Check(res1, checker.Panics) - - var data2 float64 = 3.141592653 - exp2 := []byte{0xe9, 0x38} - res2 := NumberToBytes(data2, 16) - c.Assert(res2, checker.DeepEquals, exp2) -} - -func (s *BytesSuite) TestBytesToNumber(c *checker.C) { - datasmall := []byte{0xe9, 0x38, 0xe9, 0x38} - datalarge := []byte{0xe9, 0x38, 0xe9, 0x38, 0xe9, 0x38, 0xe9, 0x38} - - var expsmall uint64 = 0xe938e938 - var explarge uint64 = 0x0 - - ressmall := BytesToNumber(datasmall) - reslarge := BytesToNumber(datalarge) - - c.Assert(ressmall, checker.Equals, expsmall) - c.Assert(reslarge, checker.Equals, explarge) - -} - -func (s *BytesSuite) TestReadVarInt(c *checker.C) { - data8 := []byte{1, 2, 3, 4, 5, 6, 7, 8} - data4 := []byte{1, 2, 3, 4} - data2 := []byte{1, 2} - data1 := []byte{1} - - exp8 := uint64(72623859790382856) - exp4 := uint64(16909060) - exp2 := uint64(258) - exp1 := uint64(1) - - res8 := ReadVarInt(data8) - res4 := ReadVarInt(data4) - res2 := ReadVarInt(data2) - res1 := ReadVarInt(data1) - - c.Assert(res8, checker.Equals, exp8) - c.Assert(res4, checker.Equals, exp4) - c.Assert(res2, checker.Equals, exp2) - c.Assert(res1, checker.Equals, exp1) -} - func (s *BytesSuite) TestCopyBytes(c *checker.C) { data1 := []byte{1, 2, 3, 4} exp1 := []byte{1, 2, 3, 4} @@ -95,22 +47,6 @@ func (s *BytesSuite) TestIsHex(c *checker.C) { } -func (s *BytesSuite) TestParseDataString(c *checker.C) { - res1 := ParseData("hello", "world", "0x0106") - data := "68656c6c6f000000000000000000000000000000000000000000000000000000776f726c640000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000" - exp1 := Hex2Bytes(data) - c.Assert(res1, checker.DeepEquals, exp1) -} - -func (s *BytesSuite) TestParseDataBytes(c *checker.C) { - data1 := []byte{232, 212, 165, 16, 0} - exp1 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 212, 165, 16, 0} - - res1 := ParseData(data1) - c.Assert(res1, checker.DeepEquals, exp1) - -} - func (s *BytesSuite) TestLeftPadBytes(c *checker.C) { val1 := []byte{1, 2, 3, 4} exp1 := []byte{0, 0, 0, 0, 1, 2, 3, 4} @@ -122,28 +58,6 @@ func (s *BytesSuite) TestLeftPadBytes(c *checker.C) { c.Assert(res2, checker.DeepEquals, val1) } -func (s *BytesSuite) TestFormatData(c *checker.C) { - data1 := "" - data2 := "0xa9e67e00" - data3 := "a9e67e" - data4 := "\"a9e67e00\"" - - // exp1 := []byte{} - exp2 := []byte{00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0xa9, 0xe6, 0x7e, 00} - exp3 := []byte{00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00} - exp4 := []byte{0x61, 0x39, 0x65, 0x36, 0x37, 0x65, 0x30, 0x30, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00} - - res1 := FormatData(data1) - res2 := FormatData(data2) - res3 := FormatData(data3) - res4 := FormatData(data4) - - c.Assert(res1, checker.IsNil) - c.Assert(res2, checker.DeepEquals, exp2) - c.Assert(res3, checker.DeepEquals, exp3) - c.Assert(res4, checker.DeepEquals, exp4) -} - func (s *BytesSuite) TestRightPadBytes(c *checker.C) { val := []byte{1, 2, 3, 4} exp := []byte{1, 2, 3, 4, 0, 0, 0, 0} @@ -155,28 +69,6 @@ func (s *BytesSuite) TestRightPadBytes(c *checker.C) { c.Assert(resshrt, checker.DeepEquals, val) } -func (s *BytesSuite) TestLeftPadString(c *checker.C) { - val := "test" - exp := "\x30\x30\x30\x30" + val - - resstd := LeftPadString(val, 8) - resshrt := LeftPadString(val, 2) - - c.Assert(resstd, checker.Equals, exp) - c.Assert(resshrt, checker.Equals, val) -} - -func (s *BytesSuite) TestRightPadString(c *checker.C) { - val := "test" - exp := val + "\x30\x30\x30\x30" - - resstd := RightPadString(val, 8) - resshrt := RightPadString(val, 2) - - c.Assert(resstd, checker.Equals, exp) - c.Assert(resshrt, checker.Equals, val) -} - func TestFromHex(t *testing.T) { input := "0x01" expected := []byte{1} diff --git a/common/icap.go b/common/icap.go deleted file mode 100644 index a36e669b34..0000000000 --- a/common/icap.go +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2015 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -// Spec at https://github.com/ethereum/wiki/wiki/ICAP:-Inter-exchange-Client-Address-Protocol - -package common - -import ( - "errors" - "math/big" - "strconv" - "strings" -) - -var ( - Base36Chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" - ICAPLengthError = errors.New("Invalid ICAP length") - ICAPEncodingError = errors.New("Invalid ICAP encoding") - ICAPChecksumError = errors.New("Invalid ICAP checksum") - ICAPCountryCodeError = errors.New("Invalid ICAP country code") - ICAPAssetIdentError = errors.New("Invalid ICAP asset identifier") - ICAPInstCodeError = errors.New("Invalid ICAP institution code") - ICAPClientIdentError = errors.New("Invalid ICAP client identifier") -) - -func ICAPToAddress(s string) (Address, error) { - switch len(s) { - case 35: // "XE" + 2 digit checksum + 31 base-36 chars of address - return parseICAP(s) - case 34: // "XE" + 2 digit checksum + 30 base-36 chars of address - return parseICAP(s) - case 20: // "XE" + 2 digit checksum + 3-char asset identifier + - // 4-char institution identifier + 9-char institution client identifier - return parseIndirectICAP(s) - default: - return Address{}, ICAPLengthError - } -} - -func parseICAP(s string) (Address, error) { - if !strings.HasPrefix(s, "XE") { - return Address{}, ICAPCountryCodeError - } - if err := validCheckSum(s); err != nil { - return Address{}, err - } - // checksum is ISO13616, Ethereum address is base-36 - bigAddr, _ := new(big.Int).SetString(s[4:], 36) - return BigToAddress(bigAddr), nil -} - -func parseIndirectICAP(s string) (Address, error) { - if !strings.HasPrefix(s, "XE") { - return Address{}, ICAPCountryCodeError - } - if s[4:7] != "ETH" { - return Address{}, ICAPAssetIdentError - } - if err := validCheckSum(s); err != nil { - return Address{}, err - } - // TODO: integrate with ICAP namereg - return Address{}, errors.New("not implemented") -} - -func AddressToICAP(a Address) (string, error) { - enc := base36Encode(a.Big()) - // zero padd encoded address to Direct ICAP length if needed - if len(enc) < 30 { - enc = join(strings.Repeat("0", 30-len(enc)), enc) - } - icap := join("XE", checkDigits(enc), enc) - return icap, nil -} - -// TODO: integrate with ICAP namereg when it's available -func AddressToIndirectICAP(a Address, instCode string) (string, error) { - // return addressToIndirectICAP(a, instCode) - return "", errors.New("not implemented") -} - -func addressToIndirectICAP(a Address, instCode string) (string, error) { - // TODO: add addressToClientIdent which grabs client ident from ICAP namereg - //clientIdent := addressToClientIdent(a) - clientIdent := "todo" - return clientIdentToIndirectICAP(instCode, clientIdent) -} - -func clientIdentToIndirectICAP(instCode, clientIdent string) (string, error) { - if len(instCode) != 4 || !validBase36(instCode) { - return "", ICAPInstCodeError - } - if len(clientIdent) != 9 || !validBase36(instCode) { - return "", ICAPClientIdentError - } - - // currently ETH is only valid asset identifier - s := join("ETH", instCode, clientIdent) - return join("XE", checkDigits(s), s), nil -} - -// https://en.wikipedia.org/wiki/International_Bank_Account_Number#Validating_the_IBAN -func validCheckSum(s string) error { - s = join(s[4:], s[:4]) - expanded, err := iso13616Expand(s) - if err != nil { - return err - } - checkSumNum, _ := new(big.Int).SetString(expanded, 10) - if checkSumNum.Mod(checkSumNum, Big97).Cmp(Big1) != 0 { - return ICAPChecksumError - } - return nil -} - -func checkDigits(s string) string { - expanded, _ := iso13616Expand(strings.Join([]string{s, "XE00"}, "")) - num, _ := new(big.Int).SetString(expanded, 10) - num.Sub(Big98, num.Mod(num, Big97)) - - checkDigits := num.String() - // zero padd checksum - if len(checkDigits) == 1 { - checkDigits = join("0", checkDigits) - } - return checkDigits -} - -// not base-36, but expansion to decimal literal: A = 10, B = 11, ... Z = 35 -func iso13616Expand(s string) (string, error) { - var parts []string - if !validBase36(s) { - return "", ICAPEncodingError - } - for _, c := range s { - i := uint64(c) - if i >= 65 { - parts = append(parts, strconv.FormatUint(uint64(c)-55, 10)) - } else { - parts = append(parts, string(c)) - } - } - return join(parts...), nil -} - -func base36Encode(i *big.Int) string { - var chars []rune - x := new(big.Int) - for { - x.Mod(i, Big36) - chars = append(chars, rune(Base36Chars[x.Uint64()])) - i.Div(i, Big36) - if i.Cmp(Big0) == 0 { - break - } - } - // reverse slice - for i, j := 0, len(chars)-1; i < j; i, j = i+1, j-1 { - chars[i], chars[j] = chars[j], chars[i] - } - return string(chars) -} - -func validBase36(s string) bool { - for _, c := range s { - i := uint64(c) - // 0-9 or A-Z - if i < 48 || (i > 57 && i < 65) || i > 90 { - return false - } - } - return true -} - -func join(s ...string) string { - return strings.Join(s, "") -} diff --git a/common/icap_test.go b/common/icap_test.go deleted file mode 100644 index 6306686d17..0000000000 --- a/common/icap_test.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2015 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package common - -import "testing" - -/* More test vectors: -https://github.com/ethereum/web3.js/blob/master/test/iban.fromAddress.js -https://github.com/ethereum/web3.js/blob/master/test/iban.toAddress.js -https://github.com/ethereum/web3.js/blob/master/test/iban.isValid.js -https://github.com/ethereum/libethereum/blob/develop/test/libethcore/icap.cpp -*/ - -type icapTest struct { - name string - addr string - icap string -} - -var icapOKTests = []icapTest{ - {"Direct1", "0x52dc504a422f0e2a9e7632a34a50f1a82f8224c7", "XE499OG1EH8ZZI0KXC6N83EKGT1BM97P2O7"}, - {"Direct2", "0x11c5496aee77c1ba1f0854206a26dda82a81d6d8", "XE1222Q908LN1QBBU6XUQSO1OHWJIOS46OO"}, - {"DirectZeroPrefix", "0x00c5496aee77c1ba1f0854206a26dda82a81d6d8", "XE7338O073KYGTWWZN0F2WZ0R8PX5ZPPZS"}, - {"DirectDoubleZeroPrefix", "0x0000a5327eab78357cbf2ae8f3d49fd9d90c7d22", "XE0600DQK33XDTYUCRI0KYM5ELAKXDWWF6"}, -} - -var icapInvalidTests = []icapTest{ - {"DirectInvalidCheckSum", "", "XE7438O073KYGTWWZN0F2WZ0R8PX5ZPPZS"}, - {"DirectInvalidCountryCode", "", "XD7338O073KYGTWWZN0F2WZ0R8PX5ZPPZS"}, - {"DirectInvalidLength36", "", "XE499OG1EH8ZZI0KXC6N83EKGT1BM97P2O77"}, - {"DirectInvalidLength33", "", "XE499OG1EH8ZZI0KXC6N83EKGT1BM97P2"}, - - {"IndirectInvalidCheckSum", "", "XE35ETHXREGGOPHERSSS"}, - {"IndirectInvalidAssetIdentifier", "", "XE34ETHXREGGOPHERSSS"}, - {"IndirectInvalidLength19", "", "XE34ETHXREGGOPHERSS"}, - {"IndirectInvalidLength21", "", "XE34ETHXREGGOPHERSSSS"}, -} - -func TestICAPOK(t *testing.T) { - for _, test := range icapOKTests { - decodeEncodeTest(HexToAddress(test.addr), test.icap, t) - } -} - -func TestICAPInvalid(t *testing.T) { - for _, test := range icapInvalidTests { - failedDecodingTest(test.icap, t) - } -} - -func decodeEncodeTest(addr0 Address, icap0 string, t *testing.T) { - icap1, err := AddressToICAP(addr0) - if err != nil { - t.Errorf("ICAP encoding failed: %s", err) - } - if icap1 != icap0 { - t.Errorf("ICAP mismatch: have: %s want: %s", icap1, icap0) - } - - addr1, err := ICAPToAddress(icap0) - if err != nil { - t.Errorf("ICAP decoding failed: %s", err) - } - if addr1 != addr0 { - t.Errorf("Address mismatch: have: %x want: %x", addr1, addr0) - } -} - -func failedDecodingTest(icap string, t *testing.T) { - addr, err := ICAPToAddress(icap) - if err == nil { - t.Errorf("Expected ICAP decoding to fail.") - } - if addr != (Address{}) { - t.Errorf("Expected empty Address on failed ICAP decoding.") - } -} diff --git a/common/list.go b/common/list.go deleted file mode 100644 index 07b2f17f53..0000000000 --- a/common/list.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2014 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package common - -import ( - "encoding/json" - "reflect" - "sync" -) - -// The list type is an anonymous slice handler which can be used -// for containing any slice type to use in an environment which -// does not support slice types (e.g., JavaScript, QML) -type List struct { - mut sync.Mutex - val interface{} - list reflect.Value - Length int -} - -// Initialise a new list. Panics if non-slice type is given. -func NewList(t interface{}) *List { - list := reflect.ValueOf(t) - if list.Kind() != reflect.Slice { - panic("list container initialized with a non-slice type") - } - - return &List{sync.Mutex{}, t, list, list.Len()} -} - -func EmptyList() *List { - return NewList([]interface{}{}) -} - -// Get N element from the embedded slice. Returns nil if OOB. -func (self *List) Get(i int) interface{} { - if self.list.Len() > i { - self.mut.Lock() - defer self.mut.Unlock() - - i := self.list.Index(i).Interface() - - return i - } - - return nil -} - -func (self *List) GetAsJson(i int) interface{} { - e := self.Get(i) - - r, _ := json.Marshal(e) - - return string(r) -} - -// Appends value at the end of the slice. Panics when incompatible value -// is given. -func (self *List) Append(v interface{}) { - self.mut.Lock() - defer self.mut.Unlock() - - self.list = reflect.Append(self.list, reflect.ValueOf(v)) - self.Length = self.list.Len() -} - -// Returns the underlying slice as interface. -func (self *List) Interface() interface{} { - return self.list.Interface() -} - -// For JavaScript <3 -func (self *List) ToJSON() string { - // make(T, 0) != nil - list := make([]interface{}, 0) - for i := 0; i < self.Length; i++ { - list = append(list, self.Get(i)) - } - - data, _ := json.Marshal(list) - - return string(data) -} diff --git a/common/math/big.go b/common/math/big.go new file mode 100644 index 0000000000..c0508c102d --- /dev/null +++ b/common/math/big.go @@ -0,0 +1,143 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Package math provides integer math utilities. +package math + +import ( + "math/big" +) + +var ( + tt255 = BigPow(2, 255) + tt256 = BigPow(2, 256) + tt256m1 = new(big.Int).Sub(tt256, big.NewInt(1)) + MaxBig256 = new(big.Int).Set(tt256m1) +) + +// ParseBig256 parses s as a 256 bit integer in decimal or hexadecimal syntax. +// Leading zeros are accepted. The empty string parses as zero. +func ParseBig256(s string) (*big.Int, bool) { + if s == "" { + return new(big.Int), true + } + var bigint *big.Int + var ok bool + if len(s) >= 2 && (s[:2] == "0x" || s[:2] == "0X") { + bigint, ok = new(big.Int).SetString(s[2:], 16) + } else { + bigint, ok = new(big.Int).SetString(s, 10) + } + if ok && bigint.BitLen() > 256 { + bigint, ok = nil, false + } + return bigint, ok +} + +// MustParseBig parses s as a 256 bit big integer and panics if the string is invalid. +func MustParseBig256(s string) *big.Int { + v, ok := ParseBig256(s) + if !ok { + panic("invalid 256 bit integer: " + s) + } + return v +} + +// BigPow returns a ** b as a big integer. +func BigPow(a, b int64) *big.Int { + r := big.NewInt(a) + return r.Exp(r, big.NewInt(b), nil) +} + +// BigMax returns the larger of x or y. +func BigMax(x, y *big.Int) *big.Int { + if x.Cmp(y) < 0 { + return y + } + return x +} + +// BigMin returns the smaller of x or y. +func BigMin(x, y *big.Int) *big.Int { + if x.Cmp(y) > 0 { + return y + } + return x +} + +// FirstBitSet returns the index of the first 1 bit in v, counting from LSB. +func FirstBitSet(v *big.Int) int { + for i := 0; i < v.BitLen(); i++ { + if v.Bit(i) > 0 { + return i + } + } + return v.BitLen() +} + +// PaddedBigBytes encodes a big integer as a big-endian byte slice. The length +// of the slice is at least n bytes. +func PaddedBigBytes(bigint *big.Int, n int) []byte { + bytes := bigint.Bytes() + if len(bytes) >= n { + return bytes + } + ret := make([]byte, n) + return append(ret[:len(ret)-len(bytes)], bytes...) +} + +// U256 encodes as a 256 bit two's complement number. This operation is destructive. +func U256(x *big.Int) *big.Int { + return x.And(x, tt256m1) +} + +// S256 interprets x as a two's complement number. +// x must not exceed 256 bits (the result is undefined if it does) and is not modified. +// +// S256(0) = 0 +// S256(1) = 1 +// S256(2**255) = -2**255 +// S256(2**256-1) = -1 +func S256(x *big.Int) *big.Int { + if x.Cmp(tt255) < 0 { + return x + } else { + return new(big.Int).Sub(x, tt256) + } +} + +// wordSize is the size number of bits in a big.Word. +const wordSize = 32 << (uint64(^big.Word(0)) >> 63) + +// Exp implements exponentiation by squaring. +// Exp returns a newly-allocated big integer and does not change +// base or exponent. The result is truncated to 256 bits. +// +// Courtesy @karalabe and @chfast +func Exp(base, exponent *big.Int) *big.Int { + result := big.NewInt(1) + + for _, word := range exponent.Bits() { + for i := 0; i < wordSize; i++ { + if word&1 == 1 { + U256(result.Mul(result, base)) + } + U256(base.Mul(base, base)) + word >>= 1 + } + } + return result +} diff --git a/common/math/big_test.go b/common/math/big_test.go new file mode 100644 index 0000000000..a0f48a8ebf --- /dev/null +++ b/common/math/big_test.go @@ -0,0 +1,196 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package math + +import ( + "bytes" + "math/big" + "testing" +) + +func TestParseBig256(t *testing.T) { + tests := []struct { + input string + num *big.Int + ok bool + }{ + {"", big.NewInt(0), true}, + {"0", big.NewInt(0), true}, + {"0x0", big.NewInt(0), true}, + {"12345678", big.NewInt(12345678), true}, + {"0x12345678", big.NewInt(0x12345678), true}, + {"0X12345678", big.NewInt(0x12345678), true}, + // Tests for leading zero behaviour: + {"0123456789", big.NewInt(123456789), true}, // note: not octal + {"00", big.NewInt(0), true}, + {"0x00", big.NewInt(0), true}, + {"0x012345678abc", big.NewInt(0x12345678abc), true}, + // Invalid syntax: + {"abcdef", nil, false}, + {"0xgg", nil, false}, + // Larger than 256 bits: + {"115792089237316195423570985008687907853269984665640564039457584007913129639936", nil, false}, + } + for _, test := range tests { + num, ok := ParseBig256(test.input) + if ok != test.ok { + t.Errorf("ParseBig(%q) -> ok = %t, want %t", test.input, ok, test.ok) + continue + } + if num != nil && test.num != nil && num.Cmp(test.num) != 0 { + t.Errorf("ParseBig(%q) -> %d, want %d", test.input, num, test.num) + } + } +} + +func TestMustParseBig256(t *testing.T) { + defer func() { + if recover() == nil { + t.Error("MustParseBig should've panicked") + } + }() + MustParseBig256("ggg") +} + +func TestBigMax(t *testing.T) { + a := big.NewInt(10) + b := big.NewInt(5) + + max1 := BigMax(a, b) + if max1 != a { + t.Errorf("Expected %d got %d", a, max1) + } + + max2 := BigMax(b, a) + if max2 != a { + t.Errorf("Expected %d got %d", a, max2) + } +} + +func TestBigMin(t *testing.T) { + a := big.NewInt(10) + b := big.NewInt(5) + + min1 := BigMin(a, b) + if min1 != b { + t.Errorf("Expected %d got %d", b, min1) + } + + min2 := BigMin(b, a) + if min2 != b { + t.Errorf("Expected %d got %d", b, min2) + } +} + +func TestFirstBigSet(t *testing.T) { + tests := []struct { + num *big.Int + ix int + }{ + {big.NewInt(0), 0}, + {big.NewInt(1), 0}, + {big.NewInt(2), 1}, + {big.NewInt(0x100), 8}, + } + for _, test := range tests { + if ix := FirstBitSet(test.num); ix != test.ix { + t.Errorf("FirstBitSet(b%b) = %d, want %d", test.num, ix, test.ix) + } + } +} + +func TestPaddedBigBytes(t *testing.T) { + tests := []struct { + num *big.Int + n int + result []byte + }{ + {num: big.NewInt(0), n: 4, result: []byte{0, 0, 0, 0}}, + {num: big.NewInt(1), n: 4, result: []byte{0, 0, 0, 1}}, + {num: big.NewInt(512), n: 4, result: []byte{0, 0, 2, 0}}, + {num: BigPow(2, 32), n: 4, result: []byte{1, 0, 0, 0, 0}}, + } + for _, test := range tests { + if result := PaddedBigBytes(test.num, test.n); !bytes.Equal(result, test.result) { + t.Errorf("PaddedBigBytes(%d, %d) = %v, want %v", test.num, test.n, result, test.result) + } + } +} + +func TestU256(t *testing.T) { + tests := []struct{ x, y *big.Int }{ + {x: big.NewInt(0), y: big.NewInt(0)}, + {x: big.NewInt(1), y: big.NewInt(1)}, + {x: BigPow(2, 255), y: BigPow(2, 255)}, + {x: BigPow(2, 256), y: big.NewInt(0)}, + {x: new(big.Int).Add(BigPow(2, 256), big.NewInt(1)), y: big.NewInt(1)}, + // negative values + {x: big.NewInt(-1), y: new(big.Int).Sub(BigPow(2, 256), big.NewInt(1))}, + {x: big.NewInt(-2), y: new(big.Int).Sub(BigPow(2, 256), big.NewInt(2))}, + {x: BigPow(2, -255), y: big.NewInt(1)}, + } + for _, test := range tests { + if y := U256(new(big.Int).Set(test.x)); y.Cmp(test.y) != 0 { + t.Errorf("U256(%x) = %x, want %x", test.x, y, test.y) + } + } +} + +func TestS256(t *testing.T) { + tests := []struct{ x, y *big.Int }{ + {x: big.NewInt(0), y: big.NewInt(0)}, + {x: big.NewInt(1), y: big.NewInt(1)}, + {x: big.NewInt(2), y: big.NewInt(2)}, + { + x: new(big.Int).Sub(BigPow(2, 255), big.NewInt(1)), + y: new(big.Int).Sub(BigPow(2, 255), big.NewInt(1)), + }, + { + x: BigPow(2, 255), + y: new(big.Int).Neg(BigPow(2, 255)), + }, + { + x: new(big.Int).Sub(BigPow(2, 256), big.NewInt(1)), + y: big.NewInt(-1), + }, + { + x: new(big.Int).Sub(BigPow(2, 256), big.NewInt(2)), + y: big.NewInt(-2), + }, + } + for _, test := range tests { + if y := S256(test.x); y.Cmp(test.y) != 0 { + t.Errorf("S256(%x) = %x, want %x", test.x, y, test.y) + } + } +} + +func TestExp(t *testing.T) { + tests := []struct{ base, exponent, result *big.Int }{ + {base: big.NewInt(0), exponent: big.NewInt(0), result: big.NewInt(1)}, + {base: big.NewInt(1), exponent: big.NewInt(0), result: big.NewInt(1)}, + {base: big.NewInt(1), exponent: big.NewInt(1), result: big.NewInt(1)}, + {base: big.NewInt(1), exponent: big.NewInt(2), result: big.NewInt(1)}, + {base: big.NewInt(3), exponent: big.NewInt(144), result: MustParseBig256("507528786056415600719754159741696356908742250191663887263627442114881")}, + {base: big.NewInt(2), exponent: big.NewInt(255), result: MustParseBig256("57896044618658097711785492504343953926634992332820282019728792003956564819968")}, + } + for _, test := range tests { + if result := Exp(test.base, test.exponent); result.Cmp(test.result) != 0 { + t.Errorf("Exp(%d, %d) = %d, want %d", test.base, test.exponent, result, test.result) + } + } +} diff --git a/common/math/dist.go b/common/math/dist.go deleted file mode 100644 index 913fbfbd47..0000000000 --- a/common/math/dist.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2015 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package math - -import ( - "math/big" - "sort" - - "github.com/ethereum/go-ethereum/common" -) - -type Summer interface { - Sum(i int) *big.Int - Len() int -} - -func Sum(slice Summer) (sum *big.Int) { - sum = new(big.Int) - - for i := 0; i < slice.Len(); i++ { - sum.Add(sum, slice.Sum(i)) - } - return -} - -type Vector struct { - Gas, Price *big.Int -} - -type VectorsBy func(v1, v2 Vector) bool - -func (self VectorsBy) Sort(vectors []Vector) { - bs := vectorSorter{ - vectors: vectors, - by: self, - } - sort.Sort(bs) -} - -type vectorSorter struct { - vectors []Vector - by func(v1, v2 Vector) bool -} - -func (v vectorSorter) Len() int { return len(v.vectors) } -func (v vectorSorter) Less(i, j int) bool { return v.by(v.vectors[i], v.vectors[j]) } -func (v vectorSorter) Swap(i, j int) { v.vectors[i], v.vectors[j] = v.vectors[j], v.vectors[i] } - -func PriceSort(v1, v2 Vector) bool { return v1.Price.Cmp(v2.Price) < 0 } -func GasSort(v1, v2 Vector) bool { return v1.Gas.Cmp(v2.Gas) < 0 } - -type vectorSummer struct { - vectors []Vector - by func(v Vector) *big.Int -} - -type VectorSum func(v Vector) *big.Int - -func (v VectorSum) Sum(vectors []Vector) *big.Int { - vs := vectorSummer{ - vectors: vectors, - by: v, - } - return Sum(vs) -} - -func (v vectorSummer) Len() int { return len(v.vectors) } -func (v vectorSummer) Sum(i int) *big.Int { return v.by(v.vectors[i]) } - -func GasSum(v Vector) *big.Int { return v.Gas } - -var etherInWei = new(big.Rat).SetInt(common.String2Big("1000000000000000000")) - -func GasPrice(bp, gl, ep *big.Int) *big.Int { - BP := new(big.Rat).SetInt(bp) - GL := new(big.Rat).SetInt(gl) - EP := new(big.Rat).SetInt(ep) - GP := new(big.Rat).Quo(BP, GL) - GP = GP.Quo(GP, EP) - - return GP.Mul(GP, etherInWei).Num() -} diff --git a/common/math/dist_test.go b/common/math/dist_test.go deleted file mode 100644 index f5857b6f80..0000000000 --- a/common/math/dist_test.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2015 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package math - -import ( - "fmt" - "math/big" - "testing" -) - -type summer struct { - numbers []*big.Int -} - -func (s summer) Len() int { return len(s.numbers) } -func (s summer) Sum(i int) *big.Int { - return s.numbers[i] -} - -func TestSum(t *testing.T) { - summer := summer{numbers: []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)}} - sum := Sum(summer) - if sum.Cmp(big.NewInt(6)) != 0 { - t.Errorf("got sum = %d, want 6", sum) - } -} - -func TestDist(t *testing.T) { - var vectors = []Vector{ - {big.NewInt(1000), big.NewInt(1234)}, - {big.NewInt(500), big.NewInt(10023)}, - {big.NewInt(1034), big.NewInt(1987)}, - {big.NewInt(1034), big.NewInt(1987)}, - {big.NewInt(8983), big.NewInt(1977)}, - {big.NewInt(98382), big.NewInt(1887)}, - {big.NewInt(12398), big.NewInt(1287)}, - {big.NewInt(12398), big.NewInt(1487)}, - {big.NewInt(12398), big.NewInt(1987)}, - {big.NewInt(12398), big.NewInt(128)}, - {big.NewInt(12398), big.NewInt(1987)}, - {big.NewInt(1398), big.NewInt(187)}, - {big.NewInt(12328), big.NewInt(1927)}, - {big.NewInt(12398), big.NewInt(1987)}, - {big.NewInt(22398), big.NewInt(1287)}, - {big.NewInt(1370), big.NewInt(1981)}, - {big.NewInt(12398), big.NewInt(1957)}, - {big.NewInt(42198), big.NewInt(1987)}, - } - - VectorsBy(GasSort).Sort(vectors) - fmt.Println(vectors) - - BP := big.NewInt(15) - GL := big.NewInt(1000000) - EP := big.NewInt(100) - fmt.Println("BP", BP, "GL", GL, "EP", EP) - GP := GasPrice(BP, GL, EP) - fmt.Println("GP =", GP, "Wei per GU") - - S := len(vectors) / 4 - fmt.Println("L", len(vectors), "S", S) - for i := 1; i <= S*4; i += S { - fmt.Printf("T%d = %v\n", i, vectors[i]) - } - - g := VectorSum(GasSum).Sum(vectors) - fmt.Printf("G = ∑g* (%v)\n", g) -} diff --git a/common/math/integer.go b/common/math/integer.go index 1689b65864..a3eeee27e7 100644 --- a/common/math/integer.go +++ b/common/math/integer.go @@ -1,10 +1,63 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + package math -import gmath "math" +import "strconv" + +const ( + // Integer limit values. + MaxInt8 = 1<<7 - 1 + MinInt8 = -1 << 7 + MaxInt16 = 1<<15 - 1 + MinInt16 = -1 << 15 + MaxInt32 = 1<<31 - 1 + MinInt32 = -1 << 31 + MaxInt64 = 1<<63 - 1 + MinInt64 = -1 << 63 + MaxUint8 = 1<<8 - 1 + MaxUint16 = 1<<16 - 1 + MaxUint32 = 1<<32 - 1 + MaxUint64 = 1<<64 - 1 +) + +// ParseUint64 parses s as an integer in decimal or hexadecimal syntax. +// Leading zeros are accepted. The empty string parses as zero. +func ParseUint64(s string) (uint64, bool) { + if s == "" { + return 0, true + } + if len(s) >= 2 && (s[:2] == "0x" || s[:2] == "0X") { + v, err := strconv.ParseUint(s[2:], 16, 64) + return v, err == nil + } + v, err := strconv.ParseUint(s, 10, 64) + return v, err == nil +} + +// MustParseUint64 parses s as an integer and panics if the string is invalid. +func MustParseUint64(s string) uint64 { + v, ok := ParseUint64(s) + if !ok { + panic("invalid unsigned 64 bit integer: " + s) + } + return v +} -/* - * NOTE: The following methods need to be optimised using either bit checking or asm - */ +// NOTE: The following methods need to be optimised using either bit checking or asm // SafeSub returns subtraction result and whether overflow occurred. func SafeSub(x, y uint64) (uint64, bool) { @@ -13,7 +66,7 @@ func SafeSub(x, y uint64) (uint64, bool) { // SafeAdd returns the result and whether overflow occurred. func SafeAdd(x, y uint64) (uint64, bool) { - return x + y, y > gmath.MaxUint64-x + return x + y, y > MaxUint64-x } // SafeMul returns multiplication result and whether overflow occurred. @@ -21,5 +74,5 @@ func SafeMul(x, y uint64) (uint64, bool) { if x == 0 || y == 0 { return 0, false } - return x * y, y > gmath.MaxUint64/x + return x * y, y > MaxUint64/x } diff --git a/common/math/integer_test.go b/common/math/integer_test.go index 198114e5e1..05bba221f9 100644 --- a/common/math/integer_test.go +++ b/common/math/integer_test.go @@ -1,7 +1,22 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + package math import ( - gmath "math" "testing" ) @@ -21,17 +36,18 @@ func TestOverflow(t *testing.T) { op operation }{ // add operations - {gmath.MaxUint64, 1, true, add}, - {gmath.MaxUint64 - 1, 1, false, add}, + {MaxUint64, 1, true, add}, + {MaxUint64 - 1, 1, false, add}, // sub operations {0, 1, true, sub}, {0, 0, false, sub}, // mul operations + {0, 0, false, mul}, {10, 10, false, mul}, - {gmath.MaxUint64, 2, true, mul}, - {gmath.MaxUint64, 1, false, mul}, + {MaxUint64, 2, true, mul}, + {MaxUint64, 1, false, mul}, } { var overflows bool switch test.op { @@ -48,3 +64,52 @@ func TestOverflow(t *testing.T) { } } } + +func TestParseUint64(t *testing.T) { + tests := []struct { + input string + num uint64 + ok bool + }{ + {"", 0, true}, + {"0", 0, true}, + {"0x0", 0, true}, + {"12345678", 12345678, true}, + {"0x12345678", 0x12345678, true}, + {"0X12345678", 0x12345678, true}, + // Tests for leading zero behaviour: + {"0123456789", 123456789, true}, // note: not octal + {"0x00", 0, true}, + {"0x012345678abc", 0x12345678abc, true}, + // Invalid syntax: + {"abcdef", 0, false}, + {"0xgg", 0, false}, + // Doesn't fit into 64 bits: + {"18446744073709551617", 0, false}, + } + for _, test := range tests { + num, ok := ParseUint64(test.input) + if ok != test.ok { + t.Errorf("ParseUint64(%q) -> ok = %t, want %t", test.input, ok, test.ok) + continue + } + if ok && num != test.num { + t.Errorf("ParseUint64(%q) -> %d, want %d", test.input, num, test.num) + } + } +} + +func TestMustParseUint64(t *testing.T) { + if v := MustParseUint64("12345"); v != 12345 { + t.Errorf(`MustParseUint64("12345") = %d, want 12345`, v) + } +} + +func TestMustParseUint64Panic(t *testing.T) { + defer func() { + if recover() == nil { + t.Error("MustParseBig should've panicked") + } + }() + MustParseUint64("ggg") +} diff --git a/common/size.go b/common/size.go index 9653b36298..c5a0cb0f2d 100644 --- a/common/size.go +++ b/common/size.go @@ -18,7 +18,6 @@ package common import ( "fmt" - "math/big" ) type StorageSize float64 @@ -36,54 +35,3 @@ func (self StorageSize) String() string { func (self StorageSize) Int64() int64 { return int64(self) } - -// The different number of units -var ( - Douglas = BigPow(10, 42) - Einstein = BigPow(10, 21) - Ether = BigPow(10, 18) - Finney = BigPow(10, 15) - Szabo = BigPow(10, 12) - Shannon = BigPow(10, 9) - Babbage = BigPow(10, 6) - Ada = BigPow(10, 3) - Wei = big.NewInt(1) -) - -// -// Currency to string -// Returns a string representing a human readable format -func CurrencyToString(num *big.Int) string { - var ( - fin *big.Int = num - denom string = "Wei" - ) - - switch { - case num.Cmp(Ether) >= 0: - fin = new(big.Int).Div(num, Ether) - denom = "Ether" - case num.Cmp(Finney) >= 0: - fin = new(big.Int).Div(num, Finney) - denom = "Finney" - case num.Cmp(Szabo) >= 0: - fin = new(big.Int).Div(num, Szabo) - denom = "Szabo" - case num.Cmp(Shannon) >= 0: - fin = new(big.Int).Div(num, Shannon) - denom = "Shannon" - case num.Cmp(Babbage) >= 0: - fin = new(big.Int).Div(num, Babbage) - denom = "Babbage" - case num.Cmp(Ada) >= 0: - fin = new(big.Int).Div(num, Ada) - denom = "Ada" - } - - // TODO add comment clarifying expected behavior - if len(fin.String()) > 5 { - return fmt.Sprintf("%sE%d %s", fin.String()[0:5], len(fin.String())-5, denom) - } - - return fmt.Sprintf("%v %s", fin, denom) -} diff --git a/common/size_test.go b/common/size_test.go index ce19cab69f..f5b6c725e2 100644 --- a/common/size_test.go +++ b/common/size_test.go @@ -17,43 +17,22 @@ package common import ( - "math/big" - - checker "gopkg.in/check.v1" + "testing" ) -type SizeSuite struct{} - -var _ = checker.Suite(&SizeSuite{}) - -func (s *SizeSuite) TestStorageSizeString(c *checker.C) { - data1 := 2381273 - data2 := 2192 - data3 := 12 - - exp1 := "2.38 mB" - exp2 := "2.19 kB" - exp3 := "12.00 B" - - c.Assert(StorageSize(data1).String(), checker.Equals, exp1) - c.Assert(StorageSize(data2).String(), checker.Equals, exp2) - c.Assert(StorageSize(data3).String(), checker.Equals, exp3) -} - -func (s *SizeSuite) TestCommon(c *checker.C) { - ether := CurrencyToString(BigPow(10, 19)) - finney := CurrencyToString(BigPow(10, 16)) - szabo := CurrencyToString(BigPow(10, 13)) - shannon := CurrencyToString(BigPow(10, 10)) - babbage := CurrencyToString(BigPow(10, 7)) - ada := CurrencyToString(BigPow(10, 4)) - wei := CurrencyToString(big.NewInt(10)) - - c.Assert(ether, checker.Equals, "10 Ether") - c.Assert(finney, checker.Equals, "10 Finney") - c.Assert(szabo, checker.Equals, "10 Szabo") - c.Assert(shannon, checker.Equals, "10 Shannon") - c.Assert(babbage, checker.Equals, "10 Babbage") - c.Assert(ada, checker.Equals, "10 Ada") - c.Assert(wei, checker.Equals, "10 Wei") +func TestStorageSizeString(t *testing.T) { + tests := []struct { + size StorageSize + str string + }{ + {2381273, "2.38 mB"}, + {2192, "2.19 kB"}, + {12, "12.00 B"}, + } + + for _, test := range tests { + if test.size.String() != test.str { + t.Errorf("%f: got %q, want %q", float64(test.size), test.size.String(), test.str) + } + } } diff --git a/common/types.go b/common/types.go index 8a456e965e..d38ea73064 100644 --- a/common/types.go +++ b/common/types.go @@ -52,7 +52,7 @@ func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) } // Get the string representation of the underlying hash func (h Hash) Str() string { return string(h[:]) } func (h Hash) Bytes() []byte { return h[:] } -func (h Hash) Big() *big.Int { return Bytes2Big(h[:]) } +func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) } func (h Hash) Hex() string { return hexutil.Encode(h[:]) } // UnmarshalJSON parses a hash in its hex from to a hash. @@ -122,7 +122,7 @@ func IsHexAddress(s string) bool { // Get the string representation of the underlying address func (a Address) Str() string { return string(a[:]) } func (a Address) Bytes() []byte { return a[:] } -func (a Address) Big() *big.Int { return Bytes2Big(a[:]) } +func (a Address) Big() *big.Int { return new(big.Int).SetBytes(a[:]) } func (a Address) Hash() Hash { return BytesToHash(a[:]) } func (a Address) Hex() string { return hexutil.Encode(a[:]) } diff --git a/common/types_template.go b/common/types_template.go index 8048f9cc3f..9a8f29977b 100644 --- a/common/types_template.go +++ b/common/types_template.go @@ -37,7 +37,7 @@ func HexTo_N_(s string) _N_ { return BytesTo_N_(FromHex(s)) } // Get the string representation of the underlying hash func (h _N_) Str() string { return string(h[:]) } func (h _N_) Bytes() []byte { return h[:] } -func (h _N_) Big() *big.Int { return Bytes2Big(h[:]) } +func (h _N_) Big() *big.Int { return new(big.Int).SetBytes(h[:]) } func (h _N_) Hex() string { return "0x" + Bytes2Hex(h[:]) } // Sets the hash to the value of b. If b is larger than len(h) it will panic diff --git a/core/bench_test.go b/core/bench_test.go index 59b5ad7589..8a16005579 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -24,6 +24,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" @@ -73,7 +74,7 @@ var ( // This is the content of the genesis block used by the benchmarks. benchRootKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") benchRootAddr = crypto.PubkeyToAddress(benchRootKey.PublicKey) - benchRootFunds = common.BigPow(2, 100) + benchRootFunds = math.BigPow(2, 100) ) // genValueTx returns a block generator that includes a single diff --git a/core/block_validator.go b/core/block_validator.go index a23a4134b1..117974ee66 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -22,6 +22,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" @@ -209,7 +210,7 @@ func ValidateHeader(config *params.ChainConfig, pow pow.PoW, header *types.Heade } if uncle { - if header.Time.Cmp(common.MaxBig) == 1 { + if header.Time.Cmp(math.MaxBig256) == 1 { return BlockTSTooBigErr } } else { @@ -344,7 +345,7 @@ func calcDifficultyFrontier(time, parentTime uint64, parentNumber, parentDiff *b expDiff := periodCount.Sub(periodCount, common.Big2) expDiff.Exp(common.Big2, expDiff, nil) diff.Add(diff, expDiff) - diff = common.BigMax(diff, params.MinimumDifficulty) + diff = math.BigMax(diff, params.MinimumDifficulty) } return diff @@ -372,13 +373,13 @@ func CalcGasLimit(parent *types.Block) *big.Int { */ gl := new(big.Int).Sub(parent.GasLimit(), decay) gl = gl.Add(gl, contrib) - gl.Set(common.BigMax(gl, params.MinGasLimit)) + gl.Set(math.BigMax(gl, params.MinGasLimit)) // however, if we're now below the target (TargetGasLimit) we increase the // limit as much as we can (parentGasLimit / 1024 -1) if gl.Cmp(params.TargetGasLimit) < 0 { gl.Add(parent.GasLimit(), decay) - gl.Set(common.BigMin(gl, params.TargetGasLimit)) + gl.Set(math.BigMin(gl, params.TargetGasLimit)) } return gl } diff --git a/core/database_util_test.go b/core/database_util_test.go index d96aa71ba8..0af4e49206 100644 --- a/core/database_util_test.go +++ b/core/database_util_test.go @@ -25,6 +25,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/sha3" @@ -53,11 +54,11 @@ func (d *diffTest) UnmarshalJSON(b []byte) (err error) { return err } - d.ParentTimestamp = common.String2Big(ext.ParentTimestamp).Uint64() - d.ParentDifficulty = common.String2Big(ext.ParentDifficulty) - d.CurrentTimestamp = common.String2Big(ext.CurrentTimestamp).Uint64() - d.CurrentBlocknumber = common.String2Big(ext.CurrentBlocknumber) - d.CurrentDifficulty = common.String2Big(ext.CurrentDifficulty) + d.ParentTimestamp = math.MustParseUint64(ext.ParentTimestamp) + d.ParentDifficulty = math.MustParseBig256(ext.ParentDifficulty) + d.CurrentTimestamp = math.MustParseUint64(ext.CurrentTimestamp) + d.CurrentBlocknumber = math.MustParseBig256(ext.CurrentBlocknumber) + d.CurrentDifficulty = math.MustParseBig256(ext.CurrentDifficulty) return nil } diff --git a/core/genesis.go b/core/genesis.go index a015f04c14..58d3440d62 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -28,6 +28,7 @@ import ( "strings" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" @@ -67,23 +68,48 @@ func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block, // creating with empty hash always works statedb, _ := state.New(common.Hash{}, chainDb) for addr, account := range genesis.Alloc { + balance, ok := math.ParseBig256(account.Balance) + if !ok { + return nil, fmt.Errorf("invalid balance for account %s: %q", addr, account.Balance) + } + nonce, ok := math.ParseUint64(account.Nonce) + if !ok { + return nil, fmt.Errorf("invalid nonce for account %s: %q", addr, account.Nonce) + } + address := common.HexToAddress(addr) - statedb.AddBalance(address, common.String2Big(account.Balance)) + statedb.AddBalance(address, balance) statedb.SetCode(address, common.FromHex(account.Code)) - statedb.SetNonce(address, common.String2Big(account.Nonce).Uint64()) + statedb.SetNonce(address, nonce) for key, value := range account.Storage { statedb.SetState(address, common.HexToHash(key), common.HexToHash(value)) } } root, stateBatch := statedb.CommitBatch(false) - difficulty := common.String2Big(genesis.Difficulty) + difficulty, ok := math.ParseBig256(genesis.Difficulty) + if !ok { + return nil, fmt.Errorf("invalid difficulty: %q", genesis.Difficulty) + } + gaslimit, ok := math.ParseUint64(genesis.GasLimit) + if !ok { + return nil, fmt.Errorf("invalid gas limit: %q", genesis.GasLimit) + } + nonce, ok := math.ParseUint64(genesis.Nonce) + if !ok { + return nil, fmt.Errorf("invalid nonce: %q", genesis.Nonce) + } + timestamp, ok := math.ParseBig256(genesis.Timestamp) + if !ok { + return nil, fmt.Errorf("invalid timestamp: %q", genesis.Timestamp) + } + block := types.NewBlock(&types.Header{ - Nonce: types.EncodeNonce(common.String2Big(genesis.Nonce).Uint64()), - Time: common.String2Big(genesis.Timestamp), + Nonce: types.EncodeNonce(nonce), + Time: timestamp, ParentHash: common.HexToHash(genesis.ParentHash), Extra: common.FromHex(genesis.ExtraData), - GasLimit: common.String2Big(genesis.GasLimit), + GasLimit: new(big.Int).SetUint64(gaslimit), Difficulty: difficulty, MixDigest: common.HexToHash(genesis.Mixhash), Coinbase: common.HexToAddress(genesis.Coinbase), @@ -153,7 +179,7 @@ func WriteGenesisBlockForTesting(db ethdb.Database, accounts ...GenesisAccount) if i != 0 { accountJson += "," } - accountJson += fmt.Sprintf(`"0x%x":{"balance":"0x%x"}`, account.Address, account.Balance.Bytes()) + accountJson += fmt.Sprintf(`"0x%x":{"balance":"%d"}`, account.Address, account.Balance) } accountJson += "}" @@ -163,7 +189,10 @@ func WriteGenesisBlockForTesting(db ethdb.Database, accounts ...GenesisAccount) "difficulty":"0x%x", "alloc": %s }`, types.EncodeNonce(0), params.GenesisGasLimit.Bytes(), params.GenesisDifficulty.Bytes(), accountJson) - block, _ := WriteGenesisBlock(db, strings.NewReader(testGenesis)) + block, err := WriteGenesisBlock(db, strings.NewReader(testGenesis)) + if err != nil { + panic(err) + } return block } diff --git a/core/state_transition.go b/core/state_transition.go index 8e7891b965..98a24af2b2 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -22,6 +22,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -281,7 +282,7 @@ func (self *StateTransition) refundGas() { // Apply refund counter, capped to half of the used gas. uhalf := remaining.Div(self.gasUsed(), common.Big2) - refund := common.BigMin(uhalf, self.state.GetRefund()) + refund := math.BigMin(uhalf, self.state.GetRefund()) self.gas += refund.Uint64() self.state.AddBalance(sender.Address(), refund.Mul(refund, self.gasPrice)) diff --git a/core/tx_pool_test.go b/core/tx_pool_test.go index 98a34b7573..3a37dd2b99 100644 --- a/core/tx_pool_test.go +++ b/core/tx_pool_test.go @@ -29,6 +29,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/params" ) func transaction(nonce uint64, gaslimit *big.Int, key *ecdsa.PrivateKey) *types.Transaction { @@ -65,7 +66,7 @@ func TestStateChangeDuringPoolReset(t *testing.T) { ) // setup pool with 2 transaction in it - statedb.SetBalance(address, new(big.Int).Mul(common.Big1, common.Ether)) + statedb.SetBalance(address, new(big.Int).SetUint64(params.Ether)) tx0 := transaction(0, big.NewInt(100000), key) tx1 := transaction(1, big.NewInt(100000), key) @@ -82,7 +83,7 @@ func TestStateChangeDuringPoolReset(t *testing.T) { statedb, _ = state.New(common.Hash{}, db) // simulate that the new head block included tx0 and tx1 statedb.SetNonce(address, 2) - statedb.SetBalance(address, new(big.Int).Mul(common.Big1, common.Ether)) + statedb.SetBalance(address, new(big.Int).SetUint64(params.Ether)) trigger = false } return stdb, nil diff --git a/core/types/bloom9.go b/core/types/bloom9.go index 32aa47a41b..2a37b5977c 100644 --- a/core/types/bloom9.go +++ b/core/types/bloom9.go @@ -20,7 +20,6 @@ import ( "fmt" "math/big" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" ) @@ -60,7 +59,7 @@ func (b *Bloom) Add(d *big.Int) { // Big converts b to a big integer. func (b Bloom) Big() *big.Int { - return common.Bytes2Big(b[:]) + return new(big.Int).SetBytes(b[:]) } func (b Bloom) Bytes() []byte { @@ -72,7 +71,8 @@ func (b Bloom) Test(test *big.Int) bool { } func (b Bloom) TestBytes(test []byte) bool { - return b.Test(common.BytesToBig(test)) + return b.Test(new(big.Int).SetBytes(test)) + } // MarshalJSON encodes b as a hex string with 0x prefix. diff --git a/core/vm/common.go b/core/vm/common.go index b7b9a6a9c7..ef40c4a957 100644 --- a/core/vm/common.go +++ b/core/vm/common.go @@ -17,15 +17,10 @@ package vm import ( - "math" "math/big" "github.com/ethereum/go-ethereum/common" -) - -var ( - U256 = common.U256 // Shortcut to common.U256 - S256 = common.S256 // Shortcut to common.S256 + "github.com/ethereum/go-ethereum/common/math" ) // calculates the memory size required for a step @@ -42,8 +37,8 @@ func calcMemSize(off, l *big.Int) *big.Int { func getData(data []byte, start, size *big.Int) []byte { dlen := big.NewInt(int64(len(data))) - s := common.BigMin(start, dlen) - e := common.BigMin(new(big.Int).Add(s, size), dlen) + s := math.BigMin(start, dlen) + e := math.BigMin(new(big.Int).Add(s, size), dlen) return common.RightPadBytes(data[s.Uint64():e.Uint64()], int(size.Uint64())) } @@ -61,3 +56,12 @@ func toWordSize(size uint64) uint64 { return (size + 31) / 32 } + +func allZero(b []byte) bool { + for _, byte := range b { + if byte != 0 { + return false + } + } + return true +} diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 2793d2aa76..0479adfda0 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -19,6 +19,7 @@ package vm import ( "crypto/sha256" "fmt" + "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -69,13 +70,13 @@ func (c *ecrecover) Run(in []byte) []byte { // "in" is (hash, v, r, s), each 32 bytes // but for ecrecover we want (r, s, v) - r := common.BytesToBig(in[64:96]) - s := common.BytesToBig(in[96:128]) + r := new(big.Int).SetBytes(in[64:96]) + s := new(big.Int).SetBytes(in[96:128]) v := in[63] - 27 // tighter sig s values in homestead only apply to tx sigs - if common.Bytes2Big(in[32:63]).BitLen() > 0 || !crypto.ValidateSignatureValues(v, r, s, false) { - log.Trace(fmt.Sprintf("ECRECOVER error: v, r or s value invalid")) + if !allZero(in[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) { + log.Trace("ECRECOVER error: v, r or s value invalid") return nil } // v needs to be at the end for libsecp256k1 diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 39e5c05870..8b7bcc4d61 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -31,7 +31,7 @@ var bigZero = new(big.Int) func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { x, y := stack.pop(), stack.pop() - stack.push(U256(x.Add(x, y))) + stack.push(math.U256(x.Add(x, y))) evm.interpreter.intPool.put(y) @@ -40,7 +40,7 @@ func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac func opSub(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { x, y := stack.pop(), stack.pop() - stack.push(U256(x.Sub(x, y))) + stack.push(math.U256(x.Sub(x, y))) evm.interpreter.intPool.put(y) @@ -49,7 +49,7 @@ func opSub(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac func opMul(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { x, y := stack.pop(), stack.pop() - stack.push(U256(x.Mul(x, y))) + stack.push(math.U256(x.Mul(x, y))) evm.interpreter.intPool.put(y) @@ -59,7 +59,7 @@ func opMul(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac func opDiv(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { x, y := stack.pop(), stack.pop() if y.Cmp(common.Big0) != 0 { - stack.push(U256(x.Div(x, y))) + stack.push(math.U256(x.Div(x, y))) } else { stack.push(new(big.Int)) } @@ -70,7 +70,7 @@ func opDiv(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac } func opSdiv(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - x, y := S256(stack.pop()), S256(stack.pop()) + x, y := math.S256(stack.pop()), math.S256(stack.pop()) if y.Cmp(common.Big0) == 0 { stack.push(new(big.Int)) return nil, nil @@ -85,7 +85,7 @@ func opSdiv(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta res := x.Div(x.Abs(x), y.Abs(y)) res.Mul(res, n) - stack.push(U256(res)) + stack.push(math.U256(res)) } evm.interpreter.intPool.put(y) return nil, nil @@ -96,14 +96,14 @@ func opMod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac if y.Cmp(common.Big0) == 0 { stack.push(new(big.Int)) } else { - stack.push(U256(x.Mod(x, y))) + stack.push(math.U256(x.Mod(x, y))) } evm.interpreter.intPool.put(y) return nil, nil } func opSmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - x, y := S256(stack.pop()), S256(stack.pop()) + x, y := math.S256(stack.pop()), math.S256(stack.pop()) if y.Cmp(common.Big0) == 0 { stack.push(new(big.Int)) @@ -118,7 +118,7 @@ func opSmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta res := x.Mod(x.Abs(x), y.Abs(y)) res.Mul(res, n) - stack.push(U256(res)) + stack.push(math.U256(res)) } evm.interpreter.intPool.put(y) return nil, nil @@ -140,13 +140,13 @@ func opSignExtend(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stac num := stack.pop() mask := back.Lsh(common.Big1, bit) mask.Sub(mask, common.Big1) - if common.BitTest(num, int(bit)) { + if num.Bit(int(bit)) > 0 { num.Or(num, mask.Not(mask)) } else { num.And(num, mask) } - stack.push(U256(num)) + stack.push(math.U256(num)) } evm.interpreter.intPool.put(back) @@ -155,7 +155,7 @@ func opSignExtend(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stac func opNot(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { x := stack.pop() - stack.push(U256(x.Not(x))) + stack.push(math.U256(x.Not(x))) return nil, nil } @@ -184,8 +184,8 @@ func opGt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack } func opSlt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - x, y := S256(stack.pop()), S256(stack.pop()) - if x.Cmp(S256(y)) < 0 { + x, y := math.S256(stack.pop()), math.S256(stack.pop()) + if x.Cmp(math.S256(y)) < 0 { stack.push(evm.interpreter.intPool.get().SetUint64(1)) } else { stack.push(new(big.Int)) @@ -196,7 +196,7 @@ func opSlt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac } func opSgt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - x, y := S256(stack.pop()), S256(stack.pop()) + x, y := math.S256(stack.pop()), math.S256(stack.pop()) if x.Cmp(y) > 0 { stack.push(evm.interpreter.intPool.get().SetUint64(1)) } else { @@ -269,7 +269,7 @@ func opAddmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S if z.Cmp(bigZero) > 0 { add := x.Add(x, y) add.Mod(add, z) - stack.push(U256(add)) + stack.push(math.U256(add)) } else { stack.push(new(big.Int)) } @@ -282,7 +282,7 @@ func opMulmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S if z.Cmp(bigZero) > 0 { mul := x.Mul(x, y) mul.Mod(mul, z) - stack.push(U256(mul)) + stack.push(math.U256(mul)) } else { stack.push(new(big.Int)) } @@ -300,14 +300,14 @@ func opSha3(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta evm.StateDB.AddPreimage(common.BytesToHash(hash), data) } - stack.push(common.BytesToBig(hash)) + stack.push(new(big.Int).SetBytes(hash)) evm.interpreter.intPool.put(offset, size) return nil, nil } func opAddress(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(common.Bytes2Big(contract.Address().Bytes())) + stack.push(contract.Address().Big()) return nil, nil } @@ -335,7 +335,7 @@ func opCallValue(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack } func opCalldataLoad(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(common.Bytes2Big(getData(contract.Input, stack.pop(), common.Big32))) + stack.push(new(big.Int).SetBytes(getData(contract.Input, stack.pop(), common.Big32))) return nil, nil } @@ -427,22 +427,22 @@ func opCoinbase(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack } func opTimestamp(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(U256(new(big.Int).Set(evm.Time))) + stack.push(math.U256(new(big.Int).Set(evm.Time))) return nil, nil } func opNumber(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(U256(new(big.Int).Set(evm.BlockNumber))) + stack.push(math.U256(new(big.Int).Set(evm.BlockNumber))) return nil, nil } func opDifficulty(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(U256(new(big.Int).Set(evm.Difficulty))) + stack.push(math.U256(new(big.Int).Set(evm.Difficulty))) return nil, nil } func opGasLimit(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(U256(new(big.Int).Set(evm.GasLimit))) + stack.push(math.U256(new(big.Int).Set(evm.GasLimit))) return nil, nil } @@ -453,7 +453,7 @@ func opPop(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac func opMload(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { offset := stack.pop() - val := common.BigD(memory.Get(offset.Int64(), 32)) + val := new(big.Int).SetBytes(memory.Get(offset.Int64(), 32)) stack.push(val) evm.interpreter.intPool.put(offset) @@ -463,7 +463,7 @@ func opMload(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *St func opMstore(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { // pop value of the stack mStart, val := stack.pop(), stack.pop() - memory.Set(mStart.Uint64(), 32, common.BigToBytes(val, 256)) + memory.Set(mStart.Uint64(), 32, math.PaddedBigBytes(val, 32)) evm.interpreter.intPool.put(mStart, val) return nil, nil @@ -505,7 +505,7 @@ func opJump(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta } func opJumpi(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { pos, cond := stack.pop(), stack.pop() - if cond.Cmp(common.BigTrue) >= 0 { + if cond.BitLen() > 0 { if !contract.jumpdests.has(contract.CodeHash, contract.Code, pos) { nop := contract.GetOp(pos.Uint64()) return nil, fmt.Errorf("invalid jump destination (%v) %v", nop, pos) @@ -572,7 +572,7 @@ func opCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta gas := stack.pop().Uint64() // pop gas and value of the stack. addr, value := stack.pop(), stack.pop() - value = U256(value) + value = math.U256(value) // pop input size and offset inOffset, inSize := stack.pop(), stack.pop() // pop return size and offset @@ -605,7 +605,7 @@ func opCallCode(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack gas := stack.pop().Uint64() // pop gas and value of the stack. addr, value := stack.pop(), stack.pop() - value = U256(value) + value = math.U256(value) // pop input size and offset inOffset, inSize := stack.pop(), stack.pop() // pop return size and offset @@ -711,7 +711,7 @@ func makeLog(size int) executionFunc { func makePush(size uint64, bsize *big.Int) executionFunc { return func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { byts := getData(contract.Code, evm.interpreter.intPool.get().SetUint64(*pc+1), bsize) - stack.push(common.Bytes2Big(byts)) + stack.push(new(big.Int).SetBytes(byts)) *pc += size return nil, nil } diff --git a/core/vm/memory_table.go b/core/vm/memory_table.go index 4db9948375..3141a2f61a 100644 --- a/core/vm/memory_table.go +++ b/core/vm/memory_table.go @@ -3,7 +3,7 @@ package vm import ( "math/big" - "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" ) func memorySha3(stack *Stack) *big.Int { @@ -42,20 +42,20 @@ func memoryCall(stack *Stack) *big.Int { x := calcMemSize(stack.Back(5), stack.Back(6)) y := calcMemSize(stack.Back(3), stack.Back(4)) - return common.BigMax(x, y) + return math.BigMax(x, y) } func memoryCallCode(stack *Stack) *big.Int { x := calcMemSize(stack.Back(5), stack.Back(6)) y := calcMemSize(stack.Back(3), stack.Back(4)) - return common.BigMax(x, y) + return math.BigMax(x, y) } func memoryDelegateCall(stack *Stack) *big.Int { x := calcMemSize(stack.Back(4), stack.Back(5)) y := calcMemSize(stack.Back(2), stack.Back(3)) - return common.BigMax(x, y) + return math.BigMax(x, y) } func memoryReturn(stack *Stack) *big.Int { diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go index 8ad74a89ab..fe39e97a01 100644 --- a/core/vm/runtime/runtime_test.go +++ b/core/vm/runtime/runtime_test.go @@ -87,7 +87,7 @@ func TestExecute(t *testing.T) { t.Fatal("didn't expect error", err) } - num := common.BytesToBig(ret) + num := new(big.Int).SetBytes(ret) if num.Cmp(big.NewInt(10)) != 0 { t.Error("Expected 10, got", num) } @@ -111,7 +111,7 @@ func TestCall(t *testing.T) { t.Fatal("didn't expect error", err) } - num := common.BytesToBig(ret) + num := new(big.Int).SetBytes(ret) if num.Cmp(big.NewInt(10)) != 0 { t.Error("Expected 10, got", num) } diff --git a/crypto/crypto.go b/crypto/crypto.go index 9d67d82e1d..ecc3be3ce5 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -71,7 +71,7 @@ func ToECDSA(prv []byte) *ecdsa.PrivateKey { priv := new(ecdsa.PrivateKey) priv.PublicKey.Curve = S256() - priv.D = common.BigD(prv) + priv.D = new(big.Int).SetBytes(prv) priv.PublicKey.X, priv.PublicKey.Y = priv.PublicKey.Curve.ScalarBaseMult(prv) return priv } diff --git a/eth/api_backend.go b/eth/api_backend.go index 72ed76cc4a..5a5c4c532e 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -21,6 +21,7 @@ import ( "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -109,7 +110,7 @@ func (b *EthApiBackend) GetTd(blockHash common.Hash) *big.Int { func (b *EthApiBackend) GetEVM(ctx context.Context, msg core.Message, state ethapi.State, header *types.Header, vmCfg vm.Config) (*vm.EVM, func() error, error) { statedb := state.(EthApiState).state from := statedb.GetOrNewStateObject(msg.From()) - from.SetBalance(common.MaxBig) + from.SetBalance(math.MaxBig256) vmError := func() error { return nil } context := core.NewEVMContext(msg, header, b.eth.BlockChain()) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index ca31c9f4be..8f4bde4719 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -21,7 +21,6 @@ import ( "encoding/hex" "errors" "fmt" - "math" "math/big" "strings" "time" @@ -31,6 +30,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -38,6 +38,7 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" "github.com/syndtr/goleveldb/leveldb" @@ -45,9 +46,11 @@ import ( "golang.org/x/net/context" ) -const defaultGas = 90000 - -var emptyHex = "0x" +const ( + defaultGas = 90000 + defaultGasPrice = 50 * params.Shannon + emptyHex = "0x" +) // PublicEthereumAPI provides an API to access Ethereum related information. // It offers only methods that operate on public data that is freely available to anyone. @@ -597,7 +600,7 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr gas = big.NewInt(50000000) } if gasPrice.BitLen() == 0 { - gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon) + gasPrice = new(big.Int).SetUint64(defaultGasPrice) } // Create new call message @@ -631,7 +634,7 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr // Setup the gas pool (also for unmetered requests) // and apply the message. - gp := new(core.GasPool).AddGas(common.MaxBig) + gp := new(core.GasPool).AddGas(math.MaxBig256) res, gas, err := core.ApplyMessage(evm, msg, gp) if err := vmError(); err != nil { return nil, common.Big0, err diff --git a/les/api_backend.go b/les/api_backend.go index ed2a7cd13e..264b381f51 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -21,6 +21,7 @@ import ( "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -95,7 +96,7 @@ func (b *LesApiBackend) GetEVM(ctx context.Context, msg core.Message, state etha if err != nil { return nil, nil, err } - from.SetBalance(common.MaxBig) + from.SetBalance(math.MaxBig256) vmstate := light.NewVMState(ctx, stateDb) context := core.NewEVMContext(msg, header, b.eth.blockchain) diff --git a/les/odr_test.go b/les/odr_test.go index 622d89e5c7..4f1fccb248 100644 --- a/les/odr_test.go +++ b/les/odr_test.go @@ -23,6 +23,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -118,7 +119,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai if err == nil { from := statedb.GetOrNewStateObject(testBankAddress) - from.SetBalance(common.MaxBig) + from.SetBalance(math.MaxBig256) msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(100000), new(big.Int), data, false)} @@ -126,7 +127,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai vmenv := vm.NewEVM(context, statedb, config, vm.Config{}) //vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{}) - gp := new(core.GasPool).AddGas(common.MaxBig) + gp := new(core.GasPool).AddGas(math.MaxBig256) ret, _, _ := core.ApplyMessage(vmenv, msg, gp) res = append(res, ret...) } @@ -136,7 +137,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai vmstate := light.NewVMState(ctx, state) from, err := state.GetOrNewStateObject(ctx, testBankAddress) if err == nil { - from.SetBalance(common.MaxBig) + from.SetBalance(math.MaxBig256) msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(100000), new(big.Int), data, false)} @@ -144,7 +145,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai vmenv := vm.NewEVM(context, vmstate, config, vm.Config{}) //vmenv := light.NewEnv(ctx, state, config, lc, msg, header, vm.Config{}) - gp := new(core.GasPool).AddGas(common.MaxBig) + gp := new(core.GasPool).AddGas(math.MaxBig256) ret, _, _ := core.ApplyMessage(vmenv, msg, gp) if vmstate.Error() == nil { res = append(res, ret...) diff --git a/light/odr_test.go b/light/odr_test.go index a76050a299..6987db6440 100644 --- a/light/odr_test.go +++ b/light/odr_test.go @@ -24,6 +24,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -169,14 +170,14 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain statedb, err := state.New(header.Root, db) if err == nil { from := statedb.GetOrNewStateObject(testBankAddress) - from.SetBalance(common.MaxBig) + from.SetBalance(math.MaxBig256) msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(1000000), new(big.Int), data, false)} context := core.NewEVMContext(msg, header, bc) vmenv := vm.NewEVM(context, statedb, config, vm.Config{}) - gp := new(core.GasPool).AddGas(common.MaxBig) + gp := new(core.GasPool).AddGas(math.MaxBig256) ret, _, _ := core.ApplyMessage(vmenv, msg, gp) res = append(res, ret...) } @@ -186,12 +187,12 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain vmstate := NewVMState(ctx, state) from, err := state.GetOrNewStateObject(ctx, testBankAddress) if err == nil { - from.SetBalance(common.MaxBig) + from.SetBalance(math.MaxBig256) msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(1000000), new(big.Int), data, false)} context := core.NewEVMContext(msg, header, lc) vmenv := vm.NewEVM(context, vmstate, config, vm.Config{}) - gp := new(core.GasPool).AddGas(common.MaxBig) + gp := new(core.GasPool).AddGas(math.MaxBig256) ret, _, _ := core.ApplyMessage(vmenv, msg, gp) if vmstate.Error() == nil { res = append(res, ret...) diff --git a/miner/worker.go b/miner/worker.go index 0379242575..2f090924e2 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -561,7 +561,7 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB // Ignore any transactions (and accounts subsequently) with low gas limits if tx.GasPrice().Cmp(gasPrice) < 0 && !env.ownedAccounts.Has(from) { // Pop the current low-priced transaction without shifting in the next from the account - log.Info(fmt.Sprintf("Transaction (%x) below gas price (tx=%v ask=%v). All sequential txs from this address(%x) will be ignored\n", tx.Hash().Bytes()[:4], common.CurrencyToString(tx.GasPrice()), common.CurrencyToString(gasPrice), from[:4])) + log.Info(fmt.Sprintf("Transaction (%x) below gas price (tx=%dwei ask=%dwei). All sequential txs from this address(%x) will be ignored\n", tx.Hash().Bytes()[:4], tx.GasPrice(), gasPrice, from[:4])) env.lowGasTxs = append(env.lowGasTxs, tx) txs.Pop() diff --git a/mobile/geth.go b/mobile/geth.go index 52c6986fb6..872b482d35 100644 --- a/mobile/geth.go +++ b/mobile/geth.go @@ -24,7 +24,6 @@ import ( "math/big" "path/filepath" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethstats" @@ -145,9 +144,9 @@ func NewNode(datadir string, config *NodeConfig) (stack *Node, _ error) { LightMode: true, DatabaseCache: config.EthereumDatabaseCache, NetworkId: config.EthereumNetworkID, - GasPrice: new(big.Int).Mul(big.NewInt(20), common.Shannon), - GpoMinGasPrice: new(big.Int).Mul(big.NewInt(20), common.Shannon), - GpoMaxGasPrice: new(big.Int).Mul(big.NewInt(500), common.Shannon), + GasPrice: new(big.Int).SetUint64(20 * params.Shannon), + GpoMinGasPrice: new(big.Int).SetUint64(50 * params.Shannon), + GpoMaxGasPrice: new(big.Int).SetUint64(500 * params.Shannon), GpoFullBlockRatio: 80, GpobaseStepDown: 10, GpobaseStepUp: 100, diff --git a/common/math/exp.go b/params/denomination.go similarity index 51% rename from common/math/exp.go rename to params/denomination.go index 113b76b39b..9e1b52506f 100644 --- a/common/math/exp.go +++ b/params/denomination.go @@ -1,4 +1,4 @@ -// Copyright 2016 The go-ethereum Authors +// Copyright 2017 The go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify @@ -14,34 +14,21 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package math +package params -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" +const ( + // These are the multipliers for ether denominations. + // Example: To get the wei value of an amount in 'douglas', use + // + // new(big.Int).Mul(value, big.NewInt(params.Douglas)) + // + Wei = 1 + Ada = 1e3 + Babbage = 1e6 + Shannon = 1e9 + Szabo = 1e12 + Finney = 1e15 + Ether = 1e18 + Einstein = 1e21 + Douglas = 1e42 ) - -// wordSize is the size number of bits in a big.Int Word. -const wordSize = 32 << (uint64(^big.Word(0)) >> 63) - -// Exp implement exponentiation by squaring algorithm. -// -// Exp return a new variable; base and exponent must -// not be changed under any circumstance. -// -// Courtesy @karalabe and @chfast -func Exp(base, exponent *big.Int) *big.Int { - result := big.NewInt(1) - - for _, word := range exponent.Bits() { - for i := 0; i < wordSize; i++ { - if word&1 == 1 { - common.U256(result.Mul(result, base)) - } - common.U256(base.Mul(base, base)) - word >>= 1 - } - } - return result -} diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 064bf45886..81f49efa5b 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -26,6 +26,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -170,11 +171,11 @@ func runStateTest(chainConfig *params.ChainConfig, test VmTest) error { return fmt.Errorf("did not find expected post-state account: %s", addr) } - if balance := statedb.GetBalance(address); balance.Cmp(common.Big(account.Balance)) != 0 { - return fmt.Errorf("(%x) balance failed. Expected: %v have: %v\n", address[:4], common.String2Big(account.Balance), balance) + if balance := statedb.GetBalance(address); balance.Cmp(math.MustParseBig256(account.Balance)) != 0 { + return fmt.Errorf("(%x) balance failed. Expected: %v have: %v\n", address[:4], math.MustParseBig256(account.Balance), balance) } - if nonce := statedb.GetNonce(address); nonce != common.String2Big(account.Nonce).Uint64() { + if nonce := statedb.GetNonce(address); nonce != math.MustParseUint64(account.Nonce) { return fmt.Errorf("(%x) nonce failed. Expected: %v have: %v\n", address[:4], account.Nonce, nonce) } @@ -205,7 +206,7 @@ func runStateTest(chainConfig *params.ChainConfig, test VmTest) error { func RunState(chainConfig *params.ChainConfig, statedb *state.StateDB, env, tx map[string]string) ([]byte, []*types.Log, *big.Int, error) { environment, msg := NewEVMEnvironment(false, chainConfig, statedb, env, tx) - gaspool := new(core.GasPool).AddGas(common.Big(env["currentGasLimit"])) + gaspool := new(core.GasPool).AddGas(math.MustParseBig256(env["currentGasLimit"])) root, _ := statedb.Commit(false) statedb.Reset(root) diff --git a/tests/transaction_test_util.go b/tests/transaction_test_util.go index d267258673..1ecc73a67c 100644 --- a/tests/transaction_test_util.go +++ b/tests/transaction_test_util.go @@ -24,6 +24,7 @@ import ( "runtime" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -161,7 +162,7 @@ func verifyTxFields(chainConfig *params.ChainConfig, txTest TransactionTest, dec var decodedSender common.Address - signer := types.MakeSigner(chainConfig, common.String2Big(txTest.Blocknumber)) + signer := types.MakeSigner(chainConfig, math.MustParseBig256(txTest.Blocknumber)) decodedSender, err = types.Sender(signer, decodedTx) if err != nil { return err diff --git a/tests/util.go b/tests/util.go index c96c2e06dc..ce5b02fed8 100644 --- a/tests/util.go +++ b/tests/util.go @@ -24,6 +24,7 @@ import ( "os" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -119,8 +120,8 @@ func insertAccount(state *state.StateDB, saddr string, account Account) { } addr := common.HexToAddress(saddr) state.SetCode(addr, common.Hex2Bytes(account.Code)) - state.SetNonce(addr, common.Big(account.Nonce).Uint64()) - state.SetBalance(addr, common.Big(account.Balance)) + state.SetNonce(addr, math.MustParseUint64(account.Nonce)) + state.SetBalance(addr, math.MustParseBig256(account.Balance)) for a, v := range account.Storage { state.SetState(addr, common.HexToHash(a), common.HexToHash(v)) } @@ -152,10 +153,10 @@ type VmTest struct { func NewEVMEnvironment(vmTest bool, chainConfig *params.ChainConfig, statedb *state.StateDB, envValues map[string]string, tx map[string]string) (*vm.EVM, core.Message) { var ( 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() + gas = math.MustParseBig256(tx["gasLimit"]) + price = math.MustParseBig256(tx["gasPrice"]) + value = math.MustParseBig256(tx["value"]) + nonce = math.MustParseUint64(tx["nonce"]) ) origin := common.HexToAddress(tx["caller"]) @@ -198,10 +199,10 @@ func NewEVMEnvironment(vmTest bool, chainConfig *params.ChainConfig, statedb *st Origin: origin, Coinbase: common.HexToAddress(envValues["currentCoinbase"]), - BlockNumber: common.Big(envValues["currentNumber"]), - Time: common.Big(envValues["currentTimestamp"]), - GasLimit: common.Big(envValues["currentGasLimit"]), - Difficulty: common.Big(envValues["currentDifficulty"]), + BlockNumber: math.MustParseBig256(envValues["currentNumber"]), + Time: math.MustParseBig256(envValues["currentTimestamp"]), + GasLimit: math.MustParseBig256(envValues["currentGasLimit"]), + Difficulty: math.MustParseBig256(envValues["currentDifficulty"]), GasPrice: price, } if context.GasPrice == nil { diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index 4bf2dbfe98..d2ddee039e 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -25,6 +25,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -180,7 +181,7 @@ func runVmTest(test VmTest) error { if len(test.Gas) == 0 && err == nil { return fmt.Errorf("gas unspecified, indicating an error. VM returned (incorrectly) successful") } else { - gexp := common.Big(test.Gas) + gexp := math.MustParseBig256(test.Gas) if gexp.Cmp(gas) != 0 { return fmt.Errorf("gas failed. Expected %v, got %v\n", gexp, gas) } @@ -222,8 +223,8 @@ func RunVm(statedb *state.StateDB, env, exec map[string]string) ([]byte, []*type to = common.HexToAddress(exec["address"]) from = common.HexToAddress(exec["caller"]) data = common.FromHex(exec["data"]) - gas = common.Big(exec["gas"]) - value = common.Big(exec["value"]) + gas = math.MustParseBig256(exec["gas"]) + value = math.MustParseBig256(exec["value"]) ) caller := statedb.GetOrNewStateObject(from) vm.PrecompiledContracts = make(map[common.Address]vm.PrecompiledContract) diff --git a/whisper/whisperv2/envelope.go b/whisper/whisperv2/envelope.go index 7110ab4571..9f1c682040 100644 --- a/whisper/whisperv2/envelope.go +++ b/whisper/whisperv2/envelope.go @@ -23,9 +23,11 @@ import ( "crypto/ecdsa" "encoding/binary" "fmt" + "math/big" "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/ecies" "github.com/ethereum/go-ethereum/rlp" @@ -66,7 +68,8 @@ func (self *Envelope) Seal(pow time.Duration) { for i := 0; i < 1024; i++ { binary.BigEndian.PutUint32(d[60:], nonce) - firstBit := common.FirstBitSet(common.BigD(crypto.Keccak256(d))) + d := new(big.Int).SetBytes(crypto.Keccak256(d)) + firstBit := math.FirstBitSet(d) if firstBit > bestBit { self.Nonce, bestBit = nonce, firstBit } diff --git a/whisper/whisperv5/envelope.go b/whisper/whisperv5/envelope.go index 8812ae207f..5d882d5dc2 100644 --- a/whisper/whisperv5/envelope.go +++ b/whisper/whisperv5/envelope.go @@ -23,10 +23,12 @@ import ( "encoding/binary" "errors" "fmt" - "math" + gmath "math" + "math/big" "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/ecies" "github.com/ethereum/go-ethereum/rlp" @@ -103,8 +105,8 @@ func (e *Envelope) Seal(options *MessageParams) error { for nonce := uint64(0); time.Now().UnixNano() < finish; { for i := 0; i < 1024; i++ { binary.BigEndian.PutUint64(buf[56:], nonce) - h = crypto.Keccak256(buf) - firstBit := common.FirstBitSet(common.BigD(h)) + d := new(big.Int).SetBytes(crypto.Keccak256(buf)) + firstBit := math.FirstBitSet(d) if firstBit > bestBit { e.EnvNonce, bestBit = nonce, firstBit if target > 0 && bestBit >= target { @@ -138,9 +140,9 @@ func (e *Envelope) calculatePoW(diff uint32) { h := crypto.Keccak256(e.rlpWithoutNonce()) copy(buf[:32], h) binary.BigEndian.PutUint64(buf[56:], e.EnvNonce) - h = crypto.Keccak256(buf) - firstBit := common.FirstBitSet(common.BigD(h)) - x := math.Pow(2, float64(firstBit)) + d := new(big.Int).SetBytes(crypto.Keccak256(buf)) + firstBit := math.FirstBitSet(d) + x := gmath.Pow(2, float64(firstBit)) x /= float64(e.size()) x /= float64(e.TTL + diff) e.pow = x @@ -150,8 +152,8 @@ func (e *Envelope) powToFirstBit(pow float64) int { x := pow x *= float64(e.size()) x *= float64(e.TTL) - bits := math.Log2(x) - bits = math.Ceil(bits) + bits := gmath.Log2(x) + bits = gmath.Ceil(bits) return int(bits) }