forked from cerc-io/plugeth
common: move big integer math to common/math (#3699)
* common: remove CurrencyToString Move denomination values to params instead. * common: delete dead code * common: move big integer operations to common/math This commit consolidates all big integer operations into common/math and adds tests and documentation. There should be no change in semantics for BigPow, BigMin, BigMax, S256, U256, Exp and their behaviour is now locked in by tests. The BigD, BytesToBig and Bytes2Big functions don't provide additional value, all uses are replaced by new(big.Int).SetBytes(). BigToBytes is now called PaddedBigBytes, its minimum output size parameter is now specified as the number of bytes instead of bits. The single use of this function is in the EVM's MSTORE instruction. Big and String2Big are replaced by ParseBig, which is slightly stricter. It previously accepted leading zeros for hexadecimal inputs but treated decimal inputs as octal if a leading zero digit was present. ParseUint64 is used in places where String2Big was used to decode a uint64. The new functions MustParseBig and MustParseUint64 are now used in many places where parsing errors were previously ignored. * common: delete unused big integer variables * accounts/abi: replace uses of BytesToBig with use of encoding/binary * common: remove BytesToBig * common: remove Bytes2Big * common: remove BigTrue * cmd/utils: add BigFlag and use it for error-checked integer flags While here, remove environment variable processing for DirectoryFlag because we don't use it. * core: add missing error checks in genesis block parser * common: remove String2Big * cmd/evm: use utils.BigFlag * common/math: check for 256 bit overflow in ParseBig This is supposed to prevent silent overflow/truncation of values in the genesis block JSON. Without this check, a genesis block that set a balance larger than 256 bits would lead to weird behaviour in the VM. * cmd/utils: fixup import
This commit is contained in:
parent
50ee279f25
commit
5c8fe28b72
@ -17,6 +17,7 @@
|
|||||||
package abi
|
package abi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -129,16 +130,15 @@ func toGoSlice(i int, t Argument, output []byte) (interface{}, error) {
|
|||||||
var size int
|
var size int
|
||||||
var offset int
|
var offset int
|
||||||
if t.Type.IsSlice {
|
if t.Type.IsSlice {
|
||||||
|
|
||||||
// get the offset which determines the start of this array ...
|
// 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) {
|
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)
|
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:]
|
slice = output[offset:]
|
||||||
// ... starting with the size of the array in elements ...
|
// ... 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:]
|
slice = slice[32:]
|
||||||
// ... and make sure that we've at the very least the amount of bytes
|
// ... and make sure that we've at the very least the amount of bytes
|
||||||
// available in the buffer.
|
// available in the buffer.
|
||||||
@ -147,7 +147,7 @@ func toGoSlice(i int, t Argument, output []byte) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reslice to match the required size
|
// reslice to match the required size
|
||||||
slice = slice[:(size * 32)]
|
slice = slice[:size*32]
|
||||||
} else if t.Type.IsArray {
|
} else if t.Type.IsArray {
|
||||||
//get the number of elements in the array
|
//get the number of elements in the array
|
||||||
size = t.Type.SliceSize
|
size = t.Type.SliceSize
|
||||||
@ -165,33 +165,12 @@ func toGoSlice(i int, t Argument, output []byte) (interface{}, error) {
|
|||||||
inter interface{} // interface type
|
inter interface{} // interface type
|
||||||
returnOutput = slice[i*32 : i*32+32] // the return output
|
returnOutput = slice[i*32 : i*32+32] // the return output
|
||||||
)
|
)
|
||||||
|
|
||||||
// set inter to the correct type (cast)
|
// set inter to the correct type (cast)
|
||||||
switch elem.T {
|
switch elem.T {
|
||||||
case IntTy, UintTy:
|
case IntTy, UintTy:
|
||||||
bigNum := common.BytesToBig(returnOutput)
|
inter = readInteger(t.Type.Kind, 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)
|
|
||||||
}
|
|
||||||
case BoolTy:
|
case BoolTy:
|
||||||
inter = common.BytesToBig(returnOutput).Uint64() > 0
|
inter = !allZero(returnOutput)
|
||||||
case AddressTy:
|
case AddressTy:
|
||||||
inter = common.BytesToAddress(returnOutput)
|
inter = common.BytesToAddress(returnOutput)
|
||||||
case HashTy:
|
case HashTy:
|
||||||
@ -207,6 +186,38 @@ func toGoSlice(i int, t Argument, output []byte) (interface{}, error) {
|
|||||||
return refSlice.Interface(), nil
|
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
|
// toGoType parses the input and casts it to the proper type defined by the ABI
|
||||||
// argument in T.
|
// argument in T.
|
||||||
func toGoType(i int, t Argument, output []byte) (interface{}, error) {
|
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 {
|
switch t.Type.T {
|
||||||
case StringTy, BytesTy: // variable arrays are written at the end of the return bytes
|
case StringTy, BytesTy: // variable arrays are written at the end of the return bytes
|
||||||
// parse offset from which we should start reading
|
// 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) {
|
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)
|
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
|
// 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) {
|
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)
|
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.
|
// convert the bytes to whatever is specified by the ABI.
|
||||||
switch t.Type.T {
|
switch t.Type.T {
|
||||||
case IntTy, UintTy:
|
case IntTy, UintTy:
|
||||||
bigNum := common.BytesToBig(returnOutput)
|
return readInteger(t.Type.Kind, returnOutput), nil
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
case BoolTy:
|
case BoolTy:
|
||||||
return common.BytesToBig(returnOutput).Uint64() > 0, nil
|
return !allZero(returnOutput), nil
|
||||||
case AddressTy:
|
case AddressTy:
|
||||||
return common.BytesToAddress(returnOutput), nil
|
return common.BytesToAddress(returnOutput), nil
|
||||||
case HashTy:
|
case HashTy:
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum"
|
"github.com/ethereum/go-ethereum"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"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.
|
// Set infinite balance to the fake caller account.
|
||||||
from := statedb.GetOrNewStateObject(call.From)
|
from := statedb.GetOrNewStateObject(call.From)
|
||||||
from.SetBalance(common.MaxBig)
|
from.SetBalance(math.MaxBig256)
|
||||||
// Execute the call.
|
// Execute the call.
|
||||||
msg := callmsg{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
|
// Create a new environment which holds all relevant information
|
||||||
// about the transaction and calling mechanisms.
|
// about the transaction and calling mechanisms.
|
||||||
vmenv := vm.NewEVM(evmContext, statedb, chainConfig, vm.Config{})
|
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()
|
ret, gasUsed, _, err := core.NewStateTransition(vmenv, msg, gaspool).TransitionDb()
|
||||||
return ret, gasUsed, err
|
return ret, gasUsed, err
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -58,7 +59,7 @@ var (
|
|||||||
|
|
||||||
// U256 converts a big Int into a 256bit EVM number.
|
// U256 converts a big Int into a 256bit EVM number.
|
||||||
func U256(n *big.Int) []byte {
|
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
|
// packNum packs the given number (using the reflect value) and will cast it to appropriate number representation
|
||||||
|
@ -20,6 +20,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
goruntime "runtime"
|
goruntime "runtime"
|
||||||
"time"
|
"time"
|
||||||
@ -51,20 +52,20 @@ var (
|
|||||||
Name: "codefile",
|
Name: "codefile",
|
||||||
Usage: "file containing EVM code",
|
Usage: "file containing EVM code",
|
||||||
}
|
}
|
||||||
GasFlag = cli.StringFlag{
|
GasFlag = cli.Uint64Flag{
|
||||||
Name: "gas",
|
Name: "gas",
|
||||||
Usage: "gas limit for the evm",
|
Usage: "gas limit for the evm",
|
||||||
Value: "10000000000",
|
Value: 10000000000,
|
||||||
}
|
}
|
||||||
PriceFlag = cli.StringFlag{
|
PriceFlag = utils.BigFlag{
|
||||||
Name: "price",
|
Name: "price",
|
||||||
Usage: "price set for the evm",
|
Usage: "price set for the evm",
|
||||||
Value: "0",
|
Value: new(big.Int),
|
||||||
}
|
}
|
||||||
ValueFlag = cli.StringFlag{
|
ValueFlag = utils.BigFlag{
|
||||||
Name: "value",
|
Name: "value",
|
||||||
Usage: "value set for the evm",
|
Usage: "value set for the evm",
|
||||||
Value: "0",
|
Value: new(big.Int),
|
||||||
}
|
}
|
||||||
DumpFlag = cli.BoolFlag{
|
DumpFlag = cli.BoolFlag{
|
||||||
Name: "dump",
|
Name: "dump",
|
||||||
@ -160,9 +161,9 @@ func run(ctx *cli.Context) error {
|
|||||||
ret, _, err = runtime.Create(input, &runtime.Config{
|
ret, _, err = runtime.Create(input, &runtime.Config{
|
||||||
Origin: sender.Address(),
|
Origin: sender.Address(),
|
||||||
State: statedb,
|
State: statedb,
|
||||||
GasLimit: common.Big(ctx.GlobalString(GasFlag.Name)).Uint64(),
|
GasLimit: ctx.GlobalUint64(GasFlag.Name),
|
||||||
GasPrice: common.Big(ctx.GlobalString(PriceFlag.Name)),
|
GasPrice: utils.GlobalBig(ctx, PriceFlag.Name),
|
||||||
Value: common.Big(ctx.GlobalString(ValueFlag.Name)),
|
Value: utils.GlobalBig(ctx, ValueFlag.Name),
|
||||||
EVMConfig: vm.Config{
|
EVMConfig: vm.Config{
|
||||||
Tracer: logger,
|
Tracer: logger,
|
||||||
Debug: ctx.GlobalBool(DebugFlag.Name),
|
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{
|
ret, err = runtime.Call(receiverAddress, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), &runtime.Config{
|
||||||
Origin: sender.Address(),
|
Origin: sender.Address(),
|
||||||
State: statedb,
|
State: statedb,
|
||||||
GasLimit: common.Big(ctx.GlobalString(GasFlag.Name)).Uint64(),
|
GasLimit: ctx.GlobalUint64(GasFlag.Name),
|
||||||
GasPrice: common.Big(ctx.GlobalString(PriceFlag.Name)),
|
GasPrice: utils.GlobalBig(ctx, PriceFlag.Name),
|
||||||
Value: common.Big(ctx.GlobalString(ValueFlag.Name)),
|
Value: utils.GlobalBig(ctx, ValueFlag.Name),
|
||||||
EVMConfig: vm.Config{
|
EVMConfig: vm.Config{
|
||||||
Tracer: logger,
|
Tracer: logger,
|
||||||
Debug: ctx.GlobalBool(DebugFlag.Name),
|
Debug: ctx.GlobalBool(DebugFlag.Name),
|
||||||
|
@ -23,11 +23,9 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"regexp"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/internal/debug"
|
"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 {
|
func ImportChain(chain *core.BlockChain, fn string) error {
|
||||||
// Watch for Ctrl-C while the import is running.
|
// Watch for Ctrl-C while the import is running.
|
||||||
// If a signal is received, the import will stop at the next batch.
|
// If a signal is received, the import will stop at the next batch.
|
||||||
|
@ -17,12 +17,17 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"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
|
// 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.
|
// Custom cli.Flag type which expand the received string to an absolute path.
|
||||||
// e.g. ~/.ethereum -> /home/username/.ethereum
|
// e.g. ~/.ethereum -> /home/username/.ethereum
|
||||||
type DirectoryFlag struct {
|
type DirectoryFlag struct {
|
||||||
Name string
|
Name string
|
||||||
Value DirectoryString
|
Value DirectoryString
|
||||||
Usage string
|
Usage string
|
||||||
EnvVar string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self DirectoryFlag) String() string {
|
func (self DirectoryFlag) String() string {
|
||||||
@ -55,7 +59,7 @@ func (self DirectoryFlag) String() string {
|
|||||||
if len(self.Value.Value) > 0 {
|
if len(self.Value.Value) > 0 {
|
||||||
fmtString = "%s \"%v\"\t%v"
|
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)) {
|
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)
|
// called by cli library, grabs variable from environment (if in env)
|
||||||
// and adds variable to flag set for parsing.
|
// and adds variable to flag set for parsing.
|
||||||
func (self DirectoryFlag) Apply(set *flag.FlagSet) {
|
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) {
|
eachName(self.Name, func(name string) {
|
||||||
set.Var(&self.Value, self.Name, self.Usage)
|
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) {
|
func prefixFor(name string) (prefix string) {
|
||||||
if len(name) == 1 {
|
if len(name) == 1 {
|
||||||
prefix = "-"
|
prefix = "-"
|
||||||
@ -106,14 +154,6 @@ func prefixedNames(fullName string) (prefixed string) {
|
|||||||
return
|
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 {
|
func (self DirectoryFlag) GetName() string {
|
||||||
return self.Name
|
return self.Name
|
||||||
}
|
}
|
||||||
|
@ -179,10 +179,10 @@ var (
|
|||||||
Usage: "Number of CPU threads to use for mining",
|
Usage: "Number of CPU threads to use for mining",
|
||||||
Value: runtime.NumCPU(),
|
Value: runtime.NumCPU(),
|
||||||
}
|
}
|
||||||
TargetGasLimitFlag = cli.StringFlag{
|
TargetGasLimitFlag = cli.Uint64Flag{
|
||||||
Name: "targetgaslimit",
|
Name: "targetgaslimit",
|
||||||
Usage: "Target gas limit sets the artificial target gas floor for the blocks to mine",
|
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{
|
AutoDAGFlag = cli.BoolFlag{
|
||||||
Name: "autodag",
|
Name: "autodag",
|
||||||
@ -193,10 +193,10 @@ var (
|
|||||||
Usage: "Public address for block mining rewards (default = first account created)",
|
Usage: "Public address for block mining rewards (default = first account created)",
|
||||||
Value: "0",
|
Value: "0",
|
||||||
}
|
}
|
||||||
GasPriceFlag = cli.StringFlag{
|
GasPriceFlag = BigFlag{
|
||||||
Name: "gasprice",
|
Name: "gasprice",
|
||||||
Usage: "Minimal gas price to accept for mining a transactions",
|
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{
|
ExtraDataFlag = cli.StringFlag{
|
||||||
Name: "extradata",
|
Name: "extradata",
|
||||||
@ -382,15 +382,15 @@ var (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Gas price oracle settings
|
// Gas price oracle settings
|
||||||
GpoMinGasPriceFlag = cli.StringFlag{
|
GpoMinGasPriceFlag = BigFlag{
|
||||||
Name: "gpomin",
|
Name: "gpomin",
|
||||||
Usage: "Minimum suggested gas price",
|
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",
|
Name: "gpomax",
|
||||||
Usage: "Maximum suggested gas price",
|
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{
|
GpoFullBlockRatioFlag = cli.IntFlag{
|
||||||
Name: "gpofull",
|
Name: "gpofull",
|
||||||
@ -741,9 +741,9 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
|
|||||||
MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name),
|
MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name),
|
||||||
ExtraData: MakeMinerExtra(extra, ctx),
|
ExtraData: MakeMinerExtra(extra, ctx),
|
||||||
DocRoot: ctx.GlobalString(DocRootFlag.Name),
|
DocRoot: ctx.GlobalString(DocRootFlag.Name),
|
||||||
GasPrice: common.String2Big(ctx.GlobalString(GasPriceFlag.Name)),
|
GasPrice: GlobalBig(ctx, GasPriceFlag.Name),
|
||||||
GpoMinGasPrice: common.String2Big(ctx.GlobalString(GpoMinGasPriceFlag.Name)),
|
GpoMinGasPrice: GlobalBig(ctx, GpoMinGasPriceFlag.Name),
|
||||||
GpoMaxGasPrice: common.String2Big(ctx.GlobalString(GpoMaxGasPriceFlag.Name)),
|
GpoMaxGasPrice: GlobalBig(ctx, GpoMaxGasPriceFlag.Name),
|
||||||
GpoFullBlockRatio: ctx.GlobalInt(GpoFullBlockRatioFlag.Name),
|
GpoFullBlockRatio: ctx.GlobalInt(GpoFullBlockRatioFlag.Name),
|
||||||
GpobaseStepDown: ctx.GlobalInt(GpobaseStepDownFlag.Name),
|
GpobaseStepDown: ctx.GlobalInt(GpobaseStepDownFlag.Name),
|
||||||
GpobaseStepUp: ctx.GlobalInt(GpobaseStepUpFlag.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.
|
// SetupNetwork configures the system for either the main net or some test network.
|
||||||
func SetupNetwork(ctx *cli.Context) {
|
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.
|
// MakeChainConfig reads the chain configuration from the database in ctx.Datadir.
|
||||||
|
12
common/.gitignore
vendored
12
common/.gitignore
vendored
@ -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
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
language: go
|
|
||||||
go:
|
|
||||||
- 1.2
|
|
140
common/README.md
140
common/README.md
@ -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)
|
|
||||||
```
|
|
140
common/big.go
140
common/big.go
@ -20,137 +20,11 @@ import "math/big"
|
|||||||
|
|
||||||
// Common big integers often used
|
// Common big integers often used
|
||||||
var (
|
var (
|
||||||
Big1 = big.NewInt(1)
|
Big1 = big.NewInt(1)
|
||||||
Big2 = big.NewInt(2)
|
Big2 = big.NewInt(2)
|
||||||
Big3 = big.NewInt(3)
|
Big3 = big.NewInt(3)
|
||||||
Big0 = big.NewInt(0)
|
Big0 = big.NewInt(0)
|
||||||
BigTrue = Big1
|
Big32 = big.NewInt(32)
|
||||||
BigFalse = Big0
|
Big256 = big.NewInt(0xff)
|
||||||
Big32 = big.NewInt(32)
|
Big257 = big.NewInt(257)
|
||||||
Big36 = big.NewInt(36)
|
|
||||||
Big97 = big.NewInt(97)
|
|
||||||
Big98 = big.NewInt(98)
|
|
||||||
Big256 = big.NewInt(0xff)
|
|
||||||
Big257 = big.NewInt(257)
|
|
||||||
MaxBig = String2Big("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
155
common/bytes.go
155
common/bytes.go
@ -18,12 +18,7 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
|
||||||
"math/big"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func ToHex(b []byte) string {
|
func ToHex(b []byte) string {
|
||||||
@ -48,65 +43,6 @@ func FromHex(s string) []byte {
|
|||||||
return nil
|
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
|
// Copy bytes
|
||||||
//
|
//
|
||||||
// Returns an exact copy of the provided 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 {
|
func RightPadBytes(slice []byte, l int) []byte {
|
||||||
if l < len(slice) {
|
if l < len(slice) {
|
||||||
return slice
|
return slice
|
||||||
@ -220,47 +109,3 @@ func LeftPadBytes(slice []byte, l int) []byte {
|
|||||||
|
|
||||||
return padded
|
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
|
|
||||||
}
|
|
||||||
|
@ -27,54 +27,6 @@ type BytesSuite struct{}
|
|||||||
|
|
||||||
var _ = checker.Suite(&BytesSuite{})
|
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) {
|
func (s *BytesSuite) TestCopyBytes(c *checker.C) {
|
||||||
data1 := []byte{1, 2, 3, 4}
|
data1 := []byte{1, 2, 3, 4}
|
||||||
exp1 := []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) {
|
func (s *BytesSuite) TestLeftPadBytes(c *checker.C) {
|
||||||
val1 := []byte{1, 2, 3, 4}
|
val1 := []byte{1, 2, 3, 4}
|
||||||
exp1 := []byte{0, 0, 0, 0, 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)
|
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) {
|
func (s *BytesSuite) TestRightPadBytes(c *checker.C) {
|
||||||
val := []byte{1, 2, 3, 4}
|
val := []byte{1, 2, 3, 4}
|
||||||
exp := []byte{1, 2, 3, 4, 0, 0, 0, 0}
|
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)
|
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) {
|
func TestFromHex(t *testing.T) {
|
||||||
input := "0x01"
|
input := "0x01"
|
||||||
expected := []byte{1}
|
expected := []byte{1}
|
||||||
|
190
common/icap.go
190
common/icap.go
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
// 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, "")
|
|
||||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
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.")
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
143
common/math/big.go
Normal file
143
common/math/big.go
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
196
common/math/big_test.go
Normal file
196
common/math/big_test.go
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package math
|
package math
|
||||||
|
|
||||||
import gmath "math"
|
import "strconv"
|
||||||
|
|
||||||
/*
|
const (
|
||||||
* NOTE: The following methods need to be optimised using either bit checking or asm
|
// 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
|
||||||
|
|
||||||
// SafeSub returns subtraction result and whether overflow occurred.
|
// SafeSub returns subtraction result and whether overflow occurred.
|
||||||
func SafeSub(x, y uint64) (uint64, bool) {
|
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.
|
// SafeAdd returns the result and whether overflow occurred.
|
||||||
func SafeAdd(x, y uint64) (uint64, bool) {
|
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.
|
// SafeMul returns multiplication result and whether overflow occurred.
|
||||||
@ -21,5 +74,5 @@ func SafeMul(x, y uint64) (uint64, bool) {
|
|||||||
if x == 0 || y == 0 {
|
if x == 0 || y == 0 {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
return x * y, y > gmath.MaxUint64/x
|
return x * y, y > MaxUint64/x
|
||||||
}
|
}
|
||||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package math
|
package math
|
||||||
|
|
||||||
import (
|
import (
|
||||||
gmath "math"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -21,17 +36,18 @@ func TestOverflow(t *testing.T) {
|
|||||||
op operation
|
op operation
|
||||||
}{
|
}{
|
||||||
// add operations
|
// add operations
|
||||||
{gmath.MaxUint64, 1, true, add},
|
{MaxUint64, 1, true, add},
|
||||||
{gmath.MaxUint64 - 1, 1, false, add},
|
{MaxUint64 - 1, 1, false, add},
|
||||||
|
|
||||||
// sub operations
|
// sub operations
|
||||||
{0, 1, true, sub},
|
{0, 1, true, sub},
|
||||||
{0, 0, false, sub},
|
{0, 0, false, sub},
|
||||||
|
|
||||||
// mul operations
|
// mul operations
|
||||||
|
{0, 0, false, mul},
|
||||||
{10, 10, false, mul},
|
{10, 10, false, mul},
|
||||||
{gmath.MaxUint64, 2, true, mul},
|
{MaxUint64, 2, true, mul},
|
||||||
{gmath.MaxUint64, 1, false, mul},
|
{MaxUint64, 1, false, mul},
|
||||||
} {
|
} {
|
||||||
var overflows bool
|
var overflows bool
|
||||||
switch test.op {
|
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")
|
||||||
|
}
|
||||||
|
@ -18,7 +18,6 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type StorageSize float64
|
type StorageSize float64
|
||||||
@ -36,54 +35,3 @@ func (self StorageSize) String() string {
|
|||||||
func (self StorageSize) Int64() int64 {
|
func (self StorageSize) Int64() int64 {
|
||||||
return int64(self)
|
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)
|
|
||||||
}
|
|
||||||
|
@ -17,43 +17,22 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"testing"
|
||||||
|
|
||||||
checker "gopkg.in/check.v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SizeSuite struct{}
|
func TestStorageSizeString(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
size StorageSize
|
||||||
|
str string
|
||||||
|
}{
|
||||||
|
{2381273, "2.38 mB"},
|
||||||
|
{2192, "2.19 kB"},
|
||||||
|
{12, "12.00 B"},
|
||||||
|
}
|
||||||
|
|
||||||
var _ = checker.Suite(&SizeSuite{})
|
for _, test := range tests {
|
||||||
|
if test.size.String() != test.str {
|
||||||
func (s *SizeSuite) TestStorageSizeString(c *checker.C) {
|
t.Errorf("%f: got %q, want %q", float64(test.size), test.size.String(), test.str)
|
||||||
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")
|
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) }
|
|||||||
// Get the string representation of the underlying hash
|
// Get the string representation of the underlying hash
|
||||||
func (h Hash) Str() string { return string(h[:]) }
|
func (h Hash) Str() string { return string(h[:]) }
|
||||||
func (h Hash) Bytes() []byte { return 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[:]) }
|
func (h Hash) Hex() string { return hexutil.Encode(h[:]) }
|
||||||
|
|
||||||
// UnmarshalJSON parses a hash in its hex from to a hash.
|
// 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
|
// Get the string representation of the underlying address
|
||||||
func (a Address) Str() string { return string(a[:]) }
|
func (a Address) Str() string { return string(a[:]) }
|
||||||
func (a Address) Bytes() []byte { return 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) Hash() Hash { return BytesToHash(a[:]) }
|
||||||
func (a Address) Hex() string { return hexutil.Encode(a[:]) }
|
func (a Address) Hex() string { return hexutil.Encode(a[:]) }
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ func HexTo_N_(s string) _N_ { return BytesTo_N_(FromHex(s)) }
|
|||||||
// Get the string representation of the underlying hash
|
// Get the string representation of the underlying hash
|
||||||
func (h _N_) Str() string { return string(h[:]) }
|
func (h _N_) Str() string { return string(h[:]) }
|
||||||
func (h _N_) Bytes() []byte { return 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[:]) }
|
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
|
// Sets the hash to the value of b. If b is larger than len(h) it will panic
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
@ -73,7 +74,7 @@ var (
|
|||||||
// This is the content of the genesis block used by the benchmarks.
|
// This is the content of the genesis block used by the benchmarks.
|
||||||
benchRootKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
benchRootKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
benchRootAddr = crypto.PubkeyToAddress(benchRootKey.PublicKey)
|
benchRootAddr = crypto.PubkeyToAddress(benchRootKey.PublicKey)
|
||||||
benchRootFunds = common.BigPow(2, 100)
|
benchRootFunds = math.BigPow(2, 100)
|
||||||
)
|
)
|
||||||
|
|
||||||
// genValueTx returns a block generator that includes a single
|
// genValueTx returns a block generator that includes a single
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
@ -209,7 +210,7 @@ func ValidateHeader(config *params.ChainConfig, pow pow.PoW, header *types.Heade
|
|||||||
}
|
}
|
||||||
|
|
||||||
if uncle {
|
if uncle {
|
||||||
if header.Time.Cmp(common.MaxBig) == 1 {
|
if header.Time.Cmp(math.MaxBig256) == 1 {
|
||||||
return BlockTSTooBigErr
|
return BlockTSTooBigErr
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -344,7 +345,7 @@ func calcDifficultyFrontier(time, parentTime uint64, parentNumber, parentDiff *b
|
|||||||
expDiff := periodCount.Sub(periodCount, common.Big2)
|
expDiff := periodCount.Sub(periodCount, common.Big2)
|
||||||
expDiff.Exp(common.Big2, expDiff, nil)
|
expDiff.Exp(common.Big2, expDiff, nil)
|
||||||
diff.Add(diff, expDiff)
|
diff.Add(diff, expDiff)
|
||||||
diff = common.BigMax(diff, params.MinimumDifficulty)
|
diff = math.BigMax(diff, params.MinimumDifficulty)
|
||||||
}
|
}
|
||||||
|
|
||||||
return diff
|
return diff
|
||||||
@ -372,13 +373,13 @@ func CalcGasLimit(parent *types.Block) *big.Int {
|
|||||||
*/
|
*/
|
||||||
gl := new(big.Int).Sub(parent.GasLimit(), decay)
|
gl := new(big.Int).Sub(parent.GasLimit(), decay)
|
||||||
gl = gl.Add(gl, contrib)
|
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
|
// however, if we're now below the target (TargetGasLimit) we increase the
|
||||||
// limit as much as we can (parentGasLimit / 1024 -1)
|
// limit as much as we can (parentGasLimit / 1024 -1)
|
||||||
if gl.Cmp(params.TargetGasLimit) < 0 {
|
if gl.Cmp(params.TargetGasLimit) < 0 {
|
||||||
gl.Add(parent.GasLimit(), decay)
|
gl.Add(parent.GasLimit(), decay)
|
||||||
gl.Set(common.BigMin(gl, params.TargetGasLimit))
|
gl.Set(math.BigMin(gl, params.TargetGasLimit))
|
||||||
}
|
}
|
||||||
return gl
|
return gl
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/crypto/sha3"
|
"github.com/ethereum/go-ethereum/crypto/sha3"
|
||||||
@ -53,11 +54,11 @@ func (d *diffTest) UnmarshalJSON(b []byte) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
d.ParentTimestamp = common.String2Big(ext.ParentTimestamp).Uint64()
|
d.ParentTimestamp = math.MustParseUint64(ext.ParentTimestamp)
|
||||||
d.ParentDifficulty = common.String2Big(ext.ParentDifficulty)
|
d.ParentDifficulty = math.MustParseBig256(ext.ParentDifficulty)
|
||||||
d.CurrentTimestamp = common.String2Big(ext.CurrentTimestamp).Uint64()
|
d.CurrentTimestamp = math.MustParseUint64(ext.CurrentTimestamp)
|
||||||
d.CurrentBlocknumber = common.String2Big(ext.CurrentBlocknumber)
|
d.CurrentBlocknumber = math.MustParseBig256(ext.CurrentBlocknumber)
|
||||||
d.CurrentDifficulty = common.String2Big(ext.CurrentDifficulty)
|
d.CurrentDifficulty = math.MustParseBig256(ext.CurrentDifficulty)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"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
|
// creating with empty hash always works
|
||||||
statedb, _ := state.New(common.Hash{}, chainDb)
|
statedb, _ := state.New(common.Hash{}, chainDb)
|
||||||
for addr, account := range genesis.Alloc {
|
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)
|
address := common.HexToAddress(addr)
|
||||||
statedb.AddBalance(address, common.String2Big(account.Balance))
|
statedb.AddBalance(address, balance)
|
||||||
statedb.SetCode(address, common.FromHex(account.Code))
|
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 {
|
for key, value := range account.Storage {
|
||||||
statedb.SetState(address, common.HexToHash(key), common.HexToHash(value))
|
statedb.SetState(address, common.HexToHash(key), common.HexToHash(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
root, stateBatch := statedb.CommitBatch(false)
|
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{
|
block := types.NewBlock(&types.Header{
|
||||||
Nonce: types.EncodeNonce(common.String2Big(genesis.Nonce).Uint64()),
|
Nonce: types.EncodeNonce(nonce),
|
||||||
Time: common.String2Big(genesis.Timestamp),
|
Time: timestamp,
|
||||||
ParentHash: common.HexToHash(genesis.ParentHash),
|
ParentHash: common.HexToHash(genesis.ParentHash),
|
||||||
Extra: common.FromHex(genesis.ExtraData),
|
Extra: common.FromHex(genesis.ExtraData),
|
||||||
GasLimit: common.String2Big(genesis.GasLimit),
|
GasLimit: new(big.Int).SetUint64(gaslimit),
|
||||||
Difficulty: difficulty,
|
Difficulty: difficulty,
|
||||||
MixDigest: common.HexToHash(genesis.Mixhash),
|
MixDigest: common.HexToHash(genesis.Mixhash),
|
||||||
Coinbase: common.HexToAddress(genesis.Coinbase),
|
Coinbase: common.HexToAddress(genesis.Coinbase),
|
||||||
@ -153,7 +179,7 @@ func WriteGenesisBlockForTesting(db ethdb.Database, accounts ...GenesisAccount)
|
|||||||
if i != 0 {
|
if i != 0 {
|
||||||
accountJson += ","
|
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 += "}"
|
accountJson += "}"
|
||||||
|
|
||||||
@ -163,7 +189,10 @@ func WriteGenesisBlockForTesting(db ethdb.Database, accounts ...GenesisAccount)
|
|||||||
"difficulty":"0x%x",
|
"difficulty":"0x%x",
|
||||||
"alloc": %s
|
"alloc": %s
|
||||||
}`, types.EncodeNonce(0), params.GenesisGasLimit.Bytes(), params.GenesisDifficulty.Bytes(), accountJson)
|
}`, 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
|
return block
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
@ -281,7 +282,7 @@ func (self *StateTransition) refundGas() {
|
|||||||
|
|
||||||
// Apply refund counter, capped to half of the used gas.
|
// Apply refund counter, capped to half of the used gas.
|
||||||
uhalf := remaining.Div(self.gasUsed(), common.Big2)
|
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.gas += refund.Uint64()
|
||||||
|
|
||||||
self.state.AddBalance(sender.Address(), refund.Mul(refund, self.gasPrice))
|
self.state.AddBalance(sender.Address(), refund.Mul(refund, self.gasPrice))
|
||||||
|
@ -29,6 +29,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
func transaction(nonce uint64, gaslimit *big.Int, key *ecdsa.PrivateKey) *types.Transaction {
|
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
|
// 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)
|
tx0 := transaction(0, big.NewInt(100000), key)
|
||||||
tx1 := transaction(1, 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)
|
statedb, _ = state.New(common.Hash{}, db)
|
||||||
// simulate that the new head block included tx0 and tx1
|
// simulate that the new head block included tx0 and tx1
|
||||||
statedb.SetNonce(address, 2)
|
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
|
trigger = false
|
||||||
}
|
}
|
||||||
return stdb, nil
|
return stdb, nil
|
||||||
|
@ -20,7 +20,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
)
|
)
|
||||||
@ -60,7 +59,7 @@ func (b *Bloom) Add(d *big.Int) {
|
|||||||
|
|
||||||
// Big converts b to a big integer.
|
// Big converts b to a big integer.
|
||||||
func (b Bloom) Big() *big.Int {
|
func (b Bloom) Big() *big.Int {
|
||||||
return common.Bytes2Big(b[:])
|
return new(big.Int).SetBytes(b[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Bloom) Bytes() []byte {
|
func (b Bloom) Bytes() []byte {
|
||||||
@ -72,7 +71,8 @@ func (b Bloom) Test(test *big.Int) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b Bloom) TestBytes(test []byte) 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.
|
// MarshalJSON encodes b as a hex string with 0x prefix.
|
||||||
|
@ -17,15 +17,10 @@
|
|||||||
package vm
|
package vm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
)
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
|
||||||
var (
|
|
||||||
U256 = common.U256 // Shortcut to common.U256
|
|
||||||
S256 = common.S256 // Shortcut to common.S256
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// calculates the memory size required for a step
|
// 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 {
|
func getData(data []byte, start, size *big.Int) []byte {
|
||||||
dlen := big.NewInt(int64(len(data)))
|
dlen := big.NewInt(int64(len(data)))
|
||||||
|
|
||||||
s := common.BigMin(start, dlen)
|
s := math.BigMin(start, dlen)
|
||||||
e := common.BigMin(new(big.Int).Add(s, size), dlen)
|
e := math.BigMin(new(big.Int).Add(s, size), dlen)
|
||||||
return common.RightPadBytes(data[s.Uint64():e.Uint64()], int(size.Uint64()))
|
return common.RightPadBytes(data[s.Uint64():e.Uint64()], int(size.Uint64()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,3 +56,12 @@ func toWordSize(size uint64) uint64 {
|
|||||||
|
|
||||||
return (size + 31) / 32
|
return (size + 31) / 32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func allZero(b []byte) bool {
|
||||||
|
for _, byte := range b {
|
||||||
|
if byte != 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
@ -19,6 +19,7 @@ package vm
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"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
|
// "in" is (hash, v, r, s), each 32 bytes
|
||||||
// but for ecrecover we want (r, s, v)
|
// but for ecrecover we want (r, s, v)
|
||||||
|
|
||||||
r := common.BytesToBig(in[64:96])
|
r := new(big.Int).SetBytes(in[64:96])
|
||||||
s := common.BytesToBig(in[96:128])
|
s := new(big.Int).SetBytes(in[96:128])
|
||||||
v := in[63] - 27
|
v := in[63] - 27
|
||||||
|
|
||||||
// tighter sig s values in homestead only apply to tx sigs
|
// 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) {
|
if !allZero(in[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) {
|
||||||
log.Trace(fmt.Sprintf("ECRECOVER error: v, r or s value invalid"))
|
log.Trace("ECRECOVER error: v, r or s value invalid")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// v needs to be at the end for libsecp256k1
|
// v needs to be at the end for libsecp256k1
|
||||||
|
@ -31,7 +31,7 @@ var bigZero = new(big.Int)
|
|||||||
|
|
||||||
func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
x, y := stack.pop(), stack.pop()
|
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)
|
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) {
|
func opSub(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
x, y := stack.pop(), stack.pop()
|
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)
|
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) {
|
func opMul(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
x, y := stack.pop(), stack.pop()
|
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)
|
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) {
|
func opDiv(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
x, y := stack.pop(), stack.pop()
|
x, y := stack.pop(), stack.pop()
|
||||||
if y.Cmp(common.Big0) != 0 {
|
if y.Cmp(common.Big0) != 0 {
|
||||||
stack.push(U256(x.Div(x, y)))
|
stack.push(math.U256(x.Div(x, y)))
|
||||||
} else {
|
} else {
|
||||||
stack.push(new(big.Int))
|
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) {
|
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 {
|
if y.Cmp(common.Big0) == 0 {
|
||||||
stack.push(new(big.Int))
|
stack.push(new(big.Int))
|
||||||
return nil, nil
|
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 := x.Div(x.Abs(x), y.Abs(y))
|
||||||
res.Mul(res, n)
|
res.Mul(res, n)
|
||||||
|
|
||||||
stack.push(U256(res))
|
stack.push(math.U256(res))
|
||||||
}
|
}
|
||||||
evm.interpreter.intPool.put(y)
|
evm.interpreter.intPool.put(y)
|
||||||
return nil, nil
|
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 {
|
if y.Cmp(common.Big0) == 0 {
|
||||||
stack.push(new(big.Int))
|
stack.push(new(big.Int))
|
||||||
} else {
|
} else {
|
||||||
stack.push(U256(x.Mod(x, y)))
|
stack.push(math.U256(x.Mod(x, y)))
|
||||||
}
|
}
|
||||||
evm.interpreter.intPool.put(y)
|
evm.interpreter.intPool.put(y)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func opSmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
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 {
|
if y.Cmp(common.Big0) == 0 {
|
||||||
stack.push(new(big.Int))
|
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 := x.Mod(x.Abs(x), y.Abs(y))
|
||||||
res.Mul(res, n)
|
res.Mul(res, n)
|
||||||
|
|
||||||
stack.push(U256(res))
|
stack.push(math.U256(res))
|
||||||
}
|
}
|
||||||
evm.interpreter.intPool.put(y)
|
evm.interpreter.intPool.put(y)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -140,13 +140,13 @@ func opSignExtend(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stac
|
|||||||
num := stack.pop()
|
num := stack.pop()
|
||||||
mask := back.Lsh(common.Big1, bit)
|
mask := back.Lsh(common.Big1, bit)
|
||||||
mask.Sub(mask, common.Big1)
|
mask.Sub(mask, common.Big1)
|
||||||
if common.BitTest(num, int(bit)) {
|
if num.Bit(int(bit)) > 0 {
|
||||||
num.Or(num, mask.Not(mask))
|
num.Or(num, mask.Not(mask))
|
||||||
} else {
|
} else {
|
||||||
num.And(num, mask)
|
num.And(num, mask)
|
||||||
}
|
}
|
||||||
|
|
||||||
stack.push(U256(num))
|
stack.push(math.U256(num))
|
||||||
}
|
}
|
||||||
|
|
||||||
evm.interpreter.intPool.put(back)
|
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) {
|
func opNot(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
x := stack.pop()
|
x := stack.pop()
|
||||||
stack.push(U256(x.Not(x)))
|
stack.push(math.U256(x.Not(x)))
|
||||||
return nil, nil
|
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) {
|
func opSlt(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(S256(y)) < 0 {
|
if x.Cmp(math.S256(y)) < 0 {
|
||||||
stack.push(evm.interpreter.intPool.get().SetUint64(1))
|
stack.push(evm.interpreter.intPool.get().SetUint64(1))
|
||||||
} else {
|
} else {
|
||||||
stack.push(new(big.Int))
|
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) {
|
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 {
|
if x.Cmp(y) > 0 {
|
||||||
stack.push(evm.interpreter.intPool.get().SetUint64(1))
|
stack.push(evm.interpreter.intPool.get().SetUint64(1))
|
||||||
} else {
|
} else {
|
||||||
@ -269,7 +269,7 @@ func opAddmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S
|
|||||||
if z.Cmp(bigZero) > 0 {
|
if z.Cmp(bigZero) > 0 {
|
||||||
add := x.Add(x, y)
|
add := x.Add(x, y)
|
||||||
add.Mod(add, z)
|
add.Mod(add, z)
|
||||||
stack.push(U256(add))
|
stack.push(math.U256(add))
|
||||||
} else {
|
} else {
|
||||||
stack.push(new(big.Int))
|
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 {
|
if z.Cmp(bigZero) > 0 {
|
||||||
mul := x.Mul(x, y)
|
mul := x.Mul(x, y)
|
||||||
mul.Mod(mul, z)
|
mul.Mod(mul, z)
|
||||||
stack.push(U256(mul))
|
stack.push(math.U256(mul))
|
||||||
} else {
|
} else {
|
||||||
stack.push(new(big.Int))
|
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)
|
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)
|
evm.interpreter.intPool.put(offset, size)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func opAddress(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
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
|
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) {
|
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
|
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) {
|
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
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func opNumber(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
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
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func opDifficulty(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
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
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func opGasLimit(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
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
|
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) {
|
func opMload(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
offset := stack.pop()
|
offset := stack.pop()
|
||||||
val := common.BigD(memory.Get(offset.Int64(), 32))
|
val := new(big.Int).SetBytes(memory.Get(offset.Int64(), 32))
|
||||||
stack.push(val)
|
stack.push(val)
|
||||||
|
|
||||||
evm.interpreter.intPool.put(offset)
|
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) {
|
func opMstore(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
// pop value of the stack
|
// pop value of the stack
|
||||||
mStart, val := stack.pop(), stack.pop()
|
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)
|
evm.interpreter.intPool.put(mStart, val)
|
||||||
return nil, nil
|
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) {
|
func opJumpi(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
pos, cond := stack.pop(), stack.pop()
|
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) {
|
if !contract.jumpdests.has(contract.CodeHash, contract.Code, pos) {
|
||||||
nop := contract.GetOp(pos.Uint64())
|
nop := contract.GetOp(pos.Uint64())
|
||||||
return nil, fmt.Errorf("invalid jump destination (%v) %v", nop, pos)
|
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()
|
gas := stack.pop().Uint64()
|
||||||
// pop gas and value of the stack.
|
// pop gas and value of the stack.
|
||||||
addr, value := stack.pop(), stack.pop()
|
addr, value := stack.pop(), stack.pop()
|
||||||
value = U256(value)
|
value = math.U256(value)
|
||||||
// pop input size and offset
|
// pop input size and offset
|
||||||
inOffset, inSize := stack.pop(), stack.pop()
|
inOffset, inSize := stack.pop(), stack.pop()
|
||||||
// pop return size and offset
|
// pop return size and offset
|
||||||
@ -605,7 +605,7 @@ func opCallCode(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack
|
|||||||
gas := stack.pop().Uint64()
|
gas := stack.pop().Uint64()
|
||||||
// pop gas and value of the stack.
|
// pop gas and value of the stack.
|
||||||
addr, value := stack.pop(), stack.pop()
|
addr, value := stack.pop(), stack.pop()
|
||||||
value = U256(value)
|
value = math.U256(value)
|
||||||
// pop input size and offset
|
// pop input size and offset
|
||||||
inOffset, inSize := stack.pop(), stack.pop()
|
inOffset, inSize := stack.pop(), stack.pop()
|
||||||
// pop return size and offset
|
// pop return size and offset
|
||||||
@ -711,7 +711,7 @@ func makeLog(size int) executionFunc {
|
|||||||
func makePush(size uint64, bsize *big.Int) executionFunc {
|
func makePush(size uint64, bsize *big.Int) executionFunc {
|
||||||
return func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
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)
|
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
|
*pc += size
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ package vm
|
|||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
)
|
)
|
||||||
|
|
||||||
func memorySha3(stack *Stack) *big.Int {
|
func memorySha3(stack *Stack) *big.Int {
|
||||||
@ -42,20 +42,20 @@ func memoryCall(stack *Stack) *big.Int {
|
|||||||
x := calcMemSize(stack.Back(5), stack.Back(6))
|
x := calcMemSize(stack.Back(5), stack.Back(6))
|
||||||
y := calcMemSize(stack.Back(3), stack.Back(4))
|
y := calcMemSize(stack.Back(3), stack.Back(4))
|
||||||
|
|
||||||
return common.BigMax(x, y)
|
return math.BigMax(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func memoryCallCode(stack *Stack) *big.Int {
|
func memoryCallCode(stack *Stack) *big.Int {
|
||||||
x := calcMemSize(stack.Back(5), stack.Back(6))
|
x := calcMemSize(stack.Back(5), stack.Back(6))
|
||||||
y := calcMemSize(stack.Back(3), stack.Back(4))
|
y := calcMemSize(stack.Back(3), stack.Back(4))
|
||||||
|
|
||||||
return common.BigMax(x, y)
|
return math.BigMax(x, y)
|
||||||
}
|
}
|
||||||
func memoryDelegateCall(stack *Stack) *big.Int {
|
func memoryDelegateCall(stack *Stack) *big.Int {
|
||||||
x := calcMemSize(stack.Back(4), stack.Back(5))
|
x := calcMemSize(stack.Back(4), stack.Back(5))
|
||||||
y := calcMemSize(stack.Back(2), stack.Back(3))
|
y := calcMemSize(stack.Back(2), stack.Back(3))
|
||||||
|
|
||||||
return common.BigMax(x, y)
|
return math.BigMax(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func memoryReturn(stack *Stack) *big.Int {
|
func memoryReturn(stack *Stack) *big.Int {
|
||||||
|
@ -87,7 +87,7 @@ func TestExecute(t *testing.T) {
|
|||||||
t.Fatal("didn't expect error", err)
|
t.Fatal("didn't expect error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
num := common.BytesToBig(ret)
|
num := new(big.Int).SetBytes(ret)
|
||||||
if num.Cmp(big.NewInt(10)) != 0 {
|
if num.Cmp(big.NewInt(10)) != 0 {
|
||||||
t.Error("Expected 10, got", num)
|
t.Error("Expected 10, got", num)
|
||||||
}
|
}
|
||||||
@ -111,7 +111,7 @@ func TestCall(t *testing.T) {
|
|||||||
t.Fatal("didn't expect error", err)
|
t.Fatal("didn't expect error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
num := common.BytesToBig(ret)
|
num := new(big.Int).SetBytes(ret)
|
||||||
if num.Cmp(big.NewInt(10)) != 0 {
|
if num.Cmp(big.NewInt(10)) != 0 {
|
||||||
t.Error("Expected 10, got", num)
|
t.Error("Expected 10, got", num)
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ func ToECDSA(prv []byte) *ecdsa.PrivateKey {
|
|||||||
|
|
||||||
priv := new(ecdsa.PrivateKey)
|
priv := new(ecdsa.PrivateKey)
|
||||||
priv.PublicKey.Curve = S256()
|
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)
|
priv.PublicKey.X, priv.PublicKey.Y = priv.PublicKey.Curve.ScalarBaseMult(prv)
|
||||||
return priv
|
return priv
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"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) {
|
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
|
statedb := state.(EthApiState).state
|
||||||
from := statedb.GetOrNewStateObject(msg.From())
|
from := statedb.GetOrNewStateObject(msg.From())
|
||||||
from.SetBalance(common.MaxBig)
|
from.SetBalance(math.MaxBig256)
|
||||||
vmError := func() error { return nil }
|
vmError := func() error { return nil }
|
||||||
|
|
||||||
context := core.NewEVMContext(msg, header, b.eth.BlockChain())
|
context := core.NewEVMContext(msg, header, b.eth.BlockChain())
|
||||||
|
@ -21,7 +21,6 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -31,6 +30,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"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"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
@ -38,6 +38,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/syndtr/goleveldb/leveldb"
|
"github.com/syndtr/goleveldb/leveldb"
|
||||||
@ -45,9 +46,11 @@ import (
|
|||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultGas = 90000
|
const (
|
||||||
|
defaultGas = 90000
|
||||||
var emptyHex = "0x"
|
defaultGasPrice = 50 * params.Shannon
|
||||||
|
emptyHex = "0x"
|
||||||
|
)
|
||||||
|
|
||||||
// PublicEthereumAPI provides an API to access Ethereum related information.
|
// PublicEthereumAPI provides an API to access Ethereum related information.
|
||||||
// It offers only methods that operate on public data that is freely available to anyone.
|
// 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)
|
gas = big.NewInt(50000000)
|
||||||
}
|
}
|
||||||
if gasPrice.BitLen() == 0 {
|
if gasPrice.BitLen() == 0 {
|
||||||
gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon)
|
gasPrice = new(big.Int).SetUint64(defaultGasPrice)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new call message
|
// 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)
|
// Setup the gas pool (also for unmetered requests)
|
||||||
// and apply the message.
|
// 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)
|
res, gas, err := core.ApplyMessage(evm, msg, gp)
|
||||||
if err := vmError(); err != nil {
|
if err := vmError(); err != nil {
|
||||||
return nil, common.Big0, err
|
return nil, common.Big0, err
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"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 {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
from.SetBalance(common.MaxBig)
|
from.SetBalance(math.MaxBig256)
|
||||||
|
|
||||||
vmstate := light.NewVMState(ctx, stateDb)
|
vmstate := light.NewVMState(ctx, stateDb)
|
||||||
context := core.NewEVMContext(msg, header, b.eth.blockchain)
|
context := core.NewEVMContext(msg, header, b.eth.blockchain)
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"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 {
|
if err == nil {
|
||||||
from := statedb.GetOrNewStateObject(testBankAddress)
|
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)}
|
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 := vm.NewEVM(context, statedb, config, vm.Config{})
|
||||||
|
|
||||||
//vmenv := core.NewEnv(statedb, config, bc, msg, header, 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)
|
ret, _, _ := core.ApplyMessage(vmenv, msg, gp)
|
||||||
res = append(res, ret...)
|
res = append(res, ret...)
|
||||||
}
|
}
|
||||||
@ -136,7 +137,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
|
|||||||
vmstate := light.NewVMState(ctx, state)
|
vmstate := light.NewVMState(ctx, state)
|
||||||
from, err := state.GetOrNewStateObject(ctx, testBankAddress)
|
from, err := state.GetOrNewStateObject(ctx, testBankAddress)
|
||||||
if err == nil {
|
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)}
|
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 := vm.NewEVM(context, vmstate, config, vm.Config{})
|
||||||
|
|
||||||
//vmenv := light.NewEnv(ctx, state, config, lc, msg, header, 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)
|
ret, _, _ := core.ApplyMessage(vmenv, msg, gp)
|
||||||
if vmstate.Error() == nil {
|
if vmstate.Error() == nil {
|
||||||
res = append(res, ret...)
|
res = append(res, ret...)
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"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)
|
statedb, err := state.New(header.Root, db)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
from := statedb.GetOrNewStateObject(testBankAddress)
|
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)}
|
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)
|
context := core.NewEVMContext(msg, header, bc)
|
||||||
vmenv := vm.NewEVM(context, statedb, config, vm.Config{})
|
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)
|
ret, _, _ := core.ApplyMessage(vmenv, msg, gp)
|
||||||
res = append(res, ret...)
|
res = append(res, ret...)
|
||||||
}
|
}
|
||||||
@ -186,12 +187,12 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
|
|||||||
vmstate := NewVMState(ctx, state)
|
vmstate := NewVMState(ctx, state)
|
||||||
from, err := state.GetOrNewStateObject(ctx, testBankAddress)
|
from, err := state.GetOrNewStateObject(ctx, testBankAddress)
|
||||||
if err == nil {
|
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)}
|
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)
|
context := core.NewEVMContext(msg, header, lc)
|
||||||
vmenv := vm.NewEVM(context, vmstate, config, vm.Config{})
|
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)
|
ret, _, _ := core.ApplyMessage(vmenv, msg, gp)
|
||||||
if vmstate.Error() == nil {
|
if vmstate.Error() == nil {
|
||||||
res = append(res, ret...)
|
res = append(res, ret...)
|
||||||
|
@ -561,7 +561,7 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB
|
|||||||
// Ignore any transactions (and accounts subsequently) with low gas limits
|
// Ignore any transactions (and accounts subsequently) with low gas limits
|
||||||
if tx.GasPrice().Cmp(gasPrice) < 0 && !env.ownedAccounts.Has(from) {
|
if tx.GasPrice().Cmp(gasPrice) < 0 && !env.ownedAccounts.Has(from) {
|
||||||
// Pop the current low-priced transaction without shifting in the next from the account
|
// 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)
|
env.lowGasTxs = append(env.lowGasTxs, tx)
|
||||||
txs.Pop()
|
txs.Pop()
|
||||||
|
@ -24,7 +24,6 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/ethclient"
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
"github.com/ethereum/go-ethereum/ethstats"
|
"github.com/ethereum/go-ethereum/ethstats"
|
||||||
@ -145,9 +144,9 @@ func NewNode(datadir string, config *NodeConfig) (stack *Node, _ error) {
|
|||||||
LightMode: true,
|
LightMode: true,
|
||||||
DatabaseCache: config.EthereumDatabaseCache,
|
DatabaseCache: config.EthereumDatabaseCache,
|
||||||
NetworkId: config.EthereumNetworkID,
|
NetworkId: config.EthereumNetworkID,
|
||||||
GasPrice: new(big.Int).Mul(big.NewInt(20), common.Shannon),
|
GasPrice: new(big.Int).SetUint64(20 * params.Shannon),
|
||||||
GpoMinGasPrice: new(big.Int).Mul(big.NewInt(20), common.Shannon),
|
GpoMinGasPrice: new(big.Int).SetUint64(50 * params.Shannon),
|
||||||
GpoMaxGasPrice: new(big.Int).Mul(big.NewInt(500), common.Shannon),
|
GpoMaxGasPrice: new(big.Int).SetUint64(500 * params.Shannon),
|
||||||
GpoFullBlockRatio: 80,
|
GpoFullBlockRatio: 80,
|
||||||
GpobaseStepDown: 10,
|
GpobaseStepDown: 10,
|
||||||
GpobaseStepUp: 100,
|
GpobaseStepUp: 100,
|
||||||
|
@ -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.
|
// This file is part of the go-ethereum library.
|
||||||
//
|
//
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
// 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
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package math
|
package params
|
||||||
|
|
||||||
import (
|
const (
|
||||||
"math/big"
|
// These are the multipliers for ether denominations.
|
||||||
|
// Example: To get the wei value of an amount in 'douglas', use
|
||||||
"github.com/ethereum/go-ethereum/common"
|
//
|
||||||
|
// 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
|
|
||||||
}
|
|
@ -26,6 +26,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"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)
|
return fmt.Errorf("did not find expected post-state account: %s", addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if balance := statedb.GetBalance(address); balance.Cmp(common.Big(account.Balance)) != 0 {
|
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], common.String2Big(account.Balance), balance)
|
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)
|
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) {
|
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)
|
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)
|
root, _ := statedb.Commit(false)
|
||||||
statedb.Reset(root)
|
statedb.Reset(root)
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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/types"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
@ -161,7 +162,7 @@ func verifyTxFields(chainConfig *params.ChainConfig, txTest TransactionTest, dec
|
|||||||
|
|
||||||
var decodedSender common.Address
|
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)
|
decodedSender, err = types.Sender(signer, decodedTx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
@ -119,8 +120,8 @@ func insertAccount(state *state.StateDB, saddr string, account Account) {
|
|||||||
}
|
}
|
||||||
addr := common.HexToAddress(saddr)
|
addr := common.HexToAddress(saddr)
|
||||||
state.SetCode(addr, common.Hex2Bytes(account.Code))
|
state.SetCode(addr, common.Hex2Bytes(account.Code))
|
||||||
state.SetNonce(addr, common.Big(account.Nonce).Uint64())
|
state.SetNonce(addr, math.MustParseUint64(account.Nonce))
|
||||||
state.SetBalance(addr, common.Big(account.Balance))
|
state.SetBalance(addr, math.MustParseBig256(account.Balance))
|
||||||
for a, v := range account.Storage {
|
for a, v := range account.Storage {
|
||||||
state.SetState(addr, common.HexToHash(a), common.HexToHash(v))
|
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) {
|
func NewEVMEnvironment(vmTest bool, chainConfig *params.ChainConfig, statedb *state.StateDB, envValues map[string]string, tx map[string]string) (*vm.EVM, core.Message) {
|
||||||
var (
|
var (
|
||||||
data = common.FromHex(tx["data"])
|
data = common.FromHex(tx["data"])
|
||||||
gas = common.Big(tx["gasLimit"])
|
gas = math.MustParseBig256(tx["gasLimit"])
|
||||||
price = common.Big(tx["gasPrice"])
|
price = math.MustParseBig256(tx["gasPrice"])
|
||||||
value = common.Big(tx["value"])
|
value = math.MustParseBig256(tx["value"])
|
||||||
nonce = common.Big(tx["nonce"]).Uint64()
|
nonce = math.MustParseUint64(tx["nonce"])
|
||||||
)
|
)
|
||||||
|
|
||||||
origin := common.HexToAddress(tx["caller"])
|
origin := common.HexToAddress(tx["caller"])
|
||||||
@ -198,10 +199,10 @@ func NewEVMEnvironment(vmTest bool, chainConfig *params.ChainConfig, statedb *st
|
|||||||
|
|
||||||
Origin: origin,
|
Origin: origin,
|
||||||
Coinbase: common.HexToAddress(envValues["currentCoinbase"]),
|
Coinbase: common.HexToAddress(envValues["currentCoinbase"]),
|
||||||
BlockNumber: common.Big(envValues["currentNumber"]),
|
BlockNumber: math.MustParseBig256(envValues["currentNumber"]),
|
||||||
Time: common.Big(envValues["currentTimestamp"]),
|
Time: math.MustParseBig256(envValues["currentTimestamp"]),
|
||||||
GasLimit: common.Big(envValues["currentGasLimit"]),
|
GasLimit: math.MustParseBig256(envValues["currentGasLimit"]),
|
||||||
Difficulty: common.Big(envValues["currentDifficulty"]),
|
Difficulty: math.MustParseBig256(envValues["currentDifficulty"]),
|
||||||
GasPrice: price,
|
GasPrice: price,
|
||||||
}
|
}
|
||||||
if context.GasPrice == nil {
|
if context.GasPrice == nil {
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
@ -180,7 +181,7 @@ func runVmTest(test VmTest) error {
|
|||||||
if len(test.Gas) == 0 && err == nil {
|
if len(test.Gas) == 0 && err == nil {
|
||||||
return fmt.Errorf("gas unspecified, indicating an error. VM returned (incorrectly) successful")
|
return fmt.Errorf("gas unspecified, indicating an error. VM returned (incorrectly) successful")
|
||||||
} else {
|
} else {
|
||||||
gexp := common.Big(test.Gas)
|
gexp := math.MustParseBig256(test.Gas)
|
||||||
if gexp.Cmp(gas) != 0 {
|
if gexp.Cmp(gas) != 0 {
|
||||||
return fmt.Errorf("gas failed. Expected %v, got %v\n", gexp, gas)
|
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"])
|
to = common.HexToAddress(exec["address"])
|
||||||
from = common.HexToAddress(exec["caller"])
|
from = common.HexToAddress(exec["caller"])
|
||||||
data = common.FromHex(exec["data"])
|
data = common.FromHex(exec["data"])
|
||||||
gas = common.Big(exec["gas"])
|
gas = math.MustParseBig256(exec["gas"])
|
||||||
value = common.Big(exec["value"])
|
value = math.MustParseBig256(exec["value"])
|
||||||
)
|
)
|
||||||
caller := statedb.GetOrNewStateObject(from)
|
caller := statedb.GetOrNewStateObject(from)
|
||||||
vm.PrecompiledContracts = make(map[common.Address]vm.PrecompiledContract)
|
vm.PrecompiledContracts = make(map[common.Address]vm.PrecompiledContract)
|
||||||
|
@ -23,9 +23,11 @@ import (
|
|||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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"
|
||||||
"github.com/ethereum/go-ethereum/crypto/ecies"
|
"github.com/ethereum/go-ethereum/crypto/ecies"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
@ -66,7 +68,8 @@ func (self *Envelope) Seal(pow time.Duration) {
|
|||||||
for i := 0; i < 1024; i++ {
|
for i := 0; i < 1024; i++ {
|
||||||
binary.BigEndian.PutUint32(d[60:], nonce)
|
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 {
|
if firstBit > bestBit {
|
||||||
self.Nonce, bestBit = nonce, firstBit
|
self.Nonce, bestBit = nonce, firstBit
|
||||||
}
|
}
|
||||||
|
@ -23,10 +23,12 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
gmath "math"
|
||||||
|
"math/big"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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"
|
||||||
"github.com/ethereum/go-ethereum/crypto/ecies"
|
"github.com/ethereum/go-ethereum/crypto/ecies"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"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 nonce := uint64(0); time.Now().UnixNano() < finish; {
|
||||||
for i := 0; i < 1024; i++ {
|
for i := 0; i < 1024; i++ {
|
||||||
binary.BigEndian.PutUint64(buf[56:], nonce)
|
binary.BigEndian.PutUint64(buf[56:], nonce)
|
||||||
h = crypto.Keccak256(buf)
|
d := new(big.Int).SetBytes(crypto.Keccak256(buf))
|
||||||
firstBit := common.FirstBitSet(common.BigD(h))
|
firstBit := math.FirstBitSet(d)
|
||||||
if firstBit > bestBit {
|
if firstBit > bestBit {
|
||||||
e.EnvNonce, bestBit = nonce, firstBit
|
e.EnvNonce, bestBit = nonce, firstBit
|
||||||
if target > 0 && bestBit >= target {
|
if target > 0 && bestBit >= target {
|
||||||
@ -138,9 +140,9 @@ func (e *Envelope) calculatePoW(diff uint32) {
|
|||||||
h := crypto.Keccak256(e.rlpWithoutNonce())
|
h := crypto.Keccak256(e.rlpWithoutNonce())
|
||||||
copy(buf[:32], h)
|
copy(buf[:32], h)
|
||||||
binary.BigEndian.PutUint64(buf[56:], e.EnvNonce)
|
binary.BigEndian.PutUint64(buf[56:], e.EnvNonce)
|
||||||
h = crypto.Keccak256(buf)
|
d := new(big.Int).SetBytes(crypto.Keccak256(buf))
|
||||||
firstBit := common.FirstBitSet(common.BigD(h))
|
firstBit := math.FirstBitSet(d)
|
||||||
x := math.Pow(2, float64(firstBit))
|
x := gmath.Pow(2, float64(firstBit))
|
||||||
x /= float64(e.size())
|
x /= float64(e.size())
|
||||||
x /= float64(e.TTL + diff)
|
x /= float64(e.TTL + diff)
|
||||||
e.pow = x
|
e.pow = x
|
||||||
@ -150,8 +152,8 @@ func (e *Envelope) powToFirstBit(pow float64) int {
|
|||||||
x := pow
|
x := pow
|
||||||
x *= float64(e.size())
|
x *= float64(e.size())
|
||||||
x *= float64(e.TTL)
|
x *= float64(e.TTL)
|
||||||
bits := math.Log2(x)
|
bits := gmath.Log2(x)
|
||||||
bits = math.Ceil(bits)
|
bits = gmath.Ceil(bits)
|
||||||
return int(bits)
|
return int(bits)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user