Merge pull request #4 from ethereum/master

Take latest changes from go-ethereum
This commit is contained in:
ledgerwatch 2018-01-04 14:41:41 +00:00 committed by GitHub
commit 50ad80e946
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
140 changed files with 2035 additions and 1039 deletions

View file

@ -87,13 +87,13 @@ matrix:
- sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-arm-linux-gnueabihf libc6-dev-armhf-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross - sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-arm-linux-gnueabihf libc6-dev-armhf-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross
- sudo ln -s /usr/include/asm-generic /usr/include/asm - sudo ln -s /usr/include/asm-generic /usr/include/asm
- GOARM=5 CC=arm-linux-gnueabi-gcc go run build/ci.go install -arch arm - GOARM=5 go run build/ci.go install -arch arm -cc arm-linux-gnueabi-gcc
- GOARM=5 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds - GOARM=5 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
- GOARM=6 CC=arm-linux-gnueabi-gcc go run build/ci.go install -arch arm - GOARM=6 go run build/ci.go install -arch arm -cc arm-linux-gnueabi-gcc
- GOARM=6 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds - GOARM=6 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
- GOARM=7 CC=arm-linux-gnueabihf-gcc go run build/ci.go install -arch arm - GOARM=7 go run build/ci.go install -arch arm -cc arm-linux-gnueabihf-gcc
- GOARM=7 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds - GOARM=7 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
- CC=aarch64-linux-gnu-gcc go run build/ci.go install -arch arm64 - go run build/ci.go install -arch arm64 -cc aarch64-linux-gnu-gcc
- go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds - go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
# This builder does the Linux Azure MIPS xgo uploads # This builder does the Linux Azure MIPS xgo uploads

View file

@ -96,6 +96,20 @@ func (arguments Arguments) unpackTuple(v interface{}, output []byte) error {
if err := requireUnpackKind(value, typ, kind, arguments); err != nil { if err := requireUnpackKind(value, typ, kind, arguments); err != nil {
return err return err
} }
// If the output interface is a struct, make sure names don't collide
if kind == reflect.Struct {
exists := make(map[string]bool)
for _, arg := range arguments {
field := capitalise(arg.Name)
if field == "" {
return fmt.Errorf("abi: purely underscored output cannot unpack to struct")
}
if exists[field] {
return fmt.Errorf("abi: multiple outputs mapping to the same struct field '%s'", field)
}
exists[field] = true
}
}
// `i` counts the nonindexed arguments. // `i` counts the nonindexed arguments.
// `j` counts the number of complex types. // `j` counts the number of complex types.
// both `i` and `j` are used to to correctly compute `data` offset. // both `i` and `j` are used to to correctly compute `data` offset.
@ -123,10 +137,10 @@ func (arguments Arguments) unpackTuple(v interface{}, output []byte) error {
switch kind { switch kind {
case reflect.Struct: case reflect.Struct:
name := capitalise(arg.Name)
for j := 0; j < typ.NumField(); j++ { for j := 0; j < typ.NumField(); j++ {
field := typ.Field(j)
// TODO read tags: `abi:"fieldName"` // TODO read tags: `abi:"fieldName"`
if field.Name == strings.ToUpper(arg.Name[:1])+arg.Name[1:] { if typ.Field(j).Name == name {
if err := set(value.Field(j), reflectValue, arg); err != nil { if err := set(value.Field(j), reflectValue, arg); err != nil {
return err return err
} }
@ -188,7 +202,7 @@ func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
inputOffset := 0 inputOffset := 0
for _, abiArg := range abiArgs { for _, abiArg := range abiArgs {
if abiArg.Type.T == ArrayTy { if abiArg.Type.T == ArrayTy {
inputOffset += (32 * abiArg.Type.Size) inputOffset += 32 * abiArg.Type.Size
} else { } else {
inputOffset += 32 inputOffset += 32
} }
@ -222,3 +236,15 @@ func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
return ret, nil return ret, nil
} }
// capitalise makes the first character of a string upper case, also removing any
// prefixing underscores from the variable names.
func capitalise(input string) string {
for len(input) > 0 && input[0] == '_' {
input = input[1:]
}
if len(input) == 0 {
return ""
}
return strings.ToUpper(input[:1]) + input[1:]
}

View file

@ -85,7 +85,7 @@ type ContractTransactor interface {
// There is no guarantee that this is the true gas limit requirement as other // There is no guarantee that this is the true gas limit requirement as other
// transactions may be added or removed by miners, but it should provide a basis // transactions may be added or removed by miners, but it should provide a basis
// for setting a reasonable default. // for setting a reasonable default.
EstimateGas(ctx context.Context, call ethereum.CallMsg) (usedGas *big.Int, err error) EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error)
// SendTransaction injects the transaction into the pending pool for execution. // SendTransaction injects the transaction into the pending pool for execution.
SendTransaction(ctx context.Context, tx *types.Transaction) error SendTransaction(ctx context.Context, tx *types.Transaction) error
} }

View file

@ -200,7 +200,7 @@ func (b *SimulatedBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error
// EstimateGas executes the requested code against the currently pending block/state and // EstimateGas executes the requested code against the currently pending block/state and
// returns the used amount of gas. // returns the used amount of gas.
func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (*big.Int, error) { func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) {
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
@ -210,16 +210,16 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
hi uint64 hi uint64
cap uint64 cap uint64
) )
if call.Gas != nil && call.Gas.Uint64() >= params.TxGas { if call.Gas >= params.TxGas {
hi = call.Gas.Uint64() hi = call.Gas
} else { } else {
hi = b.pendingBlock.GasLimit().Uint64() hi = b.pendingBlock.GasLimit()
} }
cap = hi cap = hi
// Create a helper to check if a gas allowance results in an executable transaction // Create a helper to check if a gas allowance results in an executable transaction
executable := func(gas uint64) bool { executable := func(gas uint64) bool {
call.Gas = new(big.Int).SetUint64(gas) call.Gas = gas
snapshot := b.pendingState.Snapshot() snapshot := b.pendingState.Snapshot()
_, _, failed, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState) _, _, failed, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState)
@ -242,21 +242,21 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
// Reject the transaction as invalid if it still fails at the highest allowance // Reject the transaction as invalid if it still fails at the highest allowance
if hi == cap { if hi == cap {
if !executable(hi) { if !executable(hi) {
return nil, errGasEstimationFailed return 0, errGasEstimationFailed
} }
} }
return new(big.Int).SetUint64(hi), nil return hi, nil
} }
// callContract implemens common code between normal and pending contract calls. // callContract implemens common code between normal and pending contract calls.
// state is modified during execution, make sure to copy it if necessary. // state is modified during execution, make sure to copy it if necessary.
func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Block, statedb *state.StateDB) ([]byte, *big.Int, bool, error) { func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Block, statedb *state.StateDB) ([]byte, uint64, bool, error) {
// Ensure message is initialized properly. // Ensure message is initialized properly.
if call.GasPrice == nil { if call.GasPrice == nil {
call.GasPrice = big.NewInt(1) call.GasPrice = big.NewInt(1)
} }
if call.Gas == nil || call.Gas.Sign() == 0 { if call.Gas == 0 {
call.Gas = big.NewInt(50000000) call.Gas = 50000000
} }
if call.Value == nil { if call.Value == nil {
call.Value = new(big.Int) call.Value = new(big.Int)
@ -271,9 +271,9 @@ 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, b.config, vm.Config{}) vmenv := vm.NewEVM(evmContext, statedb, b.config, vm.Config{})
gaspool := new(core.GasPool).AddGas(math.MaxBig256) gaspool := new(core.GasPool).AddGas(math.MaxUint64)
ret, gasUsed, _, failed, err := core.NewStateTransition(vmenv, msg, gaspool).TransitionDb()
return ret, gasUsed, failed, err return core.NewStateTransition(vmenv, msg, gaspool).TransitionDb()
} }
// SendTransaction updates the pending block to include the given transaction. // SendTransaction updates the pending block to include the given transaction.
@ -328,6 +328,6 @@ func (m callmsg) Nonce() uint64 { return 0 }
func (m callmsg) CheckNonce() bool { return false } func (m callmsg) CheckNonce() bool { return false }
func (m callmsg) To() *common.Address { return m.CallMsg.To } func (m callmsg) To() *common.Address { return m.CallMsg.To }
func (m callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice } func (m callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
func (m callmsg) Gas() *big.Int { return m.CallMsg.Gas } func (m callmsg) Gas() uint64 { return m.CallMsg.Gas }
func (m callmsg) Value() *big.Int { return m.CallMsg.Value } func (m callmsg) Value() *big.Int { return m.CallMsg.Value }
func (m callmsg) Data() []byte { return m.CallMsg.Data } func (m callmsg) Data() []byte { return m.CallMsg.Data }

View file

@ -50,7 +50,7 @@ type TransactOpts struct {
Value *big.Int // Funds to transfer along along the transaction (nil = 0 = no funds) Value *big.Int // Funds to transfer along along the transaction (nil = 0 = no funds)
GasPrice *big.Int // Gas price to use for the transaction execution (nil = gas price oracle) GasPrice *big.Int // Gas price to use for the transaction execution (nil = gas price oracle)
GasLimit *big.Int // Gas limit to set for the transaction execution (nil = estimate + 10%) GasLimit uint64 // Gas limit to set for the transaction execution (0 = estimate)
Context context.Context // Network context to support cancellation and timeouts (nil = no timeout) Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
} }
@ -189,7 +189,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
} }
} }
gasLimit := opts.GasLimit gasLimit := opts.GasLimit
if gasLimit == nil { if gasLimit == 0 {
// Gas estimation cannot succeed without code for method invocations // Gas estimation cannot succeed without code for method invocations
if contract != nil { if contract != nil {
if code, err := c.transactor.PendingCodeAt(ensureContext(opts.Context), c.address); err != nil { if code, err := c.transactor.PendingCodeAt(ensureContext(opts.Context), c.address); err != nil {

View file

@ -304,8 +304,15 @@ var methodNormalizer = map[Lang]func(string) string{
LangJava: decapitalise, LangJava: decapitalise,
} }
// capitalise makes the first character of a string upper case. // capitalise makes the first character of a string upper case, also removing any
// prefixing underscores from the variable names.
func capitalise(input string) string { func capitalise(input string) string {
for len(input) > 0 && input[0] == '_' {
input = input[1:]
}
if len(input) == 0 {
return ""
}
return strings.ToUpper(input[:1]) + input[1:] return strings.ToUpper(input[:1]) + input[1:]
} }
@ -315,15 +322,24 @@ func decapitalise(input string) string {
} }
// structured checks whether a method has enough information to return a proper // structured checks whether a method has enough information to return a proper
// Go struct ot if flat returns are needed. // Go struct or if flat returns are needed.
func structured(method abi.Method) bool { func structured(method abi.Method) bool {
if len(method.Outputs) < 2 { if len(method.Outputs) < 2 {
return false return false
} }
exists := make(map[string]bool)
for _, out := range method.Outputs { for _, out := range method.Outputs {
// If the name is anonymous, we can't organize into a struct
if out.Name == "" { if out.Name == "" {
return false return false
} }
// If the field name is empty when normalized or collides (var, Var, _var, _Var),
// we can't organize into a struct
field := capitalise(out.Name)
if field == "" || exists[field] {
return false
}
exists[field] = true
} }
return true return true
} }

View file

@ -126,6 +126,7 @@ var bindTests = []struct {
{"type":"function","name":"namedOutput","constant":true,"inputs":[],"outputs":[{"name":"str","type":"string"}]}, {"type":"function","name":"namedOutput","constant":true,"inputs":[],"outputs":[{"name":"str","type":"string"}]},
{"type":"function","name":"anonOutput","constant":true,"inputs":[],"outputs":[{"name":"","type":"string"}]}, {"type":"function","name":"anonOutput","constant":true,"inputs":[],"outputs":[{"name":"","type":"string"}]},
{"type":"function","name":"namedOutputs","constant":true,"inputs":[],"outputs":[{"name":"str1","type":"string"},{"name":"str2","type":"string"}]}, {"type":"function","name":"namedOutputs","constant":true,"inputs":[],"outputs":[{"name":"str1","type":"string"},{"name":"str2","type":"string"}]},
{"type":"function","name":"collidingOutputs","constant":true,"inputs":[],"outputs":[{"name":"str","type":"string"},{"name":"Str","type":"string"}]},
{"type":"function","name":"anonOutputs","constant":true,"inputs":[],"outputs":[{"name":"","type":"string"},{"name":"","type":"string"}]}, {"type":"function","name":"anonOutputs","constant":true,"inputs":[],"outputs":[{"name":"","type":"string"},{"name":"","type":"string"}]},
{"type":"function","name":"mixedOutputs","constant":true,"inputs":[],"outputs":[{"name":"","type":"string"},{"name":"str","type":"string"}]} {"type":"function","name":"mixedOutputs","constant":true,"inputs":[],"outputs":[{"name":"","type":"string"},{"name":"str","type":"string"}]}
] ]
@ -140,6 +141,7 @@ var bindTests = []struct {
str1, err = b.NamedOutput(nil) str1, err = b.NamedOutput(nil)
str1, err = b.AnonOutput(nil) str1, err = b.AnonOutput(nil)
res, _ := b.NamedOutputs(nil) res, _ := b.NamedOutputs(nil)
str1, str2, err = b.CollidingOutputs(nil)
str1, str2, err = b.AnonOutputs(nil) str1, str2, err = b.AnonOutputs(nil)
str1, str2, err = b.MixedOutputs(nil) str1, str2, err = b.MixedOutputs(nil)
@ -397,7 +399,6 @@ var bindTests = []struct {
sim.Commit() sim.Commit()
// Set the field with automatic estimation and check that it succeeds // Set the field with automatic estimation and check that it succeeds
auth.GasLimit = nil
if _, err := limiter.SetField(auth, "automatic"); err != nil { if _, err := limiter.SetField(auth, "automatic"); err != nil {
t.Fatalf("Failed to call automatically gased transaction: %v", err) t.Fatalf("Failed to call automatically gased transaction: %v", err)
} }
@ -447,6 +448,66 @@ var bindTests = []struct {
} }
`, `,
}, },
{
`Underscorer`,
`
contract Underscorer {
function UnderscoredOutput() constant returns (int _int, string _string) {
return (314, "pi");
}
function LowerLowerCollision() constant returns (int _res, int res) {
return (1, 2);
}
function LowerUpperCollision() constant returns (int _res, int Res) {
return (1, 2);
}
function UpperLowerCollision() constant returns (int _Res, int res) {
return (1, 2);
}
function UpperUpperCollision() constant returns (int _Res, int Res) {
return (1, 2);
}
function PurelyUnderscoredOutput() constant returns (int _, int res) {
return (1, 2);
}
function AllPurelyUnderscoredOutput() constant returns (int _, int __) {
return (1, 2);
}
}
`, `6060604052341561000f57600080fd5b6103498061001e6000396000f300606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806303a592131461008857806367e6633d146100b85780639df484851461014d578063af7486ab1461017d578063b564b34d146101ad578063e02ab24d146101dd578063e409ca451461020d575b600080fd5b341561009357600080fd5b61009b61023d565b604051808381526020018281526020019250505060405180910390f35b34156100c357600080fd5b6100cb610252565b6040518083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156101115780820151818401526020810190506100f6565b50505050905090810190601f16801561013e5780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b341561015857600080fd5b6101606102a0565b604051808381526020018281526020019250505060405180910390f35b341561018857600080fd5b6101906102b5565b604051808381526020018281526020019250505060405180910390f35b34156101b857600080fd5b6101c06102ca565b604051808381526020018281526020019250505060405180910390f35b34156101e857600080fd5b6101f06102df565b604051808381526020018281526020019250505060405180910390f35b341561021857600080fd5b6102206102f4565b604051808381526020018281526020019250505060405180910390f35b60008060016002819150809050915091509091565b600061025c610309565b61013a8090506040805190810160405280600281526020017f7069000000000000000000000000000000000000000000000000000000000000815250915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b6020604051908101604052806000815250905600a165627a7a72305820c11dcfa136fc7d182ee4d34f0b12d988496228f7e2d02d2b5376d996ca1743d00029`,
`[{"constant":true,"inputs":[],"name":"LowerUpperCollision","outputs":[{"name":"_res","type":"int256"},{"name":"Res","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"UnderscoredOutput","outputs":[{"name":"_int","type":"int256"},{"name":"_string","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PurelyUnderscoredOutput","outputs":[{"name":"_","type":"int256"},{"name":"res","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"UpperLowerCollision","outputs":[{"name":"_Res","type":"int256"},{"name":"res","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"AllPurelyUnderscoredOutput","outputs":[{"name":"_","type":"int256"},{"name":"__","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"UpperUpperCollision","outputs":[{"name":"_Res","type":"int256"},{"name":"Res","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"LowerLowerCollision","outputs":[{"name":"_res","type":"int256"},{"name":"res","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"}]`,
`
// Generate a new random account and a funded simulator
key, _ := crypto.GenerateKey()
auth := bind.NewKeyedTransactor(key)
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}})
// Deploy a underscorer tester contract and execute a structured call on it
_, _, underscorer, err := DeployUnderscorer(auth, sim)
if err != nil {
t.Fatalf("Failed to deploy underscorer contract: %v", err)
}
sim.Commit()
// Verify that underscored return values correctly parse into structs
if res, err := underscorer.UnderscoredOutput(nil); err != nil {
t.Errorf("Failed to call constant function: %v", err)
} else if res.Int.Cmp(big.NewInt(314)) != 0 || res.String != "pi" {
t.Errorf("Invalid result, want: {314, \"pi\"}, got: %+v", res)
}
// Verify that underscored and non-underscored name collisions force tuple outputs
var a, b *big.Int
a, b, _ = underscorer.LowerLowerCollision(nil)
a, b, _ = underscorer.LowerUpperCollision(nil)
a, b, _ = underscorer.UpperLowerCollision(nil)
a, b, _ = underscorer.UpperUpperCollision(nil)
a, b, _ = underscorer.PurelyUnderscoredOutput(nil)
a, b, _ = underscorer.AllPurelyUnderscoredOutput(nil)
fmt.Println(a, b, err)
`,
},
} }
// Tests that packages generated by the binder can be successfully compiled and // Tests that packages generated by the binder can be successfully compiled and

View file

@ -34,18 +34,18 @@ var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d
var waitDeployedTests = map[string]struct { var waitDeployedTests = map[string]struct {
code string code string
gas *big.Int gas uint64
wantAddress common.Address wantAddress common.Address
wantErr error wantErr error
}{ }{
"successful deploy": { "successful deploy": {
code: `6060604052600a8060106000396000f360606040526008565b00`, code: `6060604052600a8060106000396000f360606040526008565b00`,
gas: big.NewInt(3000000), gas: 3000000,
wantAddress: common.HexToAddress("0x3a220f351252089d385b29beca14e27f204c296a"), wantAddress: common.HexToAddress("0x3a220f351252089d385b29beca14e27f204c296a"),
}, },
"empty code": { "empty code": {
code: ``, code: ``,
gas: big.NewInt(300000), gas: 300000,
wantErr: bind.ErrNoCodeAfterDeploy, wantErr: bind.ErrNoCodeAfterDeploy,
wantAddress: common.HexToAddress("0x3a220f351252089d385b29beca14e27f204c296a"), wantAddress: common.HexToAddress("0x3a220f351252089d385b29beca14e27f204c296a"),
}, },

View file

@ -259,6 +259,51 @@ var unpackTests = []unpackTest{
enc: "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003", enc: "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003",
want: [3]*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)}, want: [3]*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)},
}, },
// struct outputs
{
def: `[{"name":"int1","type":"int256"},{"name":"int2","type":"int256"}]`,
enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
want: struct {
Int1 *big.Int
Int2 *big.Int
}{big.NewInt(1), big.NewInt(2)},
},
{
def: `[{"name":"int","type":"int256"},{"name":"Int","type":"int256"}]`,
enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
want: struct {
Int1 *big.Int
Int2 *big.Int
}{},
err: "abi: multiple outputs mapping to the same struct field 'Int'",
},
{
def: `[{"name":"int","type":"int256"},{"name":"_int","type":"int256"}]`,
enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
want: struct {
Int1 *big.Int
Int2 *big.Int
}{},
err: "abi: multiple outputs mapping to the same struct field 'Int'",
},
{
def: `[{"name":"Int","type":"int256"},{"name":"_int","type":"int256"}]`,
enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
want: struct {
Int1 *big.Int
Int2 *big.Int
}{},
err: "abi: multiple outputs mapping to the same struct field 'Int'",
},
{
def: `[{"name":"Int","type":"int256"},{"name":"_","type":"int256"}]`,
enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
want: struct {
Int1 *big.Int
Int2 *big.Int
}{},
err: "abi: purely underscored output cannot unpack to struct",
},
} }
func TestUnpack(t *testing.T) { func TestUnpack(t *testing.T) {

View file

@ -180,7 +180,7 @@ func (w *trezorDriver) trezorSign(derivationPath []uint32, tx *types.Transaction
AddressN: derivationPath, AddressN: derivationPath,
Nonce: new(big.Int).SetUint64(tx.Nonce()).Bytes(), Nonce: new(big.Int).SetUint64(tx.Nonce()).Bytes(),
GasPrice: tx.GasPrice().Bytes(), GasPrice: tx.GasPrice().Bytes(),
GasLimit: tx.Gas().Bytes(), GasLimit: new(big.Int).SetUint64(tx.Gas()).Bytes(),
Value: tx.Value().Bytes(), Value: tx.Value().Bytes(),
DataLength: &length, DataLength: &length,
} }

View file

@ -23,7 +23,7 @@ Usage: go run build/ci.go <command> <command flags/arguments>
Available commands are: Available commands are:
install [ -arch architecture ] [ packages... ] -- builds packages and executables install [ -arch architecture ] [ -cc compiler ] [ packages... ] -- builds packages and executables
test [ -coverage ] [ packages... ] -- runs the tests test [ -coverage ] [ packages... ] -- runs the tests
lint -- runs certain pre-selected linters lint -- runs certain pre-selected linters
archive [ -arch architecture ] [ -type zip|tar ] [ -signer key-envvar ] [ -upload dest ] -- archives build artefacts archive [ -arch architecture ] [ -type zip|tar ] [ -signer key-envvar ] [ -upload dest ] -- archives build artefacts
@ -173,18 +173,25 @@ func main() {
func doInstall(cmdline []string) { func doInstall(cmdline []string) {
var ( var (
arch = flag.String("arch", "", "Architecture to cross build for") arch = flag.String("arch", "", "Architecture to cross build for")
cc = flag.String("cc", "", "C compiler to cross build with")
) )
flag.CommandLine.Parse(cmdline) flag.CommandLine.Parse(cmdline)
env := build.Env() env := build.Env()
// Check Go version. People regularly open issues about compilation // Check Go version. People regularly open issues about compilation
// failure with outdated Go. This should save them the trouble. // failure with outdated Go. This should save them the trouble.
if runtime.Version() < "go1.7" && !strings.Contains(runtime.Version(), "devel") { if !strings.Contains(runtime.Version(), "devel") {
// Figure out the minor version number since we can't textually compare (1.10 < 1.7)
var minor int
fmt.Sscanf(strings.TrimPrefix(runtime.Version(), "go1."), "%d", &minor)
if minor < 7 {
log.Println("You have Go version", runtime.Version()) log.Println("You have Go version", runtime.Version())
log.Println("go-ethereum requires at least Go version 1.7 and cannot") log.Println("go-ethereum requires at least Go version 1.7 and cannot")
log.Println("be compiled with an earlier version. Please upgrade your Go installation.") log.Println("be compiled with an earlier version. Please upgrade your Go installation.")
os.Exit(1) os.Exit(1)
} }
}
// Compile packages given as arguments, or everything if there are no arguments. // Compile packages given as arguments, or everything if there are no arguments.
packages := []string{"./..."} packages := []string{"./..."}
if flag.NArg() > 0 { if flag.NArg() > 0 {
@ -207,7 +214,7 @@ func doInstall(cmdline []string) {
} }
} }
// Seems we are cross compiling, work around forbidden GOBIN // Seems we are cross compiling, work around forbidden GOBIN
goinstall := goToolArch(*arch, "install", buildFlags(env)...) goinstall := goToolArch(*arch, *cc, "install", buildFlags(env)...)
goinstall.Args = append(goinstall.Args, "-v") goinstall.Args = append(goinstall.Args, "-v")
goinstall.Args = append(goinstall.Args, []string{"-buildmode", "archive"}...) goinstall.Args = append(goinstall.Args, []string{"-buildmode", "archive"}...)
goinstall.Args = append(goinstall.Args, packages...) goinstall.Args = append(goinstall.Args, packages...)
@ -221,7 +228,7 @@ func doInstall(cmdline []string) {
} }
for name := range pkgs { for name := range pkgs {
if name == "main" { if name == "main" {
gobuild := goToolArch(*arch, "build", buildFlags(env)...) gobuild := goToolArch(*arch, *cc, "build", buildFlags(env)...)
gobuild.Args = append(gobuild.Args, "-v") gobuild.Args = append(gobuild.Args, "-v")
gobuild.Args = append(gobuild.Args, []string{"-o", executablePath(cmd.Name())}...) gobuild.Args = append(gobuild.Args, []string{"-o", executablePath(cmd.Name())}...)
gobuild.Args = append(gobuild.Args, "."+string(filepath.Separator)+filepath.Join("cmd", cmd.Name())) gobuild.Args = append(gobuild.Args, "."+string(filepath.Separator)+filepath.Join("cmd", cmd.Name()))
@ -249,15 +256,18 @@ func buildFlags(env build.Environment) (flags []string) {
} }
func goTool(subcmd string, args ...string) *exec.Cmd { func goTool(subcmd string, args ...string) *exec.Cmd {
return goToolArch(runtime.GOARCH, subcmd, args...) return goToolArch(runtime.GOARCH, os.Getenv("CC"), subcmd, args...)
} }
func goToolArch(arch string, subcmd string, args ...string) *exec.Cmd { func goToolArch(arch string, cc string, subcmd string, args ...string) *exec.Cmd {
cmd := build.GoTool(subcmd, args...) cmd := build.GoTool(subcmd, args...)
if subcmd == "build" || subcmd == "install" || subcmd == "test" { if subcmd == "build" || subcmd == "install" || subcmd == "test" {
// Go CGO has a Windows linker error prior to 1.8 (https://github.com/golang/go/issues/8756). // Go CGO has a Windows linker error prior to 1.8 (https://github.com/golang/go/issues/8756).
// Work around issue by allowing multiple definitions for <1.8 builds. // Work around issue by allowing multiple definitions for <1.8 builds.
if runtime.GOOS == "windows" && runtime.Version() < "go1.8" { var minor int
fmt.Sscanf(strings.TrimPrefix(runtime.Version(), "go1."), "%d", &minor)
if runtime.GOOS == "windows" && minor < 8 {
cmd.Args = append(cmd.Args, []string{"-ldflags", "-extldflags -Wl,--allow-multiple-definition"}...) cmd.Args = append(cmd.Args, []string{"-ldflags", "-extldflags -Wl,--allow-multiple-definition"}...)
} }
} }
@ -268,6 +278,9 @@ func goToolArch(arch string, subcmd string, args ...string) *exec.Cmd {
cmd.Env = append(cmd.Env, "CGO_ENABLED=1") cmd.Env = append(cmd.Env, "CGO_ENABLED=1")
cmd.Env = append(cmd.Env, "GOARCH="+arch) cmd.Env = append(cmd.Env, "GOARCH="+arch)
} }
if cc != "" {
cmd.Env = append(cmd.Env, "CC="+cc)
}
for _, e := range os.Environ() { for _, e := range os.Environ() {
if strings.HasPrefix(e, "GOPATH=") || strings.HasPrefix(e, "GOBIN=") { if strings.HasPrefix(e, "GOPATH=") || strings.HasPrefix(e, "GOBIN=") {
continue continue

View file

@ -473,7 +473,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
amount = new(big.Int).Mul(amount, new(big.Int).Exp(big.NewInt(5), big.NewInt(int64(msg.Tier)), nil)) amount = new(big.Int).Mul(amount, new(big.Int).Exp(big.NewInt(5), big.NewInt(int64(msg.Tier)), nil))
amount = new(big.Int).Div(amount, new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(msg.Tier)), nil)) amount = new(big.Int).Div(amount, new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(msg.Tier)), nil))
tx := types.NewTransaction(f.nonce+uint64(len(f.reqs)), address, amount, big.NewInt(21000), f.price, nil) tx := types.NewTransaction(f.nonce+uint64(len(f.reqs)), address, amount, 21000, f.price, nil)
signed, err := f.keystore.SignTx(f.account, tx, f.config.ChainId) signed, err := f.keystore.SignTx(f.account, tx, f.config.ChainId)
if err != nil { if err != nil {
f.lock.Unlock() f.lock.Unlock()

View file

@ -134,7 +134,6 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with geth. If not, see <http://www.gnu.org/licenses/>. along with geth. If not, see <http://www.gnu.org/licenses/>.`)
`)
return nil return nil
} }

View file

@ -44,7 +44,7 @@ type cppEthereumGenesisSpec struct {
MaximumExtraDataSize hexutil.Uint64 `json:"maximumExtraDataSize"` MaximumExtraDataSize hexutil.Uint64 `json:"maximumExtraDataSize"`
MinGasLimit hexutil.Uint64 `json:"minGasLimit"` MinGasLimit hexutil.Uint64 `json:"minGasLimit"`
MaxGasLimit hexutil.Uint64 `json:"maxGasLimit"` MaxGasLimit hexutil.Uint64 `json:"maxGasLimit"`
GasLimitBoundDivisor *hexutil.Big `json:"gasLimitBoundDivisor"` GasLimitBoundDivisor hexutil.Uint64 `json:"gasLimitBoundDivisor"`
MinimumDifficulty *hexutil.Big `json:"minimumDifficulty"` MinimumDifficulty *hexutil.Big `json:"minimumDifficulty"`
DifficultyBoundDivisor *hexutil.Big `json:"difficultyBoundDivisor"` DifficultyBoundDivisor *hexutil.Big `json:"difficultyBoundDivisor"`
DurationLimit *hexutil.Big `json:"durationLimit"` DurationLimit *hexutil.Big `json:"durationLimit"`
@ -107,11 +107,11 @@ func newCppEthereumGenesisSpec(network string, genesis *core.Genesis) (*cppEther
spec.Params.ChainID = (hexutil.Uint64)(genesis.Config.ChainId.Uint64()) spec.Params.ChainID = (hexutil.Uint64)(genesis.Config.ChainId.Uint64())
spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize) spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize)
spec.Params.MinGasLimit = (hexutil.Uint64)(params.MinGasLimit.Uint64()) spec.Params.MinGasLimit = (hexutil.Uint64)(params.MinGasLimit)
spec.Params.MaxGasLimit = (hexutil.Uint64)(math.MaxUint64) spec.Params.MaxGasLimit = (hexutil.Uint64)(math.MaxUint64)
spec.Params.MinimumDifficulty = (*hexutil.Big)(params.MinimumDifficulty) spec.Params.MinimumDifficulty = (*hexutil.Big)(params.MinimumDifficulty)
spec.Params.DifficultyBoundDivisor = (*hexutil.Big)(params.DifficultyBoundDivisor) spec.Params.DifficultyBoundDivisor = (*hexutil.Big)(params.DifficultyBoundDivisor)
spec.Params.GasLimitBoundDivisor = (*hexutil.Big)(params.GasLimitBoundDivisor) spec.Params.GasLimitBoundDivisor = (hexutil.Uint64)(params.GasLimitBoundDivisor)
spec.Params.DurationLimit = (*hexutil.Big)(params.DurationLimit) spec.Params.DurationLimit = (*hexutil.Big)(params.DurationLimit)
spec.Params.BlockReward = (*hexutil.Big)(ethash.FrontierBlockReward) spec.Params.BlockReward = (*hexutil.Big)(ethash.FrontierBlockReward)
@ -170,7 +170,7 @@ type parityChainSpec struct {
Params struct { Params struct {
MinimumDifficulty *hexutil.Big `json:"minimumDifficulty"` MinimumDifficulty *hexutil.Big `json:"minimumDifficulty"`
DifficultyBoundDivisor *hexutil.Big `json:"difficultyBoundDivisor"` DifficultyBoundDivisor *hexutil.Big `json:"difficultyBoundDivisor"`
GasLimitBoundDivisor *hexutil.Big `json:"gasLimitBoundDivisor"` GasLimitBoundDivisor hexutil.Uint64 `json:"gasLimitBoundDivisor"`
DurationLimit *hexutil.Big `json:"durationLimit"` DurationLimit *hexutil.Big `json:"durationLimit"`
BlockReward *hexutil.Big `json:"blockReward"` BlockReward *hexutil.Big `json:"blockReward"`
HomesteadTransition uint64 `json:"homesteadTransition"` HomesteadTransition uint64 `json:"homesteadTransition"`
@ -187,7 +187,7 @@ type parityChainSpec struct {
Params struct { Params struct {
MaximumExtraDataSize hexutil.Uint64 `json:"maximumExtraDataSize"` MaximumExtraDataSize hexutil.Uint64 `json:"maximumExtraDataSize"`
MinGasLimit *hexutil.Big `json:"minGasLimit"` MinGasLimit hexutil.Uint64 `json:"minGasLimit"`
NetworkID hexutil.Uint64 `json:"networkID"` NetworkID hexutil.Uint64 `json:"networkID"`
MaxCodeSize uint64 `json:"maxCodeSize"` MaxCodeSize uint64 `json:"maxCodeSize"`
EIP155Transition uint64 `json:"eip155Transition"` EIP155Transition uint64 `json:"eip155Transition"`
@ -270,7 +270,7 @@ func newParityChainSpec(network string, genesis *core.Genesis, bootnodes []strin
} }
spec.Engine.Ethash.Params.MinimumDifficulty = (*hexutil.Big)(params.MinimumDifficulty) spec.Engine.Ethash.Params.MinimumDifficulty = (*hexutil.Big)(params.MinimumDifficulty)
spec.Engine.Ethash.Params.DifficultyBoundDivisor = (*hexutil.Big)(params.DifficultyBoundDivisor) spec.Engine.Ethash.Params.DifficultyBoundDivisor = (*hexutil.Big)(params.DifficultyBoundDivisor)
spec.Engine.Ethash.Params.GasLimitBoundDivisor = (*hexutil.Big)(params.GasLimitBoundDivisor) spec.Engine.Ethash.Params.GasLimitBoundDivisor = (hexutil.Uint64)(params.GasLimitBoundDivisor)
spec.Engine.Ethash.Params.DurationLimit = (*hexutil.Big)(params.DurationLimit) spec.Engine.Ethash.Params.DurationLimit = (*hexutil.Big)(params.DurationLimit)
spec.Engine.Ethash.Params.BlockReward = (*hexutil.Big)(ethash.FrontierBlockReward) spec.Engine.Ethash.Params.BlockReward = (*hexutil.Big)(ethash.FrontierBlockReward)
spec.Engine.Ethash.Params.HomesteadTransition = genesis.Config.HomesteadBlock.Uint64() spec.Engine.Ethash.Params.HomesteadTransition = genesis.Config.HomesteadBlock.Uint64()
@ -283,7 +283,7 @@ func newParityChainSpec(network string, genesis *core.Genesis, bootnodes []strin
spec.Engine.Ethash.Params.EIP649Transition = genesis.Config.ByzantiumBlock.Uint64() spec.Engine.Ethash.Params.EIP649Transition = genesis.Config.ByzantiumBlock.Uint64()
spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize) spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize)
spec.Params.MinGasLimit = (*hexutil.Big)(params.MinGasLimit) spec.Params.MinGasLimit = (hexutil.Uint64)(params.MinGasLimit)
spec.Params.NetworkID = (hexutil.Uint64)(genesis.Config.ChainId.Uint64()) spec.Params.NetworkID = (hexutil.Uint64)(genesis.Config.ChainId.Uint64())
spec.Params.MaxCodeSize = params.MaxCodeSize spec.Params.MaxCodeSize = params.MaxCodeSize
spec.Params.EIP155Transition = genesis.Config.EIP155Block.Uint64() spec.Params.EIP155Transition = genesis.Config.EIP155Block.Uint64()

View file

@ -315,7 +315,7 @@ func checkDeprecated(ctx *cli.Context) {
func printConfig(config *bzzapi.Config) string { func printConfig(config *bzzapi.Config) string {
out, err := tomlSettings.Marshal(&config) out, err := tomlSettings.Marshal(&config)
if err != nil { if err != nil {
return (fmt.Sprintf("Something is not right with the configuration: %v", err)) return fmt.Sprintf("Something is not right with the configuration: %v", err)
} }
return string(out) return string(out)
} }

View file

@ -96,7 +96,7 @@ func NewApp(gitCommit, usage string) *cli.App {
//app.Authors = nil //app.Authors = nil
app.Email = "" app.Email = ""
app.Version = params.Version app.Version = params.Version
if gitCommit != "" { if len(gitCommit) >= 8 {
app.Version += "-" + gitCommit[:8] app.Version += "-" + gitCommit[:8]
} }
app.Usage = usage app.Usage = usage
@ -313,7 +313,7 @@ var (
TargetGasLimitFlag = cli.Uint64Flag{ 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.Uint64(), Value: params.GenesisGasLimit,
} }
EtherbaseFlag = cli.StringFlag{ EtherbaseFlag = cli.StringFlag{
Name: "etherbase", Name: "etherbase",
@ -1138,7 +1138,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) {
// TODO(fjl): move target gas limit into config // TODO(fjl): move target gas limit into config
params.TargetGasLimit = new(big.Int).SetUint64(ctx.GlobalUint64(TargetGasLimitFlag.Name)) params.TargetGasLimit = ctx.GlobalUint64(TargetGasLimitFlag.Name)
} }
// MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails. // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.

View file

@ -40,7 +40,7 @@ func fastXORBytes(dst, a, b []byte) int {
dw[i] = aw[i] ^ bw[i] dw[i] = aw[i] ^ bw[i]
} }
} }
for i := (n - n%wordSize); i < n; i++ { for i := n - n%wordSize; i < n; i++ {
dst[i] = a[i] ^ b[i] dst[i] = a[i] ^ b[i]
} }
return n return n
@ -84,7 +84,7 @@ func fastANDBytes(dst, a, b []byte) int {
dw[i] = aw[i] & bw[i] dw[i] = aw[i] & bw[i]
} }
} }
for i := (n - n%wordSize); i < n; i++ { for i := n - n%wordSize; i < n; i++ {
dst[i] = a[i] & b[i] dst[i] = a[i] & b[i]
} }
return n return n
@ -128,7 +128,7 @@ func fastORBytes(dst, a, b []byte) int {
dw[i] = aw[i] | bw[i] dw[i] = aw[i] | bw[i]
} }
} }
for i := (n - n%wordSize); i < n; i++ { for i := n - n%wordSize; i < n; i++ {
dst[i] = a[i] | b[i] dst[i] = a[i] | b[i]
} }
return n return n
@ -168,7 +168,7 @@ func fastTestBytes(p []byte) bool {
} }
} }
} }
for i := (n - n%wordSize); i < n; i++ { for i := n - n%wordSize; i < n; i++ {
if p[i] != 0 { if p[i] != 0 {
return true return true
} }

View file

@ -688,8 +688,8 @@ func TestConcurrentDiskCacheGeneration(t *testing.T) {
TxHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), TxHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"),
ReceiptHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), ReceiptHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"),
Difficulty: big.NewInt(167925187834220), Difficulty: big.NewInt(167925187834220),
GasLimit: big.NewInt(4015682), GasLimit: 4015682,
GasUsed: big.NewInt(0), GasUsed: 0,
Time: big.NewInt(1488928920), Time: big.NewInt(1488928920),
Extra: []byte("www.bw.com"), Extra: []byte("www.bw.com"),
MixDigest: common.HexToHash("0x3e140b0784516af5e5ec6730f2fb20cca22f32be399b9e4ad77d32541f798cd0"), MixDigest: common.HexToHash("0x3e140b0784516af5e5ec6730f2fb20cca22f32be399b9e4ad77d32541f798cd0"),

View file

@ -246,24 +246,24 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent *
return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, expected) return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, expected)
} }
// Verify that the gas limit is <= 2^63-1 // Verify that the gas limit is <= 2^63-1
if header.GasLimit.Cmp(math.MaxBig63) > 0 { cap := uint64(0x7fffffffffffffff)
return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, math.MaxBig63) if header.GasLimit > cap {
return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap)
} }
// Verify that the gasUsed is <= gasLimit // Verify that the gasUsed is <= gasLimit
if header.GasUsed.Cmp(header.GasLimit) > 0 { if header.GasUsed > header.GasLimit {
return fmt.Errorf("invalid gasUsed: have %v, gasLimit %v", header.GasUsed, header.GasLimit) return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
} }
// Verify that the gas limit remains within allowed bounds // Verify that the gas limit remains within allowed bounds
diff := new(big.Int).Set(parent.GasLimit) diff := int64(parent.GasLimit) - int64(header.GasLimit)
diff = diff.Sub(diff, header.GasLimit) if diff < 0 {
diff.Abs(diff) diff *= -1
}
limit := parent.GasLimit / params.GasLimitBoundDivisor
limit := new(big.Int).Set(parent.GasLimit) if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit {
limit = limit.Div(limit, params.GasLimitBoundDivisor) return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit)
if diff.Cmp(limit) >= 0 || header.GasLimit.Cmp(params.MinGasLimit) < 0 {
return fmt.Errorf("invalid gas limit: have %v, want %v += %v", header.GasLimit, parent.GasLimit, limit)
} }
// Verify that the block number is parent's +1 // Verify that the block number is parent's +1
if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 { if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 {
@ -381,7 +381,7 @@ func calcDifficultyByzantium(time uint64, parent *types.Header) *big.Int {
// the difficulty that a new block should have when created at time given the // the difficulty that a new block should have when created at time given the
// parent block's time and difficulty. The calculation uses the Homestead rules. // parent block's time and difficulty. The calculation uses the Homestead rules.
func calcDifficultyHomestead(time uint64, parent *types.Header) *big.Int { func calcDifficultyHomestead(time uint64, parent *types.Header) *big.Int {
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.mediawiki // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md
// algorithm: // algorithm:
// diff = (parent_diff + // diff = (parent_diff +
// (parent_diff / 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99)) // (parent_diff / 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99))

View file

@ -155,8 +155,7 @@ func (p *terminalPrompter) SetHistory(history []string) {
p.State.ReadHistory(strings.NewReader(strings.Join(history, "\n"))) p.State.ReadHistory(strings.NewReader(strings.Join(history, "\n")))
} }
// AppendHistory appends an entry to the scrollback history. It should be called // AppendHistory appends an entry to the scrollback history.
// if and only if the prompt to append was a valid command.
func (p *terminalPrompter) AppendHistory(command string) { func (p *terminalPrompter) AppendHistory(command string) {
p.State.AppendHistory(command) p.State.AppendHistory(command)
} }

View file

@ -1,4 +1,4 @@
FROM alpine:3.5 FROM alpine:3.7
RUN \ RUN \
apk add --update go git make gcc musl-dev linux-headers ca-certificates && \ apk add --update go git make gcc musl-dev linux-headers ca-certificates && \

View file

@ -1,12 +1,14 @@
FROM ubuntu:xenial FROM ubuntu:xenial
ENV PATH=/usr/lib/go-1.9/bin:$PATH
RUN \ RUN \
apt-get update && apt-get upgrade -q -y && \ apt-get update && apt-get upgrade -q -y && \
apt-get install -y --no-install-recommends golang git make gcc libc-dev ca-certificates && \ apt-get install -y --no-install-recommends golang-1.9 git make gcc libc-dev ca-certificates && \
git clone --depth 1 https://github.com/ethereum/go-ethereum && \ git clone --depth 1 https://github.com/ethereum/go-ethereum && \
(cd go-ethereum && make geth) && \ (cd go-ethereum && make geth) && \
cp go-ethereum/build/bin/geth /geth && \ cp go-ethereum/build/bin/geth /geth && \
apt-get remove -y golang git make gcc libc-dev && apt autoremove -y && apt-get clean && \ apt-get remove -y golang-1.9 git make gcc libc-dev && apt autoremove -y && apt-get clean && \
rm -rf /go-ethereum rm -rf /go-ethereum
EXPOSE 8545 EXPOSE 8545

View file

@ -1,4 +1,4 @@
FROM alpine:3.5 FROM alpine:3.7
RUN \ RUN \
apk add --update go git make gcc musl-dev linux-headers ca-certificates && \ apk add --update go git make gcc musl-dev linux-headers ca-certificates && \

View file

@ -1,12 +1,14 @@
FROM ubuntu:xenial FROM ubuntu:xenial
ENV PATH=/usr/lib/go-1.9/bin:$PATH
RUN \ RUN \
apt-get update && apt-get upgrade -q -y && \ apt-get update && apt-get upgrade -q -y && \
apt-get install -y --no-install-recommends golang git make gcc libc-dev ca-certificates && \ apt-get install -y --no-install-recommends golang-1.9 git make gcc libc-dev ca-certificates && \
git clone --depth 1 --branch release/1.7 https://github.com/ethereum/go-ethereum && \ git clone --depth 1 --branch release/1.7 https://github.com/ethereum/go-ethereum && \
(cd go-ethereum && make geth) && \ (cd go-ethereum && make geth) && \
cp go-ethereum/build/bin/geth /geth && \ cp go-ethereum/build/bin/geth /geth && \
apt-get remove -y golang git make gcc libc-dev && apt autoremove -y && apt-get clean && \ apt-get remove -y golang-1.9 git make gcc libc-dev && apt autoremove -y && apt-get clean && \
rm -rf /go-ethereum rm -rf /go-ethereum
EXPOSE 8545 EXPOSE 8545

View file

@ -56,8 +56,8 @@ import (
// * watching incoming ether // * watching incoming ether
var ( var (
gasToCash = big.NewInt(2000000) // gas cost of a cash transaction using chequebook gasToCash = uint64(2000000) // gas cost of a cash transaction using chequebook
// gasToDeploy = big.NewInt(3000000) // gasToDeploy = uint64(3000000)
) )
// Backend wraps all methods required for chequebook operation. // Backend wraps all methods required for chequebook operation.

View file

@ -19,7 +19,6 @@ package ens
//go:generate abigen --sol contract/ens.sol --pkg contract --out contract/ens.go //go:generate abigen --sol contract/ens.sol --pkg contract --out contract/ens.go
import ( import (
"math/big"
"strings" "strings"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
@ -163,7 +162,7 @@ func (self *ENS) Register(name string) (*types.Transaction, error) {
} }
opts := self.TransactOpts opts := self.TransactOpts
opts.GasLimit = big.NewInt(200000) opts.GasLimit = 200000
return registrar.Contract.Register(&opts, label, self.TransactOpts.From) return registrar.Contract.Register(&opts, label, self.TransactOpts.From)
} }
@ -178,6 +177,6 @@ func (self *ENS) SetContentHash(name string, hash common.Hash) (*types.Transacti
} }
opts := self.TransactOpts opts := self.TransactOpts
opts.GasLimit = big.NewInt(200000) opts.GasLimit = 200000
return resolver.Contract.SetContent(&opts, node, hash) return resolver.Contract.SetContent(&opts, node, hash)
} }

View file

@ -37,7 +37,7 @@ func TestENS(t *testing.T) {
contractBackend := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}}) contractBackend := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}})
transactOpts := bind.NewKeyedTransactor(key) transactOpts := bind.NewKeyedTransactor(key)
// Workaround for bug estimating gas in the call to Register // Workaround for bug estimating gas in the call to Register
transactOpts.GasLimit = big.NewInt(1000000) transactOpts.GasLimit = 1000000
ens, err := DeployENS(transactOpts, contractBackend) ens, err := DeployENS(transactOpts, contractBackend)
if err != nil { if err != nil {

View file

@ -84,7 +84,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
return func(i int, gen *BlockGen) { return func(i int, gen *BlockGen) {
toaddr := common.Address{} toaddr := common.Address{}
data := make([]byte, nbytes) data := make([]byte, nbytes)
gas := IntrinsicGas(data, false, false) gas, _ := IntrinsicGas(data, false, false)
tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(benchRootAddr), toaddr, big.NewInt(1), gas, nil, data), types.HomesteadSigner{}, benchRootKey) tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(benchRootAddr), toaddr, big.NewInt(1), gas, nil, data), types.HomesteadSigner{}, benchRootKey)
gen.AddTx(tx) gen.AddTx(tx)
} }
@ -93,7 +93,6 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
var ( var (
ringKeys = make([]*ecdsa.PrivateKey, 1000) ringKeys = make([]*ecdsa.PrivateKey, 1000)
ringAddrs = make([]common.Address, len(ringKeys)) ringAddrs = make([]common.Address, len(ringKeys))
bigTxGas = new(big.Int).SetUint64(params.TxGas)
) )
func init() { func init() {
@ -113,8 +112,8 @@ func genTxRing(naccounts int) func(int, *BlockGen) {
return func(i int, gen *BlockGen) { return func(i int, gen *BlockGen) {
gas := CalcGasLimit(gen.PrevBlock(i - 1)) gas := CalcGasLimit(gen.PrevBlock(i - 1))
for { for {
gas.Sub(gas, bigTxGas) gas -= params.TxGas
if gas.Cmp(bigTxGas) < 0 { if gas < params.TxGas {
break break
} }
to := (from + 1) % naccounts to := (from + 1) % naccounts
@ -122,7 +121,7 @@ func genTxRing(naccounts int) func(int, *BlockGen) {
gen.TxNonce(ringAddrs[from]), gen.TxNonce(ringAddrs[from]),
ringAddrs[to], ringAddrs[to],
benchRootFunds, benchRootFunds,
bigTxGas, params.TxGas,
nil, nil,
nil, nil,
) )

View file

@ -18,9 +18,7 @@ package core
import ( import (
"fmt" "fmt"
"math/big"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus"
"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"
@ -76,10 +74,10 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
// transition, such as amount of used gas, the receipt roots and the state root // transition, such as amount of used gas, the receipt roots and the state root
// itself. ValidateState returns a database batch if the validation was a success // itself. ValidateState returns a database batch if the validation was a success
// otherwise nil and an error is returned. // otherwise nil and an error is returned.
func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas *big.Int) error { func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error {
header := block.Header() header := block.Header()
if block.GasUsed().Cmp(usedGas) != 0 { if block.GasUsed() != usedGas {
return fmt.Errorf("invalid gas used (remote: %v local: %v)", block.GasUsed(), usedGas) return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas)
} }
// Validate the received block's bloom with the one derived from the generated receipts. // Validate the received block's bloom with the one derived from the generated receipts.
// For valid blocks this should always validate to true. // For valid blocks this should always validate to true.
@ -101,17 +99,13 @@ func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *stat
} }
// CalcGasLimit computes the gas limit of the next block after parent. // CalcGasLimit computes the gas limit of the next block after parent.
// The result may be modified by the caller.
// This is miner strategy, not consensus protocol. // This is miner strategy, not consensus protocol.
func CalcGasLimit(parent *types.Block) *big.Int { func CalcGasLimit(parent *types.Block) uint64 {
// contrib = (parentGasUsed * 3 / 2) / 1024 // contrib = (parentGasUsed * 3 / 2) / 1024
contrib := new(big.Int).Mul(parent.GasUsed(), big.NewInt(3)) contrib := (parent.GasUsed() + parent.GasUsed()/2) / params.GasLimitBoundDivisor
contrib = contrib.Div(contrib, big.NewInt(2))
contrib = contrib.Div(contrib, params.GasLimitBoundDivisor)
// decay = parentGasLimit / 1024 -1 // decay = parentGasLimit / 1024 -1
decay := new(big.Int).Div(parent.GasLimit(), params.GasLimitBoundDivisor) decay := parent.GasLimit()/params.GasLimitBoundDivisor - 1
decay.Sub(decay, big.NewInt(1))
/* /*
strategy: gasLimit of block-to-mine is set based on parent's strategy: gasLimit of block-to-mine is set based on parent's
@ -120,15 +114,17 @@ func CalcGasLimit(parent *types.Block) *big.Int {
at that usage) the amount increased/decreased depends on how far away at that usage) the amount increased/decreased depends on how far away
from parentGasLimit * (2/3) parentGasUsed is. from parentGasLimit * (2/3) parentGasUsed is.
*/ */
gl := new(big.Int).Sub(parent.GasLimit(), decay) limit := parent.GasLimit() - decay + contrib
gl = gl.Add(gl, contrib) if limit < params.MinGasLimit {
gl.Set(math.BigMax(gl, params.MinGasLimit)) limit = 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 limit < params.TargetGasLimit {
gl.Add(parent.GasLimit(), decay) limit = parent.GasLimit() + decay
gl.Set(math.BigMin(gl, params.TargetGasLimit)) if limit > params.TargetGasLimit {
limit = params.TargetGasLimit
} }
return gl }
return limit
} }

View file

@ -305,7 +305,7 @@ func (bc *BlockChain) FastSyncCommitHead(hash common.Hash) error {
} }
// GasLimit returns the gas limit of the current HEAD block. // GasLimit returns the gas limit of the current HEAD block.
func (bc *BlockChain) GasLimit() *big.Int { func (bc *BlockChain) GasLimit() uint64 {
bc.mu.RLock() bc.mu.RLock()
defer bc.mu.RUnlock() defer bc.mu.RUnlock()
@ -677,9 +677,9 @@ func SetReceiptsData(config *params.ChainConfig, block *types.Block, receipts ty
} }
// The used gas can be calculated based on previous receipts // The used gas can be calculated based on previous receipts
if j == 0 { if j == 0 {
receipts[j].GasUsed = new(big.Int).Set(receipts[j].CumulativeGasUsed) receipts[j].GasUsed = receipts[j].CumulativeGasUsed
} else { } else {
receipts[j].GasUsed = new(big.Int).Sub(receipts[j].CumulativeGasUsed, receipts[j-1].CumulativeGasUsed) receipts[j].GasUsed = receipts[j].CumulativeGasUsed - receipts[j-1].CumulativeGasUsed
} }
// The derived log fields can simply be set from the block and transaction // The derived log fields can simply be set from the block and transaction
for k := 0; k < len(receipts[j].Logs); k++ { for k := 0; k < len(receipts[j].Logs); k++ {
@ -1002,7 +1002,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty
events = append(events, ChainSideEvent{block}) events = append(events, ChainSideEvent{block})
} }
stats.processed++ stats.processed++
stats.usedGas += usedGas.Uint64() stats.usedGas += usedGas
stats.report(chain, i) stats.report(chain, i)
} }
// Append a single chain head event if we've progressed the chain // Append a single chain head event if we've progressed the chain
@ -1196,10 +1196,11 @@ func (bc *BlockChain) PostChainEvents(events []interface{}, logs []*types.Log) {
} }
func (bc *BlockChain) update() { func (bc *BlockChain) update() {
futureTimer := time.Tick(5 * time.Second) futureTimer := time.NewTicker(5 * time.Second)
defer futureTimer.Stop()
for { for {
select { select {
case <-futureTimer: case <-futureTimer.C:
bc.procFutureBlocks() bc.procFutureBlocks()
case <-bc.quit: case <-bc.quit:
return return

View file

@ -340,11 +340,11 @@ func testBrokenChain(t *testing.T, full bool) {
type bproc struct{} type bproc struct{}
func (bproc) ValidateBody(*types.Block) error { return nil } func (bproc) ValidateBody(*types.Block) error { return nil }
func (bproc) ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas *big.Int) error { func (bproc) ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error {
return nil return nil
} }
func (bproc) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, *big.Int, error) { func (bproc) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) {
return nil, nil, new(big.Int), nil return nil, nil, 0, nil
} }
func makeHeaderChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Header { func makeHeaderChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Header {
@ -506,8 +506,8 @@ func testReorgBadHashes(t *testing.T, full bool) {
if ncm.CurrentBlock().Hash() != blocks[2].Header().Hash() { if ncm.CurrentBlock().Hash() != blocks[2].Header().Hash() {
t.Errorf("last block hash mismatch: have: %x, want %x", ncm.CurrentBlock().Hash(), blocks[2].Header().Hash()) t.Errorf("last block hash mismatch: have: %x, want %x", ncm.CurrentBlock().Hash(), blocks[2].Header().Hash())
} }
if blocks[2].Header().GasLimit.Cmp(ncm.GasLimit()) != 0 { if blocks[2].Header().GasLimit != ncm.GasLimit() {
t.Errorf("last block gasLimit mismatch: have: %x, want %x", ncm.GasLimit(), blocks[2].Header().GasLimit) t.Errorf("last block gasLimit mismatch: have: %d, want %d", ncm.GasLimit(), blocks[2].Header().GasLimit)
} }
} else { } else {
if ncm.CurrentHeader().Hash() != headers[2].Hash() { if ncm.CurrentHeader().Hash() != headers[2].Hash() {
@ -594,7 +594,7 @@ func TestFastVsFullChains(t *testing.T) {
// If the block number is multiple of 3, send a few bonus transactions to the miner // If the block number is multiple of 3, send a few bonus transactions to the miner
if i%3 == 2 { if i%3 == 2 {
for j := 0; j < i%4+1; j++ { for j := 0; j < i%4+1; j++ {
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), bigTxGas, nil, nil), signer, key) tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil), signer, key)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -767,8 +767,8 @@ func TestChainTxReorgs(t *testing.T) {
// Create two transactions shared between the chains: // Create two transactions shared between the chains:
// - postponed: transaction included at a later block in the forked chain // - postponed: transaction included at a later block in the forked chain
// - swapped: transaction included at the same block number in the forked chain // - swapped: transaction included at the same block number in the forked chain
postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), bigTxGas, nil, nil), signer, key1) postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1)
swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), bigTxGas, nil, nil), signer, key1) swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1)
// Create two transactions that will be dropped by the forked chain: // Create two transactions that will be dropped by the forked chain:
// - pastDrop: transaction dropped retroactively from a past block // - pastDrop: transaction dropped retroactively from a past block
@ -784,13 +784,13 @@ func TestChainTxReorgs(t *testing.T) {
chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) { chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {
switch i { switch i {
case 0: case 0:
pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), bigTxGas, nil, nil), signer, key2) pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2)
gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point
gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork
case 2: case 2:
freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), bigTxGas, nil, nil), signer, key2) freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2)
gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point
gen.AddTx(swapped) // This transaction will be swapped out at the exact height gen.AddTx(swapped) // This transaction will be swapped out at the exact height
@ -809,18 +809,18 @@ func TestChainTxReorgs(t *testing.T) {
chain, _ = GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 5, func(i int, gen *BlockGen) { chain, _ = GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 5, func(i int, gen *BlockGen) {
switch i { switch i {
case 0: case 0:
pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), bigTxGas, nil, nil), signer, key3) pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3)
gen.AddTx(pastAdd) // This transaction needs to be injected during reorg gen.AddTx(pastAdd) // This transaction needs to be injected during reorg
case 2: case 2:
gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain
gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain
freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), bigTxGas, nil, nil), signer, key3) freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3)
gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time
case 3: case 3:
futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), bigTxGas, nil, nil), signer, key3) futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3)
gen.AddTx(futureAdd) // This transaction will be added after a full reorg gen.AddTx(futureAdd) // This transaction will be added after a full reorg
} }
}) })
@ -877,7 +877,7 @@ func TestLogReorgs(t *testing.T) {
blockchain.SubscribeRemovedLogsEvent(rmLogsCh) blockchain.SubscribeRemovedLogsEvent(rmLogsCh)
chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) {
if i == 1 { if i == 1 {
tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), code), signer, key1) tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1)
if err != nil { if err != nil {
t.Fatalf("failed to create tx: %v", err) t.Fatalf("failed to create tx: %v", err)
} }
@ -926,7 +926,7 @@ func TestReorgSideEvent(t *testing.T) {
} }
replacementBlocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, gen *BlockGen) { replacementBlocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, gen *BlockGen) {
tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), nil), signer, key1) tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), nil), signer, key1)
if i == 2 { if i == 2 {
gen.OffsetTime(-9) gen.OffsetTime(-9)
} }
@ -1051,7 +1051,7 @@ func TestEIP155Transition(t *testing.T) {
tx *types.Transaction tx *types.Transaction
err error err error
basicTx = func(signer types.Signer) (*types.Transaction, error) { basicTx = func(signer types.Signer) (*types.Transaction, error) {
return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key) return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key)
} }
) )
switch i { switch i {
@ -1114,7 +1114,7 @@ func TestEIP155Transition(t *testing.T) {
tx *types.Transaction tx *types.Transaction
err error err error
basicTx = func(signer types.Signer) (*types.Transaction, error) { basicTx = func(signer types.Signer) (*types.Transaction, error) {
return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key) return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key)
} }
) )
switch i { switch i {
@ -1162,11 +1162,11 @@ func TestEIP161AccountRemoval(t *testing.T) {
) )
switch i { switch i {
case 0: case 0:
tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key) tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key)
case 1: case 1:
tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key) tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key)
case 2: case 2:
tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key) tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key)
} }
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View file

@ -86,7 +86,7 @@ func (b *BlockGen) AddTx(tx *types.Transaction) {
b.SetCoinbase(common.Address{}) b.SetCoinbase(common.Address{})
} }
b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs)) b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs))
receipt, _, err := ApplyTransaction(b.config, nil, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed, vm.Config{}) receipt, _, err := ApplyTransaction(b.config, nil, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vm.Config{})
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -232,7 +232,6 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
UncleHash: parent.UncleHash(), UncleHash: parent.UncleHash(),
}), }),
GasLimit: CalcGasLimit(parent), GasLimit: CalcGasLimit(parent),
GasUsed: new(big.Int),
Number: new(big.Int).Add(parent.Number(), common.Big1), Number: new(big.Int).Add(parent.Number(), common.Big1),
Time: time, Time: time,
} }

View file

@ -54,13 +54,13 @@ func ExampleGenerateChain() {
switch i { switch i {
case 0: case 0:
// In block 1, addr1 sends addr2 some ether. // In block 1, addr1 sends addr2 some ether.
tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), bigTxGas, nil, nil), signer, key1) tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
gen.AddTx(tx) gen.AddTx(tx)
case 1: case 1:
// In block 2, addr1 sends some more ether to addr2. // In block 2, addr1 sends some more ether to addr2.
// addr2 passes it on to addr3. // addr2 passes it on to addr3.
tx1, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(1000), bigTxGas, nil, nil), signer, key1) tx1, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key1)
tx2, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr3, big.NewInt(1000), bigTxGas, nil, nil), signer, key2) tx2, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key2)
gen.AddTx(tx1) gen.AddTx(tx1)
gen.AddTx(tx2) gen.AddTx(tx2)
case 2: case 2:

View file

@ -290,9 +290,9 @@ func TestHeadStorage(t *testing.T) {
func TestLookupStorage(t *testing.T) { func TestLookupStorage(t *testing.T) {
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), big.NewInt(1111), big.NewInt(11111), []byte{0x11, 0x11, 0x11}) tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11})
tx2 := types.NewTransaction(2, common.BytesToAddress([]byte{0x22}), big.NewInt(222), big.NewInt(2222), big.NewInt(22222), []byte{0x22, 0x22, 0x22}) tx2 := types.NewTransaction(2, common.BytesToAddress([]byte{0x22}), big.NewInt(222), 2222, big.NewInt(22222), []byte{0x22, 0x22, 0x22})
tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), big.NewInt(333), big.NewInt(3333), big.NewInt(33333), []byte{0x33, 0x33, 0x33}) tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), big.NewInt(333), 3333, big.NewInt(33333), []byte{0x33, 0x33, 0x33})
txs := []*types.Transaction{tx1, tx2, tx3} txs := []*types.Transaction{tx1, tx2, tx3}
block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, txs, nil, nil) block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, txs, nil, nil)
@ -337,25 +337,25 @@ func TestBlockReceiptStorage(t *testing.T) {
receipt1 := &types.Receipt{ receipt1 := &types.Receipt{
Status: types.ReceiptStatusFailed, Status: types.ReceiptStatusFailed,
CumulativeGasUsed: big.NewInt(1), CumulativeGasUsed: 1,
Logs: []*types.Log{ Logs: []*types.Log{
{Address: common.BytesToAddress([]byte{0x11})}, {Address: common.BytesToAddress([]byte{0x11})},
{Address: common.BytesToAddress([]byte{0x01, 0x11})}, {Address: common.BytesToAddress([]byte{0x01, 0x11})},
}, },
TxHash: common.BytesToHash([]byte{0x11, 0x11}), TxHash: common.BytesToHash([]byte{0x11, 0x11}),
ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
GasUsed: big.NewInt(111111), GasUsed: 111111,
} }
receipt2 := &types.Receipt{ receipt2 := &types.Receipt{
PostState: common.Hash{2}.Bytes(), PostState: common.Hash{2}.Bytes(),
CumulativeGasUsed: big.NewInt(2), CumulativeGasUsed: 2,
Logs: []*types.Log{ Logs: []*types.Log{
{Address: common.BytesToAddress([]byte{0x22})}, {Address: common.BytesToAddress([]byte{0x22})},
{Address: common.BytesToAddress([]byte{0x02, 0x22})}, {Address: common.BytesToAddress([]byte{0x02, 0x22})},
}, },
TxHash: common.BytesToHash([]byte{0x22, 0x22}), TxHash: common.BytesToHash([]byte{0x22, 0x22}),
ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}),
GasUsed: big.NewInt(222222), GasUsed: 222222,
} }
receipts := []*types.Receipt{receipt1, receipt2} receipts := []*types.Receipt{receipt1, receipt2}

View file

@ -53,7 +53,7 @@ func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author
BlockNumber: new(big.Int).Set(header.Number), BlockNumber: new(big.Int).Set(header.Number),
Time: new(big.Int).Set(header.Time), Time: new(big.Int).Set(header.Time),
Difficulty: new(big.Int).Set(header.Difficulty), Difficulty: new(big.Int).Set(header.Difficulty),
GasLimit: new(big.Int).Set(header.GasLimit), GasLimit: header.GasLimit,
GasPrice: new(big.Int).Set(msg.GasPrice()), GasPrice: new(big.Int).Set(msg.GasPrice()),
} }
} }

View file

@ -16,31 +16,34 @@
package core package core
import "math/big" import (
"fmt"
"math"
)
// GasPool tracks the amount of gas available during // GasPool tracks the amount of gas available during execution of the transactions
// execution of the transactions in a block. // in a block. The zero value is a pool with zero gas available.
// The zero value is a pool with zero gas available. type GasPool uint64
type GasPool big.Int
// AddGas makes gas available for execution. // AddGas makes gas available for execution.
func (gp *GasPool) AddGas(amount *big.Int) *GasPool { func (gp *GasPool) AddGas(amount uint64) *GasPool {
i := (*big.Int)(gp) if uint64(*gp) > math.MaxUint64-amount {
i.Add(i, amount) panic("gas pool pushed above uint64")
}
*(*uint64)(gp) += amount
return gp return gp
} }
// SubGas deducts the given amount from the pool if enough gas is // SubGas deducts the given amount from the pool if enough gas is
// available and returns an error otherwise. // available and returns an error otherwise.
func (gp *GasPool) SubGas(amount *big.Int) error { func (gp *GasPool) SubGas(amount uint64) error {
i := (*big.Int)(gp) if uint64(*gp) < amount {
if i.Cmp(amount) < 0 {
return ErrGasLimitReached return ErrGasLimitReached
} }
i.Sub(i, amount) *(*uint64)(gp) -= amount
return nil return nil
} }
func (gp *GasPool) String() string { func (gp *GasPool) String() string {
return (*big.Int)(gp).String() return fmt.Sprintf("%d", *gp)
} }

View file

@ -13,6 +13,8 @@ import (
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
var _ = (*genesisSpecMarshaling)(nil)
func (g Genesis) MarshalJSON() ([]byte, error) { func (g Genesis) MarshalJSON() ([]byte, error) {
type Genesis struct { type Genesis struct {
Config *params.ChainConfig `json:"config"` Config *params.ChainConfig `json:"config"`

View file

@ -239,8 +239,8 @@ func (g *Genesis) ToBlock() (*types.Block, *state.StateDB) {
Time: new(big.Int).SetUint64(g.Timestamp), Time: new(big.Int).SetUint64(g.Timestamp),
ParentHash: g.ParentHash, ParentHash: g.ParentHash,
Extra: g.ExtraData, Extra: g.ExtraData,
GasLimit: new(big.Int).SetUint64(g.GasLimit), GasLimit: g.GasLimit,
GasUsed: new(big.Int).SetUint64(g.GasUsed), GasUsed: g.GasUsed,
Difficulty: g.Difficulty, Difficulty: g.Difficulty,
MixDigest: g.Mixhash, MixDigest: g.Mixhash,
Coinbase: g.Coinbase, Coinbase: g.Coinbase,

View file

@ -62,7 +62,7 @@ type (
// Changes to other state values. // Changes to other state values.
refundChange struct { refundChange struct {
prev *big.Int prev uint64
} }
addLogChange struct { addLogChange struct {
txhash common.Hash txhash common.Hash

View file

@ -57,7 +57,7 @@ type StateDB struct {
dbErr error dbErr error
// The refund counter, also used by state transitioning. // The refund counter, also used by state transitioning.
refund *big.Int refund uint64
thash, bhash common.Hash thash, bhash common.Hash
txIndex int txIndex int
@ -86,7 +86,6 @@ func New(root common.Hash, db Database) (*StateDB, error) {
trie: tr, trie: tr,
stateObjects: make(map[common.Address]*stateObject), stateObjects: make(map[common.Address]*stateObject),
stateObjectsDirty: make(map[common.Address]struct{}), stateObjectsDirty: make(map[common.Address]struct{}),
refund: new(big.Int),
logs: make(map[common.Hash][]*types.Log), logs: make(map[common.Hash][]*types.Log),
preimages: make(map[common.Hash][]byte), preimages: make(map[common.Hash][]byte),
}, nil }, nil
@ -161,9 +160,9 @@ func (self *StateDB) Preimages() map[common.Hash][]byte {
return self.preimages return self.preimages
} }
func (self *StateDB) AddRefund(gas *big.Int) { func (self *StateDB) AddRefund(gas uint64) {
self.journal = append(self.journal, refundChange{prev: new(big.Int).Set(self.refund)}) self.journal = append(self.journal, refundChange{prev: self.refund})
self.refund.Add(self.refund, gas) self.refund += gas
} }
// Exist reports whether the given account address exists in the state. // Exist reports whether the given account address exists in the state.
@ -456,7 +455,7 @@ func (self *StateDB) Copy() *StateDB {
trie: self.db.CopyTrie(self.trie), trie: self.db.CopyTrie(self.trie),
stateObjects: make(map[common.Address]*stateObject, len(self.stateObjectsDirty)), stateObjects: make(map[common.Address]*stateObject, len(self.stateObjectsDirty)),
stateObjectsDirty: make(map[common.Address]struct{}, len(self.stateObjectsDirty)), stateObjectsDirty: make(map[common.Address]struct{}, len(self.stateObjectsDirty)),
refund: new(big.Int).Set(self.refund), refund: self.refund,
logs: make(map[common.Hash][]*types.Log, len(self.logs)), logs: make(map[common.Hash][]*types.Log, len(self.logs)),
logSize: self.logSize, logSize: self.logSize,
preimages: make(map[common.Hash][]byte), preimages: make(map[common.Hash][]byte),
@ -506,9 +505,7 @@ func (self *StateDB) RevertToSnapshot(revid int) {
} }
// GetRefund returns the current value of the refund counter. // GetRefund returns the current value of the refund counter.
// The return value must not be modified by the caller and will become func (self *StateDB) GetRefund() uint64 {
// invalid at the next call to AddRefund.
func (self *StateDB) GetRefund() *big.Int {
return self.refund return self.refund
} }
@ -568,7 +565,7 @@ func (s *StateDB) DeleteSuicides() {
func (s *StateDB) clearJournalAndRefund() { func (s *StateDB) clearJournalAndRefund() {
s.journal = nil s.journal = nil
s.validRevisions = s.validRevisions[:0] s.validRevisions = s.validRevisions[:0]
s.refund = new(big.Int) s.refund = 0
} }
// CommitTo writes the state to the given database. // CommitTo writes the state to the given database.

View file

@ -263,7 +263,7 @@ func newTestAction(addr common.Address, r *rand.Rand) testAction {
{ {
name: "AddRefund", name: "AddRefund",
fn: func(a testAction, s *StateDB) { fn: func(a testAction, s *StateDB) {
s.AddRefund(big.NewInt(a.args[0])) s.AddRefund(uint64(a.args[0]))
}, },
args: make([]int64, 1), args: make([]int64, 1),
noAddr: true, noAddr: true,
@ -396,7 +396,7 @@ func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
} }
} }
if state.GetRefund().Cmp(checkstate.GetRefund()) != 0 { if state.GetRefund() != checkstate.GetRefund() {
return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d", return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d",
state.GetRefund(), checkstate.GetRefund()) state.GetRefund(), checkstate.GetRefund())
} }

View file

@ -17,8 +17,6 @@
package core package core
import ( import (
"math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/consensus/misc"
@ -55,10 +53,10 @@ func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consen
// Process returns the receipts and logs accumulated during the process and // Process returns the receipts and logs accumulated during the process and
// returns the amount of gas that was used in the process. If any of the // returns the amount of gas that was used in the process. If any of the
// transactions failed to execute due to insufficient gas it will return an error. // transactions failed to execute due to insufficient gas it will return an error.
func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, *big.Int, error) { func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) {
var ( var (
receipts types.Receipts receipts types.Receipts
totalUsedGas = big.NewInt(0) usedGas = new(uint64)
header = block.Header() header = block.Header()
allLogs []*types.Log allLogs []*types.Log
gp = new(GasPool).AddGas(block.GasLimit()) gp = new(GasPool).AddGas(block.GasLimit())
@ -70,9 +68,9 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
// Iterate over and process the individual transactions // Iterate over and process the individual transactions
for i, tx := range block.Transactions() { for i, tx := range block.Transactions() {
statedb.Prepare(tx.Hash(), block.Hash(), i) statedb.Prepare(tx.Hash(), block.Hash(), i)
receipt, _, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, totalUsedGas, cfg) receipt, _, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, usedGas, cfg)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, 0, err
} }
receipts = append(receipts, receipt) receipts = append(receipts, receipt)
allLogs = append(allLogs, receipt.Logs...) allLogs = append(allLogs, receipt.Logs...)
@ -80,17 +78,17 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards) // Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles(), receipts) p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles(), receipts)
return receipts, allLogs, totalUsedGas, nil return receipts, allLogs, *usedGas, nil
} }
// ApplyTransaction attempts to apply a transaction to the given state database // ApplyTransaction attempts to apply a transaction to the given state database
// and uses the input parameters for its environment. It returns the receipt // and uses the input parameters for its environment. It returns the receipt
// for the transaction, gas used and an error if the transaction failed, // for the transaction, gas used and an error if the transaction failed,
// indicating the block was invalid. // indicating the block was invalid.
func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, cfg vm.Config) (*types.Receipt, *big.Int, error) { func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, uint64, error) {
msg, err := tx.AsMessage(types.MakeSigner(config, header.Number)) msg, err := tx.AsMessage(types.MakeSigner(config, header.Number))
if err != nil { if err != nil {
return nil, nil, err return nil, 0, err
} }
// Create a new context to be used in the EVM environment // Create a new context to be used in the EVM environment
context := NewEVMContext(msg, header, bc, author) context := NewEVMContext(msg, header, bc, author)
@ -100,9 +98,8 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common
// Apply the transaction to the current state (included in the env) // Apply the transaction to the current state (included in the env)
_, gas, failed, err := ApplyMessage(vmenv, msg, gp) _, gas, failed, err := ApplyMessage(vmenv, msg, gp)
if err != nil { if err != nil {
return nil, nil, err return nil, 0, err
} }
// Update the state with pending changes // Update the state with pending changes
var root []byte var root []byte
if config.IsByzantium(header.Number) { if config.IsByzantium(header.Number) {
@ -110,18 +107,17 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common
} else { } else {
root = statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes() root = statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes()
} }
usedGas.Add(usedGas, gas) *usedGas += gas
// Create a new receipt for the transaction, storing the intermediate root and gas used by the tx // Create a new receipt for the transaction, storing the intermediate root and gas used by the tx
// based on the eip phase, we're passing wether the root touch-delete accounts. // based on the eip phase, we're passing wether the root touch-delete accounts.
receipt := types.NewReceipt(root, failed, usedGas) receipt := types.NewReceipt(root, failed, *usedGas)
receipt.TxHash = tx.Hash() receipt.TxHash = tx.Hash()
receipt.GasUsed = new(big.Int).Set(gas) receipt.GasUsed = gas
// if the transaction created a contract, store the creation address in the receipt. // if the transaction created a contract, store the creation address in the receipt.
if msg.To() == nil { if msg.To() == nil {
receipt.ContractAddress = crypto.CreateAddress(vmenv.Context.Origin, tx.Nonce()) receipt.ContractAddress = crypto.CreateAddress(vmenv.Context.Origin, tx.Nonce())
} }
// Set the receipt logs and create a bloom for filtering // Set the receipt logs and create a bloom for filtering
receipt.Logs = statedb.GetLogs(tx.Hash()) receipt.Logs = statedb.GetLogs(tx.Hash())
receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) receipt.Bloom = types.CreateBloom(types.Receipts{receipt})

View file

@ -18,17 +18,16 @@ package core
import ( import (
"errors" "errors"
"math"
"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"
) )
var ( var (
Big0 = big.NewInt(0)
errInsufficientBalanceForGas = errors.New("insufficient balance to pay for gas") errInsufficientBalanceForGas = errors.New("insufficient balance to pay for gas")
) )
@ -54,7 +53,7 @@ type StateTransition struct {
msg Message msg Message
gas uint64 gas uint64
gasPrice *big.Int gasPrice *big.Int
initialGas *big.Int initialGas uint64
value *big.Int value *big.Int
data []byte data []byte
state vm.StateDB state vm.StateDB
@ -68,7 +67,7 @@ type Message interface {
To() *common.Address To() *common.Address
GasPrice() *big.Int GasPrice() *big.Int
Gas() *big.Int Gas() uint64
Value() *big.Int Value() *big.Int
Nonce() uint64 Nonce() uint64
@ -76,32 +75,37 @@ type Message interface {
Data() []byte Data() []byte
} }
// IntrinsicGas computes the 'intrinsic gas' for a message // IntrinsicGas computes the 'intrinsic gas' for a message with the given data.
// with the given data. func IntrinsicGas(data []byte, contractCreation, homestead bool) (uint64, error) {
// // Set the starting gas for the raw transaction
// TODO convert to uint64 var gas uint64
func IntrinsicGas(data []byte, contractCreation, homestead bool) *big.Int {
igas := new(big.Int)
if contractCreation && homestead { if contractCreation && homestead {
igas.SetUint64(params.TxGasContractCreation) gas = params.TxGasContractCreation
} else { } else {
igas.SetUint64(params.TxGas) gas = params.TxGas
} }
// Bump the required gas by the amount of transactional data
if len(data) > 0 { if len(data) > 0 {
var nz int64 // Zero and non-zero bytes are priced differently
var nz uint64
for _, byt := range data { for _, byt := range data {
if byt != 0 { if byt != 0 {
nz++ nz++
} }
} }
m := big.NewInt(nz) // Make sure we don't exceed uint64 for all data combinations
m.Mul(m, new(big.Int).SetUint64(params.TxDataNonZeroGas)) if (math.MaxUint64-gas)/params.TxDataNonZeroGas < nz {
igas.Add(igas, m) return 0, vm.ErrOutOfGas
m.SetInt64(int64(len(data)) - nz)
m.Mul(m, new(big.Int).SetUint64(params.TxDataZeroGas))
igas.Add(igas, m)
} }
return igas gas += nz * params.TxDataNonZeroGas
z := uint64(len(data)) - nz
if (math.MaxUint64-gas)/params.TxDataZeroGas < z {
return 0, vm.ErrOutOfGas
}
gas += z * params.TxDataZeroGas
}
return gas, nil
} }
// NewStateTransition initialises and returns a new state transition object. // NewStateTransition initialises and returns a new state transition object.
@ -111,7 +115,6 @@ func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition
evm: evm, evm: evm,
msg: msg, msg: msg,
gasPrice: msg.GasPrice(), gasPrice: msg.GasPrice(),
initialGas: new(big.Int),
value: msg.Value(), value: msg.Value(),
data: msg.Data(), data: msg.Data(),
state: evm.StateDB, state: evm.StateDB,
@ -125,11 +128,8 @@ func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition
// the gas used (which includes gas refunds) and an error if it failed. An error always // the gas used (which includes gas refunds) and an error if it failed. An error always
// indicates a core error meaning that the message would always fail for that particular // indicates a core error meaning that the message would always fail for that particular
// state and would never be accepted within a block. // state and would never be accepted within a block.
func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) ([]byte, *big.Int, bool, error) { func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) ([]byte, uint64, bool, error) {
st := NewStateTransition(evm, msg, gp) return NewStateTransition(evm, msg, gp).TransitionDb()
ret, _, gasUsed, failed, err := st.TransitionDb()
return ret, gasUsed, failed, err
} }
func (st *StateTransition) from() vm.AccountRef { func (st *StateTransition) from() vm.AccountRef {
@ -166,26 +166,20 @@ func (st *StateTransition) useGas(amount uint64) error {
} }
func (st *StateTransition) buyGas() error { func (st *StateTransition) buyGas() error {
mgas := st.msg.Gas()
if mgas.BitLen() > 64 {
return vm.ErrOutOfGas
}
mgval := new(big.Int).Mul(mgas, st.gasPrice)
var ( var (
state = st.state state = st.state
sender = st.from() sender = st.from()
) )
mgval := new(big.Int).Mul(new(big.Int).SetUint64(st.msg.Gas()), st.gasPrice)
if state.GetBalance(sender.Address()).Cmp(mgval) < 0 { if state.GetBalance(sender.Address()).Cmp(mgval) < 0 {
return errInsufficientBalanceForGas return errInsufficientBalanceForGas
} }
if err := st.gp.SubGas(mgas); err != nil { if err := st.gp.SubGas(st.msg.Gas()); err != nil {
return err return err
} }
st.gas += mgas.Uint64() st.gas += st.msg.Gas()
st.initialGas.Set(mgas) st.initialGas = st.msg.Gas()
state.SubBalance(sender.Address(), mgval) state.SubBalance(sender.Address(), mgval)
return nil return nil
} }
@ -206,10 +200,10 @@ func (st *StateTransition) preCheck() error {
return st.buyGas() return st.buyGas()
} }
// TransitionDb will transition the state by applying the current message and returning the result // TransitionDb will transition the state by applying the current message and
// including the required gas for the operation as well as the used gas. It returns an error if it // returning the result including the the used gas. It returns an error if it
// failed. An error indicates a consensus issue. // failed. An error indicates a consensus issue.
func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big.Int, failed bool, err error) { func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bool, err error) {
if err = st.preCheck(); err != nil { if err = st.preCheck(); err != nil {
return return
} }
@ -220,13 +214,9 @@ func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big
contractCreation := msg.To() == nil contractCreation := msg.To() == nil
// Pay intrinsic gas // Pay intrinsic gas
// TODO convert to uint64 gas, err := IntrinsicGas(st.data, contractCreation, homestead)
intrinsicGas := IntrinsicGas(st.data, contractCreation, homestead) if err = st.useGas(gas); err != nil {
if intrinsicGas.BitLen() > 64 { return nil, 0, false, err
return nil, nil, nil, false, vm.ErrOutOfGas
}
if err = st.useGas(intrinsicGas.Uint64()); err != nil {
return nil, nil, nil, false, err
} }
var ( var (
@ -249,36 +239,35 @@ func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big
// sufficient balance to make the transfer happen. The first // sufficient balance to make the transfer happen. The first
// balance transfer may never fail. // balance transfer may never fail.
if vmerr == vm.ErrInsufficientBalance { if vmerr == vm.ErrInsufficientBalance {
return nil, nil, nil, false, vmerr return nil, 0, false, vmerr
} }
} }
requiredGas = new(big.Int).Set(st.gasUsed())
st.refundGas() st.refundGas()
st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(st.gasUsed(), st.gasPrice)) st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
return ret, requiredGas, st.gasUsed(), vmerr != nil, err return ret, st.gasUsed(), vmerr != nil, err
} }
func (st *StateTransition) refundGas() { func (st *StateTransition) refundGas() {
// Return eth for remaining gas to the sender account, // Apply refund counter, capped to half of the used gas.
// exchanged at the original rate. refund := st.gasUsed() / 2
sender := st.from() // err already checked if refund > st.state.GetRefund() {
refund = st.state.GetRefund()
}
st.gas += refund
// Return ETH for remaining gas, exchanged at the original rate.
sender := st.from()
remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gas), st.gasPrice) remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gas), st.gasPrice)
st.state.AddBalance(sender.Address(), remaining) st.state.AddBalance(sender.Address(), remaining)
// Apply refund counter, capped to half of the used gas.
uhalf := remaining.Div(st.gasUsed(), common.Big2)
refund := math.BigMin(uhalf, st.state.GetRefund())
st.gas += refund.Uint64()
st.state.AddBalance(sender.Address(), refund.Mul(refund, st.gasPrice))
// Also return remaining gas to the block gas counter so it is // Also return remaining gas to the block gas counter so it is
// available for the next transaction. // available for the next transaction.
st.gp.AddGas(new(big.Int).SetUint64(st.gas)) st.gp.AddGas(st.gas)
} }
func (st *StateTransition) gasUsed() *big.Int { // gasUsed returns the amount of gas used up by the state transition.
return new(big.Int).Sub(st.initialGas, new(big.Int).SetUint64(st.gas)) func (st *StateTransition) gasUsed() uint64 {
return st.initialGas - st.gas
} }

View file

@ -224,7 +224,7 @@ type txList struct {
txs *txSortedMap // Heap indexed sorted hash map of the transactions txs *txSortedMap // Heap indexed sorted hash map of the transactions
costcap *big.Int // Price of the highest costing transaction (reset only if exceeds balance) costcap *big.Int // Price of the highest costing transaction (reset only if exceeds balance)
gascap *big.Int // Gas limit of the highest spending transaction (reset only if exceeds block limit) gascap uint64 // Gas limit of the highest spending transaction (reset only if exceeds block limit)
} }
// newTxList create a new transaction list for maintaining nonce-indexable fast, // newTxList create a new transaction list for maintaining nonce-indexable fast,
@ -234,7 +234,6 @@ func newTxList(strict bool) *txList {
strict: strict, strict: strict,
txs: newTxSortedMap(), txs: newTxSortedMap(),
costcap: new(big.Int), costcap: new(big.Int),
gascap: new(big.Int),
} }
} }
@ -266,7 +265,7 @@ func (l *txList) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Tran
if cost := tx.Cost(); l.costcap.Cmp(cost) < 0 { if cost := tx.Cost(); l.costcap.Cmp(cost) < 0 {
l.costcap = cost l.costcap = cost
} }
if gas := tx.Gas(); l.gascap.Cmp(gas) < 0 { if gas := tx.Gas(); l.gascap < gas {
l.gascap = gas l.gascap = gas
} }
return true, old return true, old
@ -288,16 +287,16 @@ func (l *txList) Forward(threshold uint64) types.Transactions {
// a point in calculating all the costs or if the balance covers all. If the threshold // a point in calculating all the costs or if the balance covers all. If the threshold
// is lower than the costgas cap, the caps will be reset to a new high after removing // is lower than the costgas cap, the caps will be reset to a new high after removing
// the newly invalidated transactions. // the newly invalidated transactions.
func (l *txList) Filter(costLimit, gasLimit *big.Int) (types.Transactions, types.Transactions) { func (l *txList) Filter(costLimit *big.Int, gasLimit uint64) (types.Transactions, types.Transactions) {
// If all transactions are below the threshold, short circuit // If all transactions are below the threshold, short circuit
if l.costcap.Cmp(costLimit) <= 0 && l.gascap.Cmp(gasLimit) <= 0 { if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit {
return nil, nil return nil, nil
} }
l.costcap = new(big.Int).Set(costLimit) // Lower the caps to the thresholds l.costcap = new(big.Int).Set(costLimit) // Lower the caps to the thresholds
l.gascap = new(big.Int).Set(gasLimit) l.gascap = gasLimit
// Filter out all the transactions above the account's funds // Filter out all the transactions above the account's funds
removed := l.txs.Filter(func(tx *types.Transaction) bool { return tx.Cost().Cmp(costLimit) > 0 || tx.Gas().Cmp(gasLimit) > 0 }) removed := l.txs.Filter(func(tx *types.Transaction) bool { return tx.Cost().Cmp(costLimit) > 0 || tx.Gas() > gasLimit })
// If the list was strict, filter anything above the lowest nonce // If the list was strict, filter anything above the lowest nonce
var invalids types.Transactions var invalids types.Transactions

View file

@ -17,7 +17,6 @@
package core package core
import ( import (
"math/big"
"math/rand" "math/rand"
"testing" "testing"
@ -33,7 +32,7 @@ func TestStrictTxListAdd(t *testing.T) {
txs := make(types.Transactions, 1024) txs := make(types.Transactions, 1024)
for i := 0; i < len(txs); i++ { for i := 0; i < len(txs); i++ {
txs[i] = transaction(uint64(i), new(big.Int), key) txs[i] = transaction(uint64(i), 0, key)
} }
// Insert the transactions in a random order // Insert the transactions in a random order
list := newTxList(true) list := newTxList(true)

View file

@ -197,7 +197,7 @@ type TxPool struct {
currentState *state.StateDB // Current state in the blockchain head currentState *state.StateDB // Current state in the blockchain head
pendingState *state.ManagedState // Pending state tracking virtual nonces pendingState *state.ManagedState // Pending state tracking virtual nonces
currentMaxGas *big.Int // Current gas limit for transaction caps currentMaxGas uint64 // Current gas limit for transaction caps
locals *accountSet // Set of local transaction to exempt from eviction rules locals *accountSet // Set of local transaction to exempt from eviction rules
journal *txJournal // Journal of local transaction to back up to disk journal *txJournal // Journal of local transaction to back up to disk
@ -564,7 +564,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
return ErrNegativeValue return ErrNegativeValue
} }
// Ensure the transaction doesn't exceed the current block limit gas. // Ensure the transaction doesn't exceed the current block limit gas.
if pool.currentMaxGas.Cmp(tx.Gas()) < 0 { if pool.currentMaxGas < tx.Gas() {
return ErrGasLimit return ErrGasLimit
} }
// Make sure the transaction is signed properly // Make sure the transaction is signed properly
@ -586,8 +586,11 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
if pool.currentState.GetBalance(from).Cmp(tx.Cost()) < 0 { if pool.currentState.GetBalance(from).Cmp(tx.Cost()) < 0 {
return ErrInsufficientFunds return ErrInsufficientFunds
} }
intrGas := IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead) intrGas, err := IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead)
if tx.Gas().Cmp(intrGas) < 0 { if err != nil {
return err
}
if tx.Gas() < intrGas {
return ErrIntrinsicGas return ErrIntrinsicGas
} }
return nil return nil

View file

@ -46,7 +46,7 @@ func init() {
type testBlockChain struct { type testBlockChain struct {
statedb *state.StateDB statedb *state.StateDB
gasLimit *big.Int gasLimit uint64
chainHeadFeed *event.Feed chainHeadFeed *event.Feed
} }
@ -68,11 +68,11 @@ func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) even
return bc.chainHeadFeed.Subscribe(ch) return bc.chainHeadFeed.Subscribe(ch)
} }
func transaction(nonce uint64, gaslimit *big.Int, key *ecdsa.PrivateKey) *types.Transaction { func transaction(nonce uint64, gaslimit uint64, key *ecdsa.PrivateKey) *types.Transaction {
return pricedTransaction(nonce, gaslimit, big.NewInt(1), key) return pricedTransaction(nonce, gaslimit, big.NewInt(1), key)
} }
func pricedTransaction(nonce uint64, gaslimit, gasprice *big.Int, key *ecdsa.PrivateKey) *types.Transaction { func pricedTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey) *types.Transaction {
tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, gasprice, nil), types.HomesteadSigner{}, key) tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, gasprice, nil), types.HomesteadSigner{}, key)
return tx return tx
} }
@ -80,7 +80,7 @@ func pricedTransaction(nonce uint64, gaslimit, gasprice *big.Int, key *ecdsa.Pri
func setupTxPool() (*TxPool, *ecdsa.PrivateKey) { func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
key, _ := crypto.GenerateKey() key, _ := crypto.GenerateKey()
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
@ -184,10 +184,10 @@ func TestStateChangeDuringTransactionPoolReset(t *testing.T) {
// setup pool with 2 transaction in it // setup pool with 2 transaction in it
statedb.SetBalance(address, new(big.Int).SetUint64(params.Ether)) statedb.SetBalance(address, new(big.Int).SetUint64(params.Ether))
blockchain := &testChain{&testBlockChain{statedb, big.NewInt(1000000000), new(event.Feed)}, address, &trigger} blockchain := &testChain{&testBlockChain{statedb, 1000000000, new(event.Feed)}, address, &trigger}
tx0 := transaction(0, big.NewInt(100000), key) tx0 := transaction(0, 100000, key)
tx1 := transaction(1, big.NewInt(100000), key) tx1 := transaction(1, 100000, key)
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
defer pool.Stop() defer pool.Stop()
@ -230,7 +230,7 @@ func TestInvalidTransactions(t *testing.T) {
pool, key := setupTxPool() pool, key := setupTxPool()
defer pool.Stop() defer pool.Stop()
tx := transaction(0, big.NewInt(100), key) tx := transaction(0, 100, key)
from, _ := deriveSender(tx) from, _ := deriveSender(tx)
pool.currentState.AddBalance(from, big.NewInt(1)) pool.currentState.AddBalance(from, big.NewInt(1))
@ -238,7 +238,7 @@ func TestInvalidTransactions(t *testing.T) {
t.Error("expected", ErrInsufficientFunds) t.Error("expected", ErrInsufficientFunds)
} }
balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(tx.Gas(), tx.GasPrice())) balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice()))
pool.currentState.AddBalance(from, balance) pool.currentState.AddBalance(from, balance)
if err := pool.AddRemote(tx); err != ErrIntrinsicGas { if err := pool.AddRemote(tx); err != ErrIntrinsicGas {
t.Error("expected", ErrIntrinsicGas, "got", err) t.Error("expected", ErrIntrinsicGas, "got", err)
@ -246,12 +246,12 @@ func TestInvalidTransactions(t *testing.T) {
pool.currentState.SetNonce(from, 1) pool.currentState.SetNonce(from, 1)
pool.currentState.AddBalance(from, big.NewInt(0xffffffffffffff)) pool.currentState.AddBalance(from, big.NewInt(0xffffffffffffff))
tx = transaction(0, big.NewInt(100000), key) tx = transaction(0, 100000, key)
if err := pool.AddRemote(tx); err != ErrNonceTooLow { if err := pool.AddRemote(tx); err != ErrNonceTooLow {
t.Error("expected", ErrNonceTooLow) t.Error("expected", ErrNonceTooLow)
} }
tx = transaction(1, big.NewInt(100000), key) tx = transaction(1, 100000, key)
pool.gasPrice = big.NewInt(1000) pool.gasPrice = big.NewInt(1000)
if err := pool.AddRemote(tx); err != ErrUnderpriced { if err := pool.AddRemote(tx); err != ErrUnderpriced {
t.Error("expected", ErrUnderpriced, "got", err) t.Error("expected", ErrUnderpriced, "got", err)
@ -267,7 +267,7 @@ func TestTransactionQueue(t *testing.T) {
pool, key := setupTxPool() pool, key := setupTxPool()
defer pool.Stop() defer pool.Stop()
tx := transaction(0, big.NewInt(100), key) tx := transaction(0, 100, key)
from, _ := deriveSender(tx) from, _ := deriveSender(tx)
pool.currentState.AddBalance(from, big.NewInt(1000)) pool.currentState.AddBalance(from, big.NewInt(1000))
pool.lockedReset(nil, nil) pool.lockedReset(nil, nil)
@ -278,7 +278,7 @@ func TestTransactionQueue(t *testing.T) {
t.Error("expected valid txs to be 1 is", len(pool.pending)) t.Error("expected valid txs to be 1 is", len(pool.pending))
} }
tx = transaction(1, big.NewInt(100), key) tx = transaction(1, 100, key)
from, _ = deriveSender(tx) from, _ = deriveSender(tx)
pool.currentState.SetNonce(from, 2) pool.currentState.SetNonce(from, 2)
pool.enqueueTx(tx.Hash(), tx) pool.enqueueTx(tx.Hash(), tx)
@ -294,9 +294,9 @@ func TestTransactionQueue(t *testing.T) {
pool, key = setupTxPool() pool, key = setupTxPool()
defer pool.Stop() defer pool.Stop()
tx1 := transaction(0, big.NewInt(100), key) tx1 := transaction(0, 100, key)
tx2 := transaction(10, big.NewInt(100), key) tx2 := transaction(10, 100, key)
tx3 := transaction(11, big.NewInt(100), key) tx3 := transaction(11, 100, key)
from, _ = deriveSender(tx1) from, _ = deriveSender(tx1)
pool.currentState.AddBalance(from, big.NewInt(1000)) pool.currentState.AddBalance(from, big.NewInt(1000))
pool.lockedReset(nil, nil) pool.lockedReset(nil, nil)
@ -321,7 +321,7 @@ func TestTransactionNegativeValue(t *testing.T) {
pool, key := setupTxPool() pool, key := setupTxPool()
defer pool.Stop() defer pool.Stop()
tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), big.NewInt(100), big.NewInt(1), nil), types.HomesteadSigner{}, key) tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), 100, big.NewInt(1), nil), types.HomesteadSigner{}, key)
from, _ := deriveSender(tx) from, _ := deriveSender(tx)
pool.currentState.AddBalance(from, big.NewInt(1)) pool.currentState.AddBalance(from, big.NewInt(1))
if err := pool.AddRemote(tx); err != ErrNegativeValue { if err := pool.AddRemote(tx); err != ErrNegativeValue {
@ -341,12 +341,12 @@ func TestTransactionChainFork(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
statedb.AddBalance(addr, big.NewInt(100000000000000)) statedb.AddBalance(addr, big.NewInt(100000000000000))
pool.chain = &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)}
pool.lockedReset(nil, nil) pool.lockedReset(nil, nil)
} }
resetState() resetState()
tx := transaction(0, big.NewInt(100000), key) tx := transaction(0, 100000, key)
if _, err := pool.add(tx, false); err != nil { if _, err := pool.add(tx, false); err != nil {
t.Error("didn't expect error", err) t.Error("didn't expect error", err)
} }
@ -371,15 +371,15 @@ func TestTransactionDoubleNonce(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
statedb.AddBalance(addr, big.NewInt(100000000000000)) statedb.AddBalance(addr, big.NewInt(100000000000000))
pool.chain = &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)}
pool.lockedReset(nil, nil) pool.lockedReset(nil, nil)
} }
resetState() resetState()
signer := types.HomesteadSigner{} signer := types.HomesteadSigner{}
tx1, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(100000), big.NewInt(1), nil), signer, key) tx1, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 100000, big.NewInt(1), nil), signer, key)
tx2, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(2), nil), signer, key) tx2, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(2), nil), signer, key)
tx3, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(1), nil), signer, key) tx3, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(1), nil), signer, key)
// Add the first two transaction, ensure higher priced stays only // Add the first two transaction, ensure higher priced stays only
if replace, err := pool.add(tx1, false); err != nil || replace { if replace, err := pool.add(tx1, false); err != nil || replace {
@ -418,7 +418,7 @@ func TestTransactionMissingNonce(t *testing.T) {
addr := crypto.PubkeyToAddress(key.PublicKey) addr := crypto.PubkeyToAddress(key.PublicKey)
pool.currentState.AddBalance(addr, big.NewInt(100000000000000)) pool.currentState.AddBalance(addr, big.NewInt(100000000000000))
tx := transaction(1, big.NewInt(100000), key) tx := transaction(1, 100000, key)
if _, err := pool.add(tx, false); err != nil { if _, err := pool.add(tx, false); err != nil {
t.Error("didn't expect error", err) t.Error("didn't expect error", err)
} }
@ -445,7 +445,7 @@ func TestTransactionNonceRecovery(t *testing.T) {
pool.currentState.AddBalance(addr, big.NewInt(100000000000000)) pool.currentState.AddBalance(addr, big.NewInt(100000000000000))
pool.lockedReset(nil, nil) pool.lockedReset(nil, nil)
tx := transaction(n, big.NewInt(100000), key) tx := transaction(n, 100000, key)
if err := pool.AddRemote(tx); err != nil { if err := pool.AddRemote(tx); err != nil {
t.Error(err) t.Error(err)
} }
@ -466,17 +466,17 @@ func TestTransactionDropping(t *testing.T) {
pool, key := setupTxPool() pool, key := setupTxPool()
defer pool.Stop() defer pool.Stop()
account, _ := deriveSender(transaction(0, big.NewInt(0), key)) account, _ := deriveSender(transaction(0, 0, key))
pool.currentState.AddBalance(account, big.NewInt(1000)) pool.currentState.AddBalance(account, big.NewInt(1000))
// Add some pending and some queued transactions // Add some pending and some queued transactions
var ( var (
tx0 = transaction(0, big.NewInt(100), key) tx0 = transaction(0, 100, key)
tx1 = transaction(1, big.NewInt(200), key) tx1 = transaction(1, 200, key)
tx2 = transaction(2, big.NewInt(300), key) tx2 = transaction(2, 300, key)
tx10 = transaction(10, big.NewInt(100), key) tx10 = transaction(10, 100, key)
tx11 = transaction(11, big.NewInt(200), key) tx11 = transaction(11, 200, key)
tx12 = transaction(12, big.NewInt(300), key) tx12 = transaction(12, 300, key)
) )
pool.promoteTx(account, tx0.Hash(), tx0) pool.promoteTx(account, tx0.Hash(), tx0)
pool.promoteTx(account, tx1.Hash(), tx1) pool.promoteTx(account, tx1.Hash(), tx1)
@ -531,7 +531,7 @@ func TestTransactionDropping(t *testing.T) {
t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 4) t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 4)
} }
// Reduce the block gas limit, check that invalidated transactions are dropped // Reduce the block gas limit, check that invalidated transactions are dropped
pool.chain.(*testBlockChain).gasLimit = big.NewInt(100) pool.chain.(*testBlockChain).gasLimit = 100
pool.lockedReset(nil, nil) pool.lockedReset(nil, nil)
if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok { if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok {
@ -561,7 +561,7 @@ func TestTransactionPostponing(t *testing.T) {
pool, key := setupTxPool() pool, key := setupTxPool()
defer pool.Stop() defer pool.Stop()
account, _ := deriveSender(transaction(0, big.NewInt(0), key)) account, _ := deriveSender(transaction(0, 0, key))
pool.currentState.AddBalance(account, big.NewInt(1000)) pool.currentState.AddBalance(account, big.NewInt(1000))
// Add a batch consecutive pending transactions for validation // Add a batch consecutive pending transactions for validation
@ -569,9 +569,9 @@ func TestTransactionPostponing(t *testing.T) {
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
var tx *types.Transaction var tx *types.Transaction
if i%2 == 0 { if i%2 == 0 {
tx = transaction(uint64(i), big.NewInt(100), key) tx = transaction(uint64(i), 100, key)
} else { } else {
tx = transaction(uint64(i), big.NewInt(500), key) tx = transaction(uint64(i), 500, key)
} }
pool.promoteTx(account, tx.Hash(), tx) pool.promoteTx(account, tx.Hash(), tx)
txns = append(txns, tx) txns = append(txns, tx)
@ -638,7 +638,7 @@ func TestTransactionGapFilling(t *testing.T) {
pool, key := setupTxPool() pool, key := setupTxPool()
defer pool.Stop() defer pool.Stop()
account, _ := deriveSender(transaction(0, big.NewInt(0), key)) account, _ := deriveSender(transaction(0, 0, key))
pool.currentState.AddBalance(account, big.NewInt(1000000)) pool.currentState.AddBalance(account, big.NewInt(1000000))
// Keep track of transaction events to ensure all executables get announced // Keep track of transaction events to ensure all executables get announced
@ -647,10 +647,10 @@ func TestTransactionGapFilling(t *testing.T) {
defer sub.Unsubscribe() defer sub.Unsubscribe()
// Create a pending and a queued transaction with a nonce-gap in between // Create a pending and a queued transaction with a nonce-gap in between
if err := pool.AddRemote(transaction(0, big.NewInt(100000), key)); err != nil { if err := pool.AddRemote(transaction(0, 100000, key)); err != nil {
t.Fatalf("failed to add pending transaction: %v", err) t.Fatalf("failed to add pending transaction: %v", err)
} }
if err := pool.AddRemote(transaction(2, big.NewInt(100000), key)); err != nil { if err := pool.AddRemote(transaction(2, 100000, key)); err != nil {
t.Fatalf("failed to add queued transaction: %v", err) t.Fatalf("failed to add queued transaction: %v", err)
} }
pending, queued := pool.Stats() pending, queued := pool.Stats()
@ -667,7 +667,7 @@ func TestTransactionGapFilling(t *testing.T) {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// Fill the nonce gap and ensure all transactions become pending // Fill the nonce gap and ensure all transactions become pending
if err := pool.AddRemote(transaction(1, big.NewInt(100000), key)); err != nil { if err := pool.AddRemote(transaction(1, 100000, key)); err != nil {
t.Fatalf("failed to add gapped transaction: %v", err) t.Fatalf("failed to add gapped transaction: %v", err)
} }
pending, queued = pool.Stats() pending, queued = pool.Stats()
@ -694,12 +694,12 @@ func TestTransactionQueueAccountLimiting(t *testing.T) {
pool, key := setupTxPool() pool, key := setupTxPool()
defer pool.Stop() defer pool.Stop()
account, _ := deriveSender(transaction(0, big.NewInt(0), key)) account, _ := deriveSender(transaction(0, 0, key))
pool.currentState.AddBalance(account, big.NewInt(1000000)) pool.currentState.AddBalance(account, big.NewInt(1000000))
// Keep queuing up transactions and make sure all above a limit are dropped // Keep queuing up transactions and make sure all above a limit are dropped
for i := uint64(1); i <= testTxPoolConfig.AccountQueue+5; i++ { for i := uint64(1); i <= testTxPoolConfig.AccountQueue+5; i++ {
if err := pool.AddRemote(transaction(i, big.NewInt(100000), key)); err != nil { if err := pool.AddRemote(transaction(i, 100000, key)); err != nil {
t.Fatalf("tx %d: failed to add transaction: %v", i, err) t.Fatalf("tx %d: failed to add transaction: %v", i, err)
} }
if len(pool.pending) != 0 { if len(pool.pending) != 0 {
@ -738,7 +738,7 @@ func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) {
// Create the pool to test the limit enforcement with // Create the pool to test the limit enforcement with
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig config := testTxPoolConfig
config.NoLocals = nolocals config.NoLocals = nolocals
@ -763,7 +763,7 @@ func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) {
key := keys[rand.Intn(len(keys)-1)] // skip adding transactions with the local account key := keys[rand.Intn(len(keys)-1)] // skip adding transactions with the local account
addr := crypto.PubkeyToAddress(key.PublicKey) addr := crypto.PubkeyToAddress(key.PublicKey)
txs = append(txs, transaction(nonces[addr]+1, big.NewInt(100000), key)) txs = append(txs, transaction(nonces[addr]+1, 100000, key))
nonces[addr]++ nonces[addr]++
} }
// Import the batch and verify that limits have been enforced // Import the batch and verify that limits have been enforced
@ -782,7 +782,7 @@ func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) {
// Generate a batch of transactions from the local account and import them // Generate a batch of transactions from the local account and import them
txs = txs[:0] txs = txs[:0]
for i := uint64(0); i < 3*config.GlobalQueue; i++ { for i := uint64(0); i < 3*config.GlobalQueue; i++ {
txs = append(txs, transaction(i+1, big.NewInt(100000), local)) txs = append(txs, transaction(i+1, 100000, local))
} }
pool.AddLocals(txs) pool.AddLocals(txs)
@ -827,7 +827,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
// Create the pool to test the non-expiration enforcement // Create the pool to test the non-expiration enforcement
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig config := testTxPoolConfig
config.Lifetime = time.Second config.Lifetime = time.Second
@ -844,10 +844,10 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
pool.currentState.AddBalance(crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000)) pool.currentState.AddBalance(crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000))
// Add the two transactions and ensure they both are queued up // Add the two transactions and ensure they both are queued up
if err := pool.AddLocal(pricedTransaction(1, big.NewInt(100000), big.NewInt(1), local)); err != nil { if err := pool.AddLocal(pricedTransaction(1, 100000, big.NewInt(1), local)); err != nil {
t.Fatalf("failed to add local transaction: %v", err) t.Fatalf("failed to add local transaction: %v", err)
} }
if err := pool.AddRemote(pricedTransaction(1, big.NewInt(100000), big.NewInt(1), remote)); err != nil { if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(1), remote)); err != nil {
t.Fatalf("failed to add remote transaction: %v", err) t.Fatalf("failed to add remote transaction: %v", err)
} }
pending, queued := pool.Stats() pending, queued := pool.Stats()
@ -891,7 +891,7 @@ func TestTransactionPendingLimiting(t *testing.T) {
pool, key := setupTxPool() pool, key := setupTxPool()
defer pool.Stop() defer pool.Stop()
account, _ := deriveSender(transaction(0, big.NewInt(0), key)) account, _ := deriveSender(transaction(0, 0, key))
pool.currentState.AddBalance(account, big.NewInt(1000000)) pool.currentState.AddBalance(account, big.NewInt(1000000))
// Keep track of transaction events to ensure all executables get announced // Keep track of transaction events to ensure all executables get announced
@ -901,7 +901,7 @@ func TestTransactionPendingLimiting(t *testing.T) {
// Keep queuing up transactions and make sure all above a limit are dropped // Keep queuing up transactions and make sure all above a limit are dropped
for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ { for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ {
if err := pool.AddRemote(transaction(i, big.NewInt(100000), key)); err != nil { if err := pool.AddRemote(transaction(i, 100000, key)); err != nil {
t.Fatalf("tx %d: failed to add transaction: %v", i, err) t.Fatalf("tx %d: failed to add transaction: %v", i, err)
} }
if pool.pending[account].Len() != int(i)+1 { if pool.pending[account].Len() != int(i)+1 {
@ -934,11 +934,11 @@ func testTransactionLimitingEquivalency(t *testing.T, origin uint64) {
pool1, key1 := setupTxPool() pool1, key1 := setupTxPool()
defer pool1.Stop() defer pool1.Stop()
account1, _ := deriveSender(transaction(0, big.NewInt(0), key1)) account1, _ := deriveSender(transaction(0, 0, key1))
pool1.currentState.AddBalance(account1, big.NewInt(1000000)) pool1.currentState.AddBalance(account1, big.NewInt(1000000))
for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ { for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ {
if err := pool1.AddRemote(transaction(origin+i, big.NewInt(100000), key1)); err != nil { if err := pool1.AddRemote(transaction(origin+i, 100000, key1)); err != nil {
t.Fatalf("tx %d: failed to add transaction: %v", i, err) t.Fatalf("tx %d: failed to add transaction: %v", i, err)
} }
} }
@ -946,12 +946,12 @@ func testTransactionLimitingEquivalency(t *testing.T, origin uint64) {
pool2, key2 := setupTxPool() pool2, key2 := setupTxPool()
defer pool2.Stop() defer pool2.Stop()
account2, _ := deriveSender(transaction(0, big.NewInt(0), key2)) account2, _ := deriveSender(transaction(0, 0, key2))
pool2.currentState.AddBalance(account2, big.NewInt(1000000)) pool2.currentState.AddBalance(account2, big.NewInt(1000000))
txns := []*types.Transaction{} txns := []*types.Transaction{}
for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ { for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ {
txns = append(txns, transaction(origin+i, big.NewInt(100000), key2)) txns = append(txns, transaction(origin+i, 100000, key2))
} }
pool2.AddRemotes(txns) pool2.AddRemotes(txns)
@ -982,7 +982,7 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) {
// Create the pool to test the limit enforcement with // Create the pool to test the limit enforcement with
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig config := testTxPoolConfig
config.GlobalSlots = config.AccountSlots * 10 config.GlobalSlots = config.AccountSlots * 10
@ -1003,7 +1003,7 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) {
for _, key := range keys { for _, key := range keys {
addr := crypto.PubkeyToAddress(key.PublicKey) addr := crypto.PubkeyToAddress(key.PublicKey)
for j := 0; j < int(config.GlobalSlots)/len(keys)*2; j++ { for j := 0; j < int(config.GlobalSlots)/len(keys)*2; j++ {
txs = append(txs, transaction(nonces[addr], big.NewInt(100000), key)) txs = append(txs, transaction(nonces[addr], 100000, key))
nonces[addr]++ nonces[addr]++
} }
} }
@ -1029,7 +1029,7 @@ func TestTransactionCapClearsFromAll(t *testing.T) {
// Create the pool to test the limit enforcement with // Create the pool to test the limit enforcement with
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig config := testTxPoolConfig
config.AccountSlots = 2 config.AccountSlots = 2
@ -1046,7 +1046,7 @@ func TestTransactionCapClearsFromAll(t *testing.T) {
txs := types.Transactions{} txs := types.Transactions{}
for j := 0; j < int(config.GlobalSlots)*2; j++ { for j := 0; j < int(config.GlobalSlots)*2; j++ {
txs = append(txs, transaction(uint64(j), big.NewInt(100000), key)) txs = append(txs, transaction(uint64(j), 100000, key))
} }
// Import the batch and verify that limits have been enforced // Import the batch and verify that limits have been enforced
pool.AddRemotes(txs) pool.AddRemotes(txs)
@ -1064,7 +1064,7 @@ func TestTransactionPendingMinimumAllowance(t *testing.T) {
// Create the pool to test the limit enforcement with // Create the pool to test the limit enforcement with
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig config := testTxPoolConfig
config.GlobalSlots = 0 config.GlobalSlots = 0
@ -1085,7 +1085,7 @@ func TestTransactionPendingMinimumAllowance(t *testing.T) {
for _, key := range keys { for _, key := range keys {
addr := crypto.PubkeyToAddress(key.PublicKey) addr := crypto.PubkeyToAddress(key.PublicKey)
for j := 0; j < int(config.AccountSlots)*2; j++ { for j := 0; j < int(config.AccountSlots)*2; j++ {
txs = append(txs, transaction(nonces[addr], big.NewInt(100000), key)) txs = append(txs, transaction(nonces[addr], 100000, key))
nonces[addr]++ nonces[addr]++
} }
} }
@ -1113,7 +1113,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
// Create the pool to test the pricing enforcement with // Create the pool to test the pricing enforcement with
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
defer pool.Stop() defer pool.Stop()
@ -1132,15 +1132,15 @@ func TestTransactionPoolRepricing(t *testing.T) {
// Generate and queue a batch of transactions, both pending and queued // Generate and queue a batch of transactions, both pending and queued
txs := types.Transactions{} txs := types.Transactions{}
txs = append(txs, pricedTransaction(0, big.NewInt(100000), big.NewInt(2), keys[0])) txs = append(txs, pricedTransaction(0, 100000, big.NewInt(2), keys[0]))
txs = append(txs, pricedTransaction(1, big.NewInt(100000), big.NewInt(1), keys[0])) txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[0]))
txs = append(txs, pricedTransaction(2, big.NewInt(100000), big.NewInt(2), keys[0])) txs = append(txs, pricedTransaction(2, 100000, big.NewInt(2), keys[0]))
txs = append(txs, pricedTransaction(1, big.NewInt(100000), big.NewInt(2), keys[1])) txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[1]))
txs = append(txs, pricedTransaction(2, big.NewInt(100000), big.NewInt(1), keys[1])) txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[1]))
txs = append(txs, pricedTransaction(3, big.NewInt(100000), big.NewInt(2), keys[1])) txs = append(txs, pricedTransaction(3, 100000, big.NewInt(2), keys[1]))
ltx := pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[2]) ltx := pricedTransaction(0, 100000, big.NewInt(1), keys[2])
// Import the batch and that both pending and queued transactions match up // Import the batch and that both pending and queued transactions match up
pool.AddRemotes(txs) pool.AddRemotes(txs)
@ -1176,10 +1176,10 @@ func TestTransactionPoolRepricing(t *testing.T) {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// Check that we can't add the old transactions back // Check that we can't add the old transactions back
if err := pool.AddRemote(pricedTransaction(1, big.NewInt(100000), big.NewInt(1), keys[0])); err != ErrUnderpriced { if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(1), keys[0])); err != ErrUnderpriced {
t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced) t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced)
} }
if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(1), keys[1])); err != ErrUnderpriced { if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(1), keys[1])); err != ErrUnderpriced {
t.Fatalf("adding underpriced queued transaction error mismatch: have %v, want %v", err, ErrUnderpriced) t.Fatalf("adding underpriced queued transaction error mismatch: have %v, want %v", err, ErrUnderpriced)
} }
if err := validateEvents(events, 0); err != nil { if err := validateEvents(events, 0); err != nil {
@ -1189,7 +1189,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// However we can add local underpriced transactions // However we can add local underpriced transactions
tx := pricedTransaction(1, big.NewInt(100000), big.NewInt(1), keys[2]) tx := pricedTransaction(1, 100000, big.NewInt(1), keys[2])
if err := pool.AddLocal(tx); err != nil { if err := pool.AddLocal(tx); err != nil {
t.Fatalf("failed to add underpriced local transaction: %v", err) t.Fatalf("failed to add underpriced local transaction: %v", err)
} }
@ -1212,7 +1212,7 @@ func TestTransactionPoolRepricingKeepsLocals(t *testing.T) {
// Create the pool to test the pricing enforcement with // Create the pool to test the pricing enforcement with
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
defer pool.Stop() defer pool.Stop()
@ -1226,12 +1226,12 @@ func TestTransactionPoolRepricingKeepsLocals(t *testing.T) {
// Create transaction (both pending and queued) with a linearly growing gasprice // Create transaction (both pending and queued) with a linearly growing gasprice
for i := uint64(0); i < 500; i++ { for i := uint64(0); i < 500; i++ {
// Add pending // Add pending
p_tx := pricedTransaction(i, big.NewInt(100000), big.NewInt(int64(i)), keys[2]) p_tx := pricedTransaction(i, 100000, big.NewInt(int64(i)), keys[2])
if err := pool.AddLocal(p_tx); err != nil { if err := pool.AddLocal(p_tx); err != nil {
t.Fatal(err) t.Fatal(err)
} }
// Add queued // Add queued
q_tx := pricedTransaction(i+501, big.NewInt(100000), big.NewInt(int64(i)), keys[2]) q_tx := pricedTransaction(i+501, 100000, big.NewInt(int64(i)), keys[2])
if err := pool.AddLocal(q_tx); err != nil { if err := pool.AddLocal(q_tx); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -1275,7 +1275,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
// Create the pool to test the pricing enforcement with // Create the pool to test the pricing enforcement with
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig config := testTxPoolConfig
config.GlobalSlots = 2 config.GlobalSlots = 2
@ -1298,12 +1298,12 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
// Generate and queue a batch of transactions, both pending and queued // Generate and queue a batch of transactions, both pending and queued
txs := types.Transactions{} txs := types.Transactions{}
txs = append(txs, pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[0])) txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0]))
txs = append(txs, pricedTransaction(1, big.NewInt(100000), big.NewInt(2), keys[0])) txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[0]))
txs = append(txs, pricedTransaction(1, big.NewInt(100000), big.NewInt(1), keys[1])) txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[1]))
ltx := pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[2]) ltx := pricedTransaction(0, 100000, big.NewInt(1), keys[2])
// Import the batch and that both pending and queued transactions match up // Import the batch and that both pending and queued transactions match up
pool.AddRemotes(txs) pool.AddRemotes(txs)
@ -1323,17 +1323,17 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// Ensure that adding an underpriced transaction on block limit fails // Ensure that adding an underpriced transaction on block limit fails
if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[1])); err != ErrUnderpriced { if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), keys[1])); err != ErrUnderpriced {
t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced) t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced)
} }
// Ensure that adding high priced transactions drops cheap ones, but not own // Ensure that adding high priced transactions drops cheap ones, but not own
if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(3), keys[1])); err != nil { if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(3), keys[1])); err != nil {
t.Fatalf("failed to add well priced transaction: %v", err) t.Fatalf("failed to add well priced transaction: %v", err)
} }
if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(4), keys[1])); err != nil { if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(4), keys[1])); err != nil {
t.Fatalf("failed to add well priced transaction: %v", err) t.Fatalf("failed to add well priced transaction: %v", err)
} }
if err := pool.AddRemote(pricedTransaction(3, big.NewInt(100000), big.NewInt(5), keys[1])); err != nil { if err := pool.AddRemote(pricedTransaction(3, 100000, big.NewInt(5), keys[1])); err != nil {
t.Fatalf("failed to add well priced transaction: %v", err) t.Fatalf("failed to add well priced transaction: %v", err)
} }
pending, queued = pool.Stats() pending, queued = pool.Stats()
@ -1350,7 +1350,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// Ensure that adding local transactions can push out even higher priced ones // Ensure that adding local transactions can push out even higher priced ones
tx := pricedTransaction(1, big.NewInt(100000), big.NewInt(0), keys[2]) tx := pricedTransaction(1, 100000, big.NewInt(0), keys[2])
if err := pool.AddLocal(tx); err != nil { if err := pool.AddLocal(tx); err != nil {
t.Fatalf("failed to add underpriced local transaction: %v", err) t.Fatalf("failed to add underpriced local transaction: %v", err)
} }
@ -1377,7 +1377,7 @@ func TestTransactionReplacement(t *testing.T) {
// Create the pool to test the pricing enforcement with // Create the pool to test the pricing enforcement with
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
defer pool.Stop() defer pool.Stop()
@ -1395,49 +1395,49 @@ func TestTransactionReplacement(t *testing.T) {
price := int64(100) price := int64(100)
threshold := (price * (100 + int64(testTxPoolConfig.PriceBump))) / 100 threshold := (price * (100 + int64(testTxPoolConfig.PriceBump))) / 100
if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(1), key)); err != nil { if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), key)); err != nil {
t.Fatalf("failed to add original cheap pending transaction: %v", err) t.Fatalf("failed to add original cheap pending transaction: %v", err)
} }
if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100001), big.NewInt(1), key)); err != ErrReplaceUnderpriced { if err := pool.AddRemote(pricedTransaction(0, 100001, big.NewInt(1), key)); err != ErrReplaceUnderpriced {
t.Fatalf("original cheap pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) t.Fatalf("original cheap pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced)
} }
if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(2), key)); err != nil { if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(2), key)); err != nil {
t.Fatalf("failed to replace original cheap pending transaction: %v", err) t.Fatalf("failed to replace original cheap pending transaction: %v", err)
} }
if err := validateEvents(events, 2); err != nil { if err := validateEvents(events, 2); err != nil {
t.Fatalf("cheap replacement event firing failed: %v", err) t.Fatalf("cheap replacement event firing failed: %v", err)
} }
if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(price), key)); err != nil { if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(price), key)); err != nil {
t.Fatalf("failed to add original proper pending transaction: %v", err) t.Fatalf("failed to add original proper pending transaction: %v", err)
} }
if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100001), big.NewInt(threshold-1), key)); err != ErrReplaceUnderpriced { if err := pool.AddRemote(pricedTransaction(0, 100001, big.NewInt(threshold-1), key)); err != ErrReplaceUnderpriced {
t.Fatalf("original proper pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) t.Fatalf("original proper pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced)
} }
if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(threshold), key)); err != nil { if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(threshold), key)); err != nil {
t.Fatalf("failed to replace original proper pending transaction: %v", err) t.Fatalf("failed to replace original proper pending transaction: %v", err)
} }
if err := validateEvents(events, 2); err != nil { if err := validateEvents(events, 2); err != nil {
t.Fatalf("proper replacement event firing failed: %v", err) t.Fatalf("proper replacement event firing failed: %v", err)
} }
// Add queued transactions, ensuring the minimum price bump is enforced for replacement (for ultra low prices too) // Add queued transactions, ensuring the minimum price bump is enforced for replacement (for ultra low prices too)
if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(1), key)); err != nil { if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(1), key)); err != nil {
t.Fatalf("failed to add original cheap queued transaction: %v", err) t.Fatalf("failed to add original cheap queued transaction: %v", err)
} }
if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100001), big.NewInt(1), key)); err != ErrReplaceUnderpriced { if err := pool.AddRemote(pricedTransaction(2, 100001, big.NewInt(1), key)); err != ErrReplaceUnderpriced {
t.Fatalf("original cheap queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) t.Fatalf("original cheap queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced)
} }
if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(2), key)); err != nil { if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(2), key)); err != nil {
t.Fatalf("failed to replace original cheap queued transaction: %v", err) t.Fatalf("failed to replace original cheap queued transaction: %v", err)
} }
if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(price), key)); err != nil { if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(price), key)); err != nil {
t.Fatalf("failed to add original proper queued transaction: %v", err) t.Fatalf("failed to add original proper queued transaction: %v", err)
} }
if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100001), big.NewInt(threshold-1), key)); err != ErrReplaceUnderpriced { if err := pool.AddRemote(pricedTransaction(2, 100001, big.NewInt(threshold-1), key)); err != ErrReplaceUnderpriced {
t.Fatalf("original proper queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) t.Fatalf("original proper queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced)
} }
if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(threshold), key)); err != nil { if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(threshold), key)); err != nil {
t.Fatalf("failed to replace original proper queued transaction: %v", err) t.Fatalf("failed to replace original proper queued transaction: %v", err)
} }
@ -1472,7 +1472,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
// Create the original pool to inject transaction into the journal // Create the original pool to inject transaction into the journal
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig config := testTxPoolConfig
config.NoLocals = nolocals config.NoLocals = nolocals
@ -1489,16 +1489,16 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
pool.currentState.AddBalance(crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000)) pool.currentState.AddBalance(crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000))
// Add three local and a remote transactions and ensure they are queued up // Add three local and a remote transactions and ensure they are queued up
if err := pool.AddLocal(pricedTransaction(0, big.NewInt(100000), big.NewInt(1), local)); err != nil { if err := pool.AddLocal(pricedTransaction(0, 100000, big.NewInt(1), local)); err != nil {
t.Fatalf("failed to add local transaction: %v", err) t.Fatalf("failed to add local transaction: %v", err)
} }
if err := pool.AddLocal(pricedTransaction(1, big.NewInt(100000), big.NewInt(1), local)); err != nil { if err := pool.AddLocal(pricedTransaction(1, 100000, big.NewInt(1), local)); err != nil {
t.Fatalf("failed to add local transaction: %v", err) t.Fatalf("failed to add local transaction: %v", err)
} }
if err := pool.AddLocal(pricedTransaction(2, big.NewInt(100000), big.NewInt(1), local)); err != nil { if err := pool.AddLocal(pricedTransaction(2, 100000, big.NewInt(1), local)); err != nil {
t.Fatalf("failed to add local transaction: %v", err) t.Fatalf("failed to add local transaction: %v", err)
} }
if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(1), remote)); err != nil { if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), remote)); err != nil {
t.Fatalf("failed to add remote transaction: %v", err) t.Fatalf("failed to add remote transaction: %v", err)
} }
pending, queued := pool.Stats() pending, queued := pool.Stats()
@ -1514,7 +1514,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
// Terminate the old pool, bump the local nonce, create a new pool and ensure relevant transaction survive // Terminate the old pool, bump the local nonce, create a new pool and ensure relevant transaction survive
pool.Stop() pool.Stop()
statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1) statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1)
blockchain = &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} blockchain = &testBlockChain{statedb, 1000000, new(event.Feed)}
pool = NewTxPool(config, params.TestChainConfig, blockchain) pool = NewTxPool(config, params.TestChainConfig, blockchain)
@ -1541,7 +1541,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
pool.Stop() pool.Stop()
statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1) statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1)
blockchain = &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} blockchain = &testBlockChain{statedb, 1000000, new(event.Feed)}
pool = NewTxPool(config, params.TestChainConfig, blockchain) pool = NewTxPool(config, params.TestChainConfig, blockchain)
pending, queued = pool.Stats() pending, queued = pool.Stats()
@ -1571,7 +1571,7 @@ func TestTransactionStatusCheck(t *testing.T) {
// Create the pool to test the status retrievals with // Create the pool to test the status retrievals with
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
defer pool.Stop() defer pool.Stop()
@ -1585,10 +1585,10 @@ func TestTransactionStatusCheck(t *testing.T) {
// Generate and queue a batch of transactions, both pending and queued // Generate and queue a batch of transactions, both pending and queued
txs := types.Transactions{} txs := types.Transactions{}
txs = append(txs, pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[0])) // Pending only txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0])) // Pending only
txs = append(txs, pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[1])) // Pending and queued txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[1])) // Pending and queued
txs = append(txs, pricedTransaction(2, big.NewInt(100000), big.NewInt(1), keys[1])) txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[1]))
txs = append(txs, pricedTransaction(2, big.NewInt(100000), big.NewInt(1), keys[2])) // Queued only txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[2])) // Queued only
// Import the transaction and ensure they are correctly added // Import the transaction and ensure they are correctly added
pool.AddRemotes(txs) pool.AddRemotes(txs)
@ -1631,11 +1631,11 @@ func benchmarkPendingDemotion(b *testing.B, size int) {
pool, key := setupTxPool() pool, key := setupTxPool()
defer pool.Stop() defer pool.Stop()
account, _ := deriveSender(transaction(0, big.NewInt(0), key)) account, _ := deriveSender(transaction(0, 0, key))
pool.currentState.AddBalance(account, big.NewInt(1000000)) pool.currentState.AddBalance(account, big.NewInt(1000000))
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
tx := transaction(uint64(i), big.NewInt(100000), key) tx := transaction(uint64(i), 100000, key)
pool.promoteTx(account, tx.Hash(), tx) pool.promoteTx(account, tx.Hash(), tx)
} }
// Benchmark the speed of pool validation // Benchmark the speed of pool validation
@ -1656,11 +1656,11 @@ func benchmarkFuturePromotion(b *testing.B, size int) {
pool, key := setupTxPool() pool, key := setupTxPool()
defer pool.Stop() defer pool.Stop()
account, _ := deriveSender(transaction(0, big.NewInt(0), key)) account, _ := deriveSender(transaction(0, 0, key))
pool.currentState.AddBalance(account, big.NewInt(1000000)) pool.currentState.AddBalance(account, big.NewInt(1000000))
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
tx := transaction(uint64(1+i), big.NewInt(100000), key) tx := transaction(uint64(1+i), 100000, key)
pool.enqueueTx(tx.Hash(), tx) pool.enqueueTx(tx.Hash(), tx)
} }
// Benchmark the speed of pool validation // Benchmark the speed of pool validation
@ -1676,12 +1676,12 @@ func BenchmarkPoolInsert(b *testing.B) {
pool, key := setupTxPool() pool, key := setupTxPool()
defer pool.Stop() defer pool.Stop()
account, _ := deriveSender(transaction(0, big.NewInt(0), key)) account, _ := deriveSender(transaction(0, 0, key))
pool.currentState.AddBalance(account, big.NewInt(1000000)) pool.currentState.AddBalance(account, big.NewInt(1000000))
txs := make(types.Transactions, b.N) txs := make(types.Transactions, b.N)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
txs[i] = transaction(uint64(i), big.NewInt(100000), key) txs[i] = transaction(uint64(i), 100000, key)
} }
// Benchmark importing the transactions into the queue // Benchmark importing the transactions into the queue
b.ResetTimer() b.ResetTimer()
@ -1700,14 +1700,14 @@ func benchmarkPoolBatchInsert(b *testing.B, size int) {
pool, key := setupTxPool() pool, key := setupTxPool()
defer pool.Stop() defer pool.Stop()
account, _ := deriveSender(transaction(0, big.NewInt(0), key)) account, _ := deriveSender(transaction(0, 0, key))
pool.currentState.AddBalance(account, big.NewInt(1000000)) pool.currentState.AddBalance(account, big.NewInt(1000000))
batches := make([]types.Transactions, b.N) batches := make([]types.Transactions, b.N)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
batches[i] = make(types.Transactions, size) batches[i] = make(types.Transactions, size)
for j := 0; j < size; j++ { for j := 0; j < size; j++ {
batches[i][j] = transaction(uint64(size*i+j), big.NewInt(100000), key) batches[i][j] = transaction(uint64(size*i+j), 100000, key)
} }
} }
// Benchmark importing the transactions into the queue // Benchmark importing the transactions into the queue

View file

@ -17,8 +17,6 @@
package core package core
import ( import (
"math/big"
"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"
@ -34,7 +32,7 @@ type Validator interface {
// ValidateState validates the given statedb and optionally the receipts and // ValidateState validates the given statedb and optionally the receipts and
// gas used. // gas used.
ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas *big.Int) error ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error
} }
// Processor is an interface for processing blocks using a given initial state. // Processor is an interface for processing blocks using a given initial state.
@ -44,5 +42,5 @@ type Validator interface {
// of gas used in the process and return an error if any of the internal rules // of gas used in the process and return an error if any of the internal rules
// failed. // failed.
type Processor interface { type Processor interface {
Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, *big.Int, error) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error)
} }

View file

@ -77,8 +77,8 @@ type Header struct {
Bloom Bloom `json:"logsBloom" gencodec:"required"` Bloom Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *big.Int `json:"difficulty" gencodec:"required"` Difficulty *big.Int `json:"difficulty" gencodec:"required"`
Number *big.Int `json:"number" gencodec:"required"` Number *big.Int `json:"number" gencodec:"required"`
GasLimit *big.Int `json:"gasLimit" gencodec:"required"` GasLimit uint64 `json:"gasLimit" gencodec:"required"`
GasUsed *big.Int `json:"gasUsed" gencodec:"required"` GasUsed uint64 `json:"gasUsed" gencodec:"required"`
Time *big.Int `json:"timestamp" gencodec:"required"` Time *big.Int `json:"timestamp" gencodec:"required"`
Extra []byte `json:"extraData" gencodec:"required"` Extra []byte `json:"extraData" gencodec:"required"`
MixDigest common.Hash `json:"mixHash" gencodec:"required"` MixDigest common.Hash `json:"mixHash" gencodec:"required"`
@ -89,8 +89,8 @@ type Header struct {
type headerMarshaling struct { type headerMarshaling struct {
Difficulty *hexutil.Big Difficulty *hexutil.Big
Number *hexutil.Big Number *hexutil.Big
GasLimit *hexutil.Big GasLimit *hexutil.Uint64
GasUsed *hexutil.Big GasUsed *hexutil.Uint64
Time *hexutil.Big Time *hexutil.Big
Extra hexutil.Bytes Extra hexutil.Bytes
Hash common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON Hash common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON
@ -243,12 +243,6 @@ func CopyHeader(h *Header) *Header {
if cpy.Number = new(big.Int); h.Number != nil { if cpy.Number = new(big.Int); h.Number != nil {
cpy.Number.Set(h.Number) cpy.Number.Set(h.Number)
} }
if cpy.GasLimit = new(big.Int); h.GasLimit != nil {
cpy.GasLimit.Set(h.GasLimit)
}
if cpy.GasUsed = new(big.Int); h.GasUsed != nil {
cpy.GasUsed.Set(h.GasUsed)
}
if len(h.Extra) > 0 { if len(h.Extra) > 0 {
cpy.Extra = make([]byte, len(h.Extra)) cpy.Extra = make([]byte, len(h.Extra))
copy(cpy.Extra, h.Extra) copy(cpy.Extra, h.Extra)
@ -302,8 +296,8 @@ func (b *Block) Transaction(hash common.Hash) *Transaction {
} }
func (b *Block) Number() *big.Int { return new(big.Int).Set(b.header.Number) } func (b *Block) Number() *big.Int { return new(big.Int).Set(b.header.Number) }
func (b *Block) GasLimit() *big.Int { return new(big.Int).Set(b.header.GasLimit) } func (b *Block) GasLimit() uint64 { return b.header.GasLimit }
func (b *Block) GasUsed() *big.Int { return new(big.Int).Set(b.header.GasUsed) } func (b *Block) GasUsed() uint64 { return b.header.GasUsed }
func (b *Block) Difficulty() *big.Int { return new(big.Int).Set(b.header.Difficulty) } func (b *Block) Difficulty() *big.Int { return new(big.Int).Set(b.header.Difficulty) }
func (b *Block) Time() *big.Int { return new(big.Int).Set(b.header.Time) } func (b *Block) Time() *big.Int { return new(big.Int).Set(b.header.Time) }

View file

@ -41,8 +41,8 @@ func TestBlockEncoding(t *testing.T) {
} }
} }
check("Difficulty", block.Difficulty(), big.NewInt(131072)) check("Difficulty", block.Difficulty(), big.NewInt(131072))
check("GasLimit", block.GasLimit(), big.NewInt(3141592)) check("GasLimit", block.GasLimit(), uint64(3141592))
check("GasUsed", block.GasUsed(), big.NewInt(21000)) check("GasUsed", block.GasUsed(), uint64(21000))
check("Coinbase", block.Coinbase(), common.HexToAddress("8888f1f195afa192cfee860698584c030f4c9db1")) check("Coinbase", block.Coinbase(), common.HexToAddress("8888f1f195afa192cfee860698584c030f4c9db1"))
check("MixDigest", block.MixDigest(), common.HexToHash("bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff498")) check("MixDigest", block.MixDigest(), common.HexToHash("bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff498"))
check("Root", block.Root(), common.HexToHash("ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017")) check("Root", block.Root(), common.HexToHash("ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017"))
@ -51,7 +51,7 @@ func TestBlockEncoding(t *testing.T) {
check("Time", block.Time(), big.NewInt(1426516743)) check("Time", block.Time(), big.NewInt(1426516743))
check("Size", block.Size(), common.StorageSize(len(blockEnc))) check("Size", block.Size(), common.StorageSize(len(blockEnc)))
tx1 := NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), big.NewInt(50000), big.NewInt(10), nil) tx1 := NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), 50000, big.NewInt(10), nil)
tx1, _ = tx1.WithSignature(HomesteadSigner{}, common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100")) tx1, _ = tx1.WithSignature(HomesteadSigner{}, common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100"))
fmt.Println(block.Transactions()[0].Hash()) fmt.Println(block.Transactions()[0].Hash())

View file

@ -22,8 +22,8 @@ func (h Header) MarshalJSON() ([]byte, error) {
Bloom Bloom `json:"logsBloom" gencodec:"required"` Bloom Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
Number *hexutil.Big `json:"number" gencodec:"required"` Number *hexutil.Big `json:"number" gencodec:"required"`
GasLimit *hexutil.Big `json:"gasLimit" gencodec:"required"` GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
GasUsed *hexutil.Big `json:"gasUsed" gencodec:"required"` GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
Time *hexutil.Big `json:"timestamp" gencodec:"required"` Time *hexutil.Big `json:"timestamp" gencodec:"required"`
Extra hexutil.Bytes `json:"extraData" gencodec:"required"` Extra hexutil.Bytes `json:"extraData" gencodec:"required"`
MixDigest common.Hash `json:"mixHash" gencodec:"required"` MixDigest common.Hash `json:"mixHash" gencodec:"required"`
@ -40,8 +40,8 @@ func (h Header) MarshalJSON() ([]byte, error) {
enc.Bloom = h.Bloom enc.Bloom = h.Bloom
enc.Difficulty = (*hexutil.Big)(h.Difficulty) enc.Difficulty = (*hexutil.Big)(h.Difficulty)
enc.Number = (*hexutil.Big)(h.Number) enc.Number = (*hexutil.Big)(h.Number)
enc.GasLimit = (*hexutil.Big)(h.GasLimit) enc.GasLimit = hexutil.Uint64(h.GasLimit)
enc.GasUsed = (*hexutil.Big)(h.GasUsed) enc.GasUsed = hexutil.Uint64(h.GasUsed)
enc.Time = (*hexutil.Big)(h.Time) enc.Time = (*hexutil.Big)(h.Time)
enc.Extra = h.Extra enc.Extra = h.Extra
enc.MixDigest = h.MixDigest enc.MixDigest = h.MixDigest
@ -61,8 +61,8 @@ func (h *Header) UnmarshalJSON(input []byte) error {
Bloom *Bloom `json:"logsBloom" gencodec:"required"` Bloom *Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
Number *hexutil.Big `json:"number" gencodec:"required"` Number *hexutil.Big `json:"number" gencodec:"required"`
GasLimit *hexutil.Big `json:"gasLimit" gencodec:"required"` GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
GasUsed *hexutil.Big `json:"gasUsed" gencodec:"required"` GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
Time *hexutil.Big `json:"timestamp" gencodec:"required"` Time *hexutil.Big `json:"timestamp" gencodec:"required"`
Extra hexutil.Bytes `json:"extraData" gencodec:"required"` Extra hexutil.Bytes `json:"extraData" gencodec:"required"`
MixDigest *common.Hash `json:"mixHash" gencodec:"required"` MixDigest *common.Hash `json:"mixHash" gencodec:"required"`
@ -111,11 +111,11 @@ func (h *Header) UnmarshalJSON(input []byte) error {
if dec.GasLimit == nil { if dec.GasLimit == nil {
return errors.New("missing required field 'gasLimit' for Header") return errors.New("missing required field 'gasLimit' for Header")
} }
h.GasLimit = (*big.Int)(dec.GasLimit) h.GasLimit = (uint64)(*dec.GasLimit)
if dec.GasUsed == nil { if dec.GasUsed == nil {
return errors.New("missing required field 'gasUsed' for Header") return errors.New("missing required field 'gasUsed' for Header")
} }
h.GasUsed = (*big.Int)(dec.GasUsed) h.GasUsed = (uint64)(*dec.GasUsed)
if dec.Time == nil { if dec.Time == nil {
return errors.New("missing required field 'timestamp' for Header") return errors.New("missing required field 'timestamp' for Header")
} }

View file

@ -5,7 +5,6 @@ package types
import ( import (
"encoding/json" "encoding/json"
"errors" "errors"
"math/big"
"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"
@ -15,22 +14,22 @@ func (r Receipt) MarshalJSON() ([]byte, error) {
type Receipt struct { type Receipt struct {
PostState hexutil.Bytes `json:"root"` PostState hexutil.Bytes `json:"root"`
Status hexutil.Uint `json:"status"` Status hexutil.Uint `json:"status"`
CumulativeGasUsed *hexutil.Big `json:"cumulativeGasUsed" gencodec:"required"` CumulativeGasUsed hexutil.Uint64 `json:"cumulativeGasUsed" gencodec:"required"`
Bloom Bloom `json:"logsBloom" gencodec:"required"` Bloom Bloom `json:"logsBloom" gencodec:"required"`
Logs []*Log `json:"logs" gencodec:"required"` Logs []*Log `json:"logs" gencodec:"required"`
TxHash common.Hash `json:"transactionHash" gencodec:"required"` TxHash common.Hash `json:"transactionHash" gencodec:"required"`
ContractAddress common.Address `json:"contractAddress"` ContractAddress common.Address `json:"contractAddress"`
GasUsed *hexutil.Big `json:"gasUsed" gencodec:"required"` GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
} }
var enc Receipt var enc Receipt
enc.PostState = r.PostState enc.PostState = r.PostState
enc.Status = hexutil.Uint(r.Status) enc.Status = hexutil.Uint(r.Status)
enc.CumulativeGasUsed = (*hexutil.Big)(r.CumulativeGasUsed) enc.CumulativeGasUsed = hexutil.Uint64(r.CumulativeGasUsed)
enc.Bloom = r.Bloom enc.Bloom = r.Bloom
enc.Logs = r.Logs enc.Logs = r.Logs
enc.TxHash = r.TxHash enc.TxHash = r.TxHash
enc.ContractAddress = r.ContractAddress enc.ContractAddress = r.ContractAddress
enc.GasUsed = (*hexutil.Big)(r.GasUsed) enc.GasUsed = hexutil.Uint64(r.GasUsed)
return json.Marshal(&enc) return json.Marshal(&enc)
} }
@ -38,12 +37,12 @@ func (r *Receipt) UnmarshalJSON(input []byte) error {
type Receipt struct { type Receipt struct {
PostState hexutil.Bytes `json:"root"` PostState hexutil.Bytes `json:"root"`
Status *hexutil.Uint `json:"status"` Status *hexutil.Uint `json:"status"`
CumulativeGasUsed *hexutil.Big `json:"cumulativeGasUsed" gencodec:"required"` CumulativeGasUsed *hexutil.Uint64 `json:"cumulativeGasUsed" gencodec:"required"`
Bloom *Bloom `json:"logsBloom" gencodec:"required"` Bloom *Bloom `json:"logsBloom" gencodec:"required"`
Logs []*Log `json:"logs" gencodec:"required"` Logs []*Log `json:"logs" gencodec:"required"`
TxHash *common.Hash `json:"transactionHash" gencodec:"required"` TxHash *common.Hash `json:"transactionHash" gencodec:"required"`
ContractAddress *common.Address `json:"contractAddress"` ContractAddress *common.Address `json:"contractAddress"`
GasUsed *hexutil.Big `json:"gasUsed" gencodec:"required"` GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
} }
var dec Receipt var dec Receipt
if err := json.Unmarshal(input, &dec); err != nil { if err := json.Unmarshal(input, &dec); err != nil {
@ -58,7 +57,7 @@ func (r *Receipt) UnmarshalJSON(input []byte) error {
if dec.CumulativeGasUsed == nil { if dec.CumulativeGasUsed == nil {
return errors.New("missing required field 'cumulativeGasUsed' for Receipt") return errors.New("missing required field 'cumulativeGasUsed' for Receipt")
} }
r.CumulativeGasUsed = (*big.Int)(dec.CumulativeGasUsed) r.CumulativeGasUsed = uint64(*dec.CumulativeGasUsed)
if dec.Bloom == nil { if dec.Bloom == nil {
return errors.New("missing required field 'logsBloom' for Receipt") return errors.New("missing required field 'logsBloom' for Receipt")
} }
@ -77,6 +76,6 @@ func (r *Receipt) UnmarshalJSON(input []byte) error {
if dec.GasUsed == nil { if dec.GasUsed == nil {
return errors.New("missing required field 'gasUsed' for Receipt") return errors.New("missing required field 'gasUsed' for Receipt")
} }
r.GasUsed = (*big.Int)(dec.GasUsed) r.GasUsed = uint64(*dec.GasUsed)
return nil return nil
} }

View file

@ -15,7 +15,7 @@ func (t txdata) MarshalJSON() ([]byte, error) {
type txdata struct { type txdata struct {
AccountNonce hexutil.Uint64 `json:"nonce" gencodec:"required"` AccountNonce hexutil.Uint64 `json:"nonce" gencodec:"required"`
Price *hexutil.Big `json:"gasPrice" gencodec:"required"` Price *hexutil.Big `json:"gasPrice" gencodec:"required"`
GasLimit *hexutil.Big `json:"gas" gencodec:"required"` GasLimit hexutil.Uint64 `json:"gas" gencodec:"required"`
Recipient *common.Address `json:"to" rlp:"nil"` Recipient *common.Address `json:"to" rlp:"nil"`
Amount *hexutil.Big `json:"value" gencodec:"required"` Amount *hexutil.Big `json:"value" gencodec:"required"`
Payload hexutil.Bytes `json:"input" gencodec:"required"` Payload hexutil.Bytes `json:"input" gencodec:"required"`
@ -27,7 +27,7 @@ func (t txdata) MarshalJSON() ([]byte, error) {
var enc txdata var enc txdata
enc.AccountNonce = hexutil.Uint64(t.AccountNonce) enc.AccountNonce = hexutil.Uint64(t.AccountNonce)
enc.Price = (*hexutil.Big)(t.Price) enc.Price = (*hexutil.Big)(t.Price)
enc.GasLimit = (*hexutil.Big)(t.GasLimit) enc.GasLimit = hexutil.Uint64(t.GasLimit)
enc.Recipient = t.Recipient enc.Recipient = t.Recipient
enc.Amount = (*hexutil.Big)(t.Amount) enc.Amount = (*hexutil.Big)(t.Amount)
enc.Payload = t.Payload enc.Payload = t.Payload
@ -42,7 +42,7 @@ func (t *txdata) UnmarshalJSON(input []byte) error {
type txdata struct { type txdata struct {
AccountNonce *hexutil.Uint64 `json:"nonce" gencodec:"required"` AccountNonce *hexutil.Uint64 `json:"nonce" gencodec:"required"`
Price *hexutil.Big `json:"gasPrice" gencodec:"required"` Price *hexutil.Big `json:"gasPrice" gencodec:"required"`
GasLimit *hexutil.Big `json:"gas" gencodec:"required"` GasLimit *hexutil.Uint64 `json:"gas" gencodec:"required"`
Recipient *common.Address `json:"to" rlp:"nil"` Recipient *common.Address `json:"to" rlp:"nil"`
Amount *hexutil.Big `json:"value" gencodec:"required"` Amount *hexutil.Big `json:"value" gencodec:"required"`
Payload hexutil.Bytes `json:"input" gencodec:"required"` Payload hexutil.Bytes `json:"input" gencodec:"required"`
@ -66,7 +66,7 @@ func (t *txdata) UnmarshalJSON(input []byte) error {
if dec.GasLimit == nil { if dec.GasLimit == nil {
return errors.New("missing required field 'gas' for txdata") return errors.New("missing required field 'gas' for txdata")
} }
t.GasLimit = (*big.Int)(dec.GasLimit) t.GasLimit = uint64(*dec.GasLimit)
if dec.Recipient != nil { if dec.Recipient != nil {
t.Recipient = dec.Recipient t.Recipient = dec.Recipient
} }

View file

@ -20,7 +20,6 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"io" "io"
"math/big"
"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"
@ -47,44 +46,44 @@ type Receipt struct {
// Consensus fields // Consensus fields
PostState []byte `json:"root"` PostState []byte `json:"root"`
Status uint `json:"status"` Status uint `json:"status"`
CumulativeGasUsed *big.Int `json:"cumulativeGasUsed" gencodec:"required"` CumulativeGasUsed uint64 `json:"cumulativeGasUsed" gencodec:"required"`
Bloom Bloom `json:"logsBloom" gencodec:"required"` Bloom Bloom `json:"logsBloom" gencodec:"required"`
Logs []*Log `json:"logs" gencodec:"required"` Logs []*Log `json:"logs" gencodec:"required"`
// Implementation fields (don't reorder!) // Implementation fields (don't reorder!)
TxHash common.Hash `json:"transactionHash" gencodec:"required"` TxHash common.Hash `json:"transactionHash" gencodec:"required"`
ContractAddress common.Address `json:"contractAddress"` ContractAddress common.Address `json:"contractAddress"`
GasUsed *big.Int `json:"gasUsed" gencodec:"required"` GasUsed uint64 `json:"gasUsed" gencodec:"required"`
} }
type receiptMarshaling struct { type receiptMarshaling struct {
PostState hexutil.Bytes PostState hexutil.Bytes
Status hexutil.Uint Status hexutil.Uint
CumulativeGasUsed *hexutil.Big CumulativeGasUsed hexutil.Uint64
GasUsed *hexutil.Big GasUsed hexutil.Uint64
} }
// receiptRLP is the consensus encoding of a receipt. // receiptRLP is the consensus encoding of a receipt.
type receiptRLP struct { type receiptRLP struct {
PostStateOrStatus []byte PostStateOrStatus []byte
CumulativeGasUsed *big.Int CumulativeGasUsed uint64
Bloom Bloom Bloom Bloom
Logs []*Log Logs []*Log
} }
type receiptStorageRLP struct { type receiptStorageRLP struct {
PostStateOrStatus []byte PostStateOrStatus []byte
CumulativeGasUsed *big.Int CumulativeGasUsed uint64
Bloom Bloom Bloom Bloom
TxHash common.Hash TxHash common.Hash
ContractAddress common.Address ContractAddress common.Address
Logs []*LogForStorage Logs []*LogForStorage
GasUsed *big.Int GasUsed uint64
} }
// NewReceipt creates a barebone transaction receipt, copying the init fields. // NewReceipt creates a barebone transaction receipt, copying the init fields.
func NewReceipt(root []byte, failed bool, cumulativeGasUsed *big.Int) *Receipt { func NewReceipt(root []byte, failed bool, cumulativeGasUsed uint64) *Receipt {
r := &Receipt{PostState: common.CopyBytes(root), CumulativeGasUsed: new(big.Int).Set(cumulativeGasUsed)} r := &Receipt{PostState: common.CopyBytes(root), CumulativeGasUsed: cumulativeGasUsed}
if failed { if failed {
r.Status = ReceiptStatusFailed r.Status = ReceiptStatusFailed
} else { } else {

View file

@ -57,7 +57,7 @@ type Transaction struct {
type txdata struct { type txdata struct {
AccountNonce uint64 `json:"nonce" gencodec:"required"` AccountNonce uint64 `json:"nonce" gencodec:"required"`
Price *big.Int `json:"gasPrice" gencodec:"required"` Price *big.Int `json:"gasPrice" gencodec:"required"`
GasLimit *big.Int `json:"gas" gencodec:"required"` GasLimit uint64 `json:"gas" gencodec:"required"`
Recipient *common.Address `json:"to" rlp:"nil"` // nil means contract creation Recipient *common.Address `json:"to" rlp:"nil"` // nil means contract creation
Amount *big.Int `json:"value" gencodec:"required"` Amount *big.Int `json:"value" gencodec:"required"`
Payload []byte `json:"input" gencodec:"required"` Payload []byte `json:"input" gencodec:"required"`
@ -74,7 +74,7 @@ type txdata struct {
type txdataMarshaling struct { type txdataMarshaling struct {
AccountNonce hexutil.Uint64 AccountNonce hexutil.Uint64
Price *hexutil.Big Price *hexutil.Big
GasLimit *hexutil.Big GasLimit hexutil.Uint64
Amount *hexutil.Big Amount *hexutil.Big
Payload hexutil.Bytes Payload hexutil.Bytes
V *hexutil.Big V *hexutil.Big
@ -82,15 +82,15 @@ type txdataMarshaling struct {
S *hexutil.Big S *hexutil.Big
} }
func NewTransaction(nonce uint64, to common.Address, amount, gasLimit, gasPrice *big.Int, data []byte) *Transaction { func NewTransaction(nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *Transaction {
return newTransaction(nonce, &to, amount, gasLimit, gasPrice, data) return newTransaction(nonce, &to, amount, gasLimit, gasPrice, data)
} }
func NewContractCreation(nonce uint64, amount, gasLimit, gasPrice *big.Int, data []byte) *Transaction { func NewContractCreation(nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *Transaction {
return newTransaction(nonce, nil, amount, gasLimit, gasPrice, data) return newTransaction(nonce, nil, amount, gasLimit, gasPrice, data)
} }
func newTransaction(nonce uint64, to *common.Address, amount, gasLimit, gasPrice *big.Int, data []byte) *Transaction { func newTransaction(nonce uint64, to *common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *Transaction {
if len(data) > 0 { if len(data) > 0 {
data = common.CopyBytes(data) data = common.CopyBytes(data)
} }
@ -99,7 +99,7 @@ func newTransaction(nonce uint64, to *common.Address, amount, gasLimit, gasPrice
Recipient: to, Recipient: to,
Payload: data, Payload: data,
Amount: new(big.Int), Amount: new(big.Int),
GasLimit: new(big.Int), GasLimit: gasLimit,
Price: new(big.Int), Price: new(big.Int),
V: new(big.Int), V: new(big.Int),
R: new(big.Int), R: new(big.Int),
@ -108,9 +108,6 @@ func newTransaction(nonce uint64, to *common.Address, amount, gasLimit, gasPrice
if amount != nil { if amount != nil {
d.Amount.Set(amount) d.Amount.Set(amount)
} }
if gasLimit != nil {
d.GasLimit.Set(gasLimit)
}
if gasPrice != nil { if gasPrice != nil {
d.Price.Set(gasPrice) d.Price.Set(gasPrice)
} }
@ -182,7 +179,7 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
} }
func (tx *Transaction) Data() []byte { return common.CopyBytes(tx.data.Payload) } func (tx *Transaction) Data() []byte { return common.CopyBytes(tx.data.Payload) }
func (tx *Transaction) Gas() *big.Int { return new(big.Int).Set(tx.data.GasLimit) } func (tx *Transaction) Gas() uint64 { return tx.data.GasLimit }
func (tx *Transaction) GasPrice() *big.Int { return new(big.Int).Set(tx.data.Price) } func (tx *Transaction) GasPrice() *big.Int { return new(big.Int).Set(tx.data.Price) }
func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.data.Amount) } func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.data.Amount) }
func (tx *Transaction) Nonce() uint64 { return tx.data.AccountNonce } func (tx *Transaction) Nonce() uint64 { return tx.data.AccountNonce }
@ -227,8 +224,8 @@ func (tx *Transaction) Size() common.StorageSize {
func (tx *Transaction) AsMessage(s Signer) (Message, error) { func (tx *Transaction) AsMessage(s Signer) (Message, error) {
msg := Message{ msg := Message{
nonce: tx.data.AccountNonce, nonce: tx.data.AccountNonce,
price: new(big.Int).Set(tx.data.Price), gasLimit: tx.data.GasLimit,
gasLimit: new(big.Int).Set(tx.data.GasLimit), gasPrice: new(big.Int).Set(tx.data.Price),
to: tx.data.Recipient, to: tx.data.Recipient,
amount: tx.data.Amount, amount: tx.data.Amount,
data: tx.data.Payload, data: tx.data.Payload,
@ -254,7 +251,7 @@ func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, e
// Cost returns amount + gasprice * gaslimit. // Cost returns amount + gasprice * gaslimit.
func (tx *Transaction) Cost() *big.Int { func (tx *Transaction) Cost() *big.Int {
total := new(big.Int).Mul(tx.data.Price, tx.data.GasLimit) total := new(big.Int).Mul(tx.data.Price, new(big.Int).SetUint64(tx.data.GasLimit))
total.Add(total, tx.data.Amount) total.Add(total, tx.data.Amount)
return total return total
} }
@ -443,19 +440,21 @@ type Message struct {
to *common.Address to *common.Address
from common.Address from common.Address
nonce uint64 nonce uint64
amount, price, gasLimit *big.Int amount *big.Int
gasLimit uint64
gasPrice *big.Int
data []byte data []byte
checkNonce bool checkNonce bool
} }
func NewMessage(from common.Address, to *common.Address, nonce uint64, amount, gasLimit, price *big.Int, data []byte, checkNonce bool) Message { func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, checkNonce bool) Message {
return Message{ return Message{
from: from, from: from,
to: to, to: to,
nonce: nonce, nonce: nonce,
amount: amount, amount: amount,
price: price,
gasLimit: gasLimit, gasLimit: gasLimit,
gasPrice: gasPrice,
data: data, data: data,
checkNonce: checkNonce, checkNonce: checkNonce,
} }
@ -463,9 +462,9 @@ func NewMessage(from common.Address, to *common.Address, nonce uint64, amount, g
func (m Message) From() common.Address { return m.from } func (m Message) From() common.Address { return m.from }
func (m Message) To() *common.Address { return m.to } func (m Message) To() *common.Address { return m.to }
func (m Message) GasPrice() *big.Int { return m.price } func (m Message) GasPrice() *big.Int { return m.gasPrice }
func (m Message) Value() *big.Int { return m.amount } func (m Message) Value() *big.Int { return m.amount }
func (m Message) Gas() *big.Int { return m.gasLimit } func (m Message) Gas() uint64 { return m.gasLimit }
func (m Message) Nonce() uint64 { return m.nonce } func (m Message) Nonce() uint64 { return m.nonce }
func (m Message) Data() []byte { return m.data } func (m Message) Data() []byte { return m.data }
func (m Message) CheckNonce() bool { return m.checkNonce } func (m Message) CheckNonce() bool { return m.checkNonce }

View file

@ -30,7 +30,7 @@ func TestEIP155Signing(t *testing.T) {
addr := crypto.PubkeyToAddress(key.PublicKey) addr := crypto.PubkeyToAddress(key.PublicKey)
signer := NewEIP155Signer(big.NewInt(18)) signer := NewEIP155Signer(big.NewInt(18))
tx, err := SignTx(NewTransaction(0, addr, new(big.Int), new(big.Int), new(big.Int), nil), signer, key) tx, err := SignTx(NewTransaction(0, addr, new(big.Int), 0, new(big.Int), nil), signer, key)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -49,7 +49,7 @@ func TestEIP155ChainId(t *testing.T) {
addr := crypto.PubkeyToAddress(key.PublicKey) addr := crypto.PubkeyToAddress(key.PublicKey)
signer := NewEIP155Signer(big.NewInt(18)) signer := NewEIP155Signer(big.NewInt(18))
tx, err := SignTx(NewTransaction(0, addr, new(big.Int), new(big.Int), new(big.Int), nil), signer, key) tx, err := SignTx(NewTransaction(0, addr, new(big.Int), 0, new(big.Int), nil), signer, key)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -61,7 +61,7 @@ func TestEIP155ChainId(t *testing.T) {
t.Error("expected chainId to be", signer.chainId, "got", tx.ChainId()) t.Error("expected chainId to be", signer.chainId, "got", tx.ChainId())
} }
tx = NewTransaction(0, addr, new(big.Int), new(big.Int), new(big.Int), nil) tx = NewTransaction(0, addr, new(big.Int), 0, new(big.Int), nil)
tx, err = SignTx(tx, HomesteadSigner{}, key) tx, err = SignTx(tx, HomesteadSigner{}, key)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -118,7 +118,7 @@ func TestEIP155SigningVitalik(t *testing.T) {
func TestChainId(t *testing.T) { func TestChainId(t *testing.T) {
key, _ := defaultTestKey() key, _ := defaultTestKey()
tx := NewTransaction(0, common.Address{}, new(big.Int), new(big.Int), new(big.Int), nil) tx := NewTransaction(0, common.Address{}, new(big.Int), 0, new(big.Int), nil)
var err error var err error
tx, err = SignTx(tx, NewEIP155Signer(big.NewInt(1)), key) tx, err = SignTx(tx, NewEIP155Signer(big.NewInt(1)), key)

View file

@ -34,7 +34,7 @@ var (
emptyTx = NewTransaction( emptyTx = NewTransaction(
0, 0,
common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"),
big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), 0, big.NewInt(0),
nil, nil,
) )
@ -42,7 +42,7 @@ var (
3, 3,
common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b"), common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b"),
big.NewInt(10), big.NewInt(10),
big.NewInt(2000), 2000,
big.NewInt(1), big.NewInt(1),
common.FromHex("5544"), common.FromHex("5544"),
).WithSignature( ).WithSignature(
@ -139,7 +139,7 @@ func TestTransactionPriceNonceSort(t *testing.T) {
for start, key := range keys { for start, key := range keys {
addr := crypto.PubkeyToAddress(key.PublicKey) addr := crypto.PubkeyToAddress(key.PublicKey)
for i := 0; i < 25; i++ { for i := 0; i < 25; i++ {
tx, _ := SignTx(NewTransaction(uint64(start+i), common.Address{}, big.NewInt(100), big.NewInt(100), big.NewInt(int64(start+i)), nil), signer, key) tx, _ := SignTx(NewTransaction(uint64(start+i), common.Address{}, big.NewInt(100), 100, big.NewInt(int64(start+i)), nil), signer, key)
groups[addr] = append(groups[addr], tx) groups[addr] = append(groups[addr], tx)
} }
} }
@ -204,9 +204,9 @@ func TestTransactionJSON(t *testing.T) {
var tx *Transaction var tx *Transaction
switch i % 2 { switch i % 2 {
case 0: case 0:
tx = NewTransaction(i, common.Address{1}, common.Big0, common.Big1, common.Big2, []byte("abcdef")) tx = NewTransaction(i, common.Address{1}, common.Big0, 1, common.Big2, []byte("abcdef"))
case 1: case 1:
tx = NewContractCreation(i, common.Big0, common.Big1, common.Big2, []byte("abcdef")) tx = NewContractCreation(i, common.Big0, 1, common.Big2, []byte("abcdef"))
} }
tx, err := SignTx(tx, signer, key) tx, err := SignTx(tx, signer, key)

View file

@ -69,7 +69,7 @@ type Context struct {
// Block information // Block information
Coinbase common.Address // Provides information for COINBASE Coinbase common.Address // Provides information for COINBASE
GasLimit *big.Int // Provides information for GASLIMIT GasLimit uint64 // Provides information for GASLIMIT
BlockNumber *big.Int // Provides information for NUMBER BlockNumber *big.Int // Provides information for NUMBER
Time *big.Int // Provides information for TIME Time *big.Int // Provides information for TIME
Difficulty *big.Int // Provides information for DIFFICULTY Difficulty *big.Int // Provides information for DIFFICULTY

View file

@ -17,8 +17,6 @@
package vm package vm
import ( import (
"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/common/math"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@ -130,7 +128,7 @@ func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, m
// 0 => non 0 // 0 => non 0
return params.SstoreSetGas, nil return params.SstoreSetGas, nil
} else if !common.EmptyHash(val) && common.EmptyHash(common.BigToHash(y)) { } else if !common.EmptyHash(val) && common.EmptyHash(common.BigToHash(y)) {
evm.StateDB.AddRefund(new(big.Int).SetUint64(params.SstoreRefundGas)) evm.StateDB.AddRefund(params.SstoreRefundGas)
return params.SstoreClearGas, nil return params.SstoreClearGas, nil
} else { } else {
@ -405,7 +403,7 @@ func gasSuicide(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack,
} }
if !evm.StateDB.HasSuicided(contract.Address()) { if !evm.StateDB.HasSuicided(contract.Address()) {
evm.StateDB.AddRefund(new(big.Int).SetUint64(params.SuicideRefundGas)) evm.StateDB.AddRefund(params.SuicideRefundGas)
} }
return gas, nil return gas, nil
} }

View file

@ -472,7 +472,7 @@ func opDifficulty(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stac
} }
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(math.U256(new(big.Int).Set(evm.GasLimit))) stack.push(math.U256(new(big.Int).SetUint64(evm.GasLimit)))
return nil, nil return nil, nil
} }

View file

@ -39,8 +39,8 @@ type StateDB interface {
SetCode(common.Address, []byte) SetCode(common.Address, []byte)
GetCodeSize(common.Address) int GetCodeSize(common.Address) int
AddRefund(*big.Int) AddRefund(uint64)
GetRefund() *big.Int GetRefund() uint64
GetState(common.Address, common.Hash) common.Hash GetState(common.Address, common.Hash) common.Hash
SetState(common.Address, common.Hash, common.Hash) SetState(common.Address, common.Hash, common.Hash)

View file

@ -100,6 +100,8 @@ type StructLogger struct {
logs []StructLog logs []StructLog
changedValues map[common.Address]Storage changedValues map[common.Address]Storage
output []byte
err error
} }
// NewStructLogger returns a new logger // NewStructLogger returns a new logger
@ -172,17 +174,19 @@ func (l *StructLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost ui
} }
func (l *StructLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error { func (l *StructLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error {
fmt.Printf("0x%x", output) l.output = output
if err != nil { l.err = err
fmt.Printf(" error: %v\n", err)
}
return nil return nil
} }
// StructLogs returns a list of captured log entries // StructLogs returns the captured log entries.
func (l *StructLogger) StructLogs() []StructLog { func (l *StructLogger) StructLogs() []StructLog { return l.logs }
return l.logs
} // Error returns the VM error captured by the trace.
func (l *StructLogger) Error() error { return l.err }
// Output returns the VM return value captured by the trace.
func (l *StructLogger) Output() []byte { return l.output }
// WriteTrace writes a formatted trace to the given writer // WriteTrace writes a formatted trace to the given writer
func WriteTrace(writer io.Writer, logs []StructLog) { func WriteTrace(writer io.Writer, logs []StructLog) {

View file

@ -55,8 +55,8 @@ func (NoopStateDB) GetCodeHash(common.Address) common.Hash
func (NoopStateDB) GetCode(common.Address) []byte { return nil } func (NoopStateDB) GetCode(common.Address) []byte { return nil }
func (NoopStateDB) SetCode(common.Address, []byte) {} func (NoopStateDB) SetCode(common.Address, []byte) {}
func (NoopStateDB) GetCodeSize(common.Address) int { return 0 } func (NoopStateDB) GetCodeSize(common.Address) int { return 0 }
func (NoopStateDB) AddRefund(*big.Int) {} func (NoopStateDB) AddRefund(uint64) {}
func (NoopStateDB) GetRefund() *big.Int { return nil } func (NoopStateDB) GetRefund() uint64 { return 0 }
func (NoopStateDB) GetState(common.Address, common.Hash) common.Hash { return common.Hash{} } func (NoopStateDB) GetState(common.Address, common.Hash) common.Hash { return common.Hash{} }
func (NoopStateDB) SetState(common.Address, common.Hash, common.Hash) {} func (NoopStateDB) SetState(common.Address, common.Hash, common.Hash) {}
func (NoopStateDB) Suicide(common.Address) bool { return false } func (NoopStateDB) Suicide(common.Address) bool { return false }

View file

@ -17,8 +17,6 @@
package runtime package runtime
import ( import (
"math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
@ -35,7 +33,7 @@ func NewEnv(cfg *Config) *vm.EVM {
BlockNumber: cfg.BlockNumber, BlockNumber: cfg.BlockNumber,
Time: cfg.Time, Time: cfg.Time,
Difficulty: cfg.Difficulty, Difficulty: cfg.Difficulty,
GasLimit: new(big.Int).SetUint64(cfg.GasLimit), GasLimit: cfg.GasLimit,
GasPrice: cfg.GasPrice, GasPrice: cfg.GasPrice,
} }

View file

@ -97,6 +97,16 @@ func toECDSA(d []byte, strict bool) (*ecdsa.PrivateKey, error) {
return nil, fmt.Errorf("invalid length, need %d bits", priv.Params().BitSize) return nil, fmt.Errorf("invalid length, need %d bits", priv.Params().BitSize)
} }
priv.D = new(big.Int).SetBytes(d) priv.D = new(big.Int).SetBytes(d)
// The priv.D must < N
if priv.D.Cmp(secp256k1_N) >= 0 {
return nil, fmt.Errorf("invalid private key, >=N")
}
// The priv.D must not be zero or negative.
if priv.D.Sign() <= 0 {
return nil, fmt.Errorf("invalid private key, zero or negative")
}
priv.PublicKey.X, priv.PublicKey.Y = priv.PublicKey.Curve.ScalarBaseMult(d) priv.PublicKey.X, priv.PublicKey.Y = priv.PublicKey.Curve.ScalarBaseMult(d)
if priv.PublicKey.X == nil { if priv.PublicKey.X == nil {
return nil, errors.New("invalid private key") return nil, errors.New("invalid private key")

View file

@ -314,7 +314,7 @@ func (prv *PrivateKey) Decrypt(rand io.Reader, c, s1, s2 []byte) (m []byte, err
switch c[0] { switch c[0] {
case 2, 3, 4: case 2, 3, 4:
rLen = ((prv.PublicKey.Curve.Params().BitSize + 7) / 4) rLen = (prv.PublicKey.Curve.Params().BitSize + 7) / 4
if len(c) < (rLen + hLen + 1) { if len(c) < (rLen + hLen + 1) {
err = ErrInvalidMessage err = ErrInvalidMessage
return return

View file

@ -204,7 +204,7 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
if err != nil { if err != nil {
// If the starting state is missing, allow some number of blocks to be reexecuted // If the starting state is missing, allow some number of blocks to be reexecuted
reexec := defaultTraceReexec reexec := defaultTraceReexec
if config.Reexec != nil { if config != nil && config.Reexec != nil {
reexec = *config.Reexec reexec = *config.Reexec
} }
// Find the most recent block that has the state available // Find the most recent block that has the state available
@ -465,7 +465,7 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
return nil, fmt.Errorf("parent %x not found", block.ParentHash()) return nil, fmt.Errorf("parent %x not found", block.ParentHash())
} }
reexec := defaultTraceReexec reexec := defaultTraceReexec
if config.Reexec != nil { if config != nil && config.Reexec != nil {
reexec = *config.Reexec reexec = *config.Reexec
} }
statedb, err := api.computeStateDB(parent, reexec) statedb, err := api.computeStateDB(parent, reexec)
@ -619,7 +619,7 @@ func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, hash common.Ha
return nil, fmt.Errorf("transaction %x not found", hash) return nil, fmt.Errorf("transaction %x not found", hash)
} }
reexec := defaultTraceReexec reexec := defaultTraceReexec
if config.Reexec != nil { if config != nil && config.Reexec != nil {
reexec = *config.Reexec reexec = *config.Reexec
} }
msg, vmctx, statedb, err := api.computeTxEnv(blockHash, int(index), reexec) msg, vmctx, statedb, err := api.computeTxEnv(blockHash, int(index), reexec)

View file

@ -83,9 +83,7 @@ func toCallArgs(msg ethereum.CallMsg) ethapi.CallArgs {
To: msg.To, To: msg.To,
From: msg.From, From: msg.From,
Data: msg.Data, Data: msg.Data,
} Gas: hexutil.Uint64(msg.Gas),
if msg.Gas != nil {
args.Gas = hexutil.Big(*msg.Gas)
} }
if msg.GasPrice != nil { if msg.GasPrice != nil {
args.GasPrice = hexutil.Big(*msg.GasPrice) args.GasPrice = hexutil.Big(*msg.GasPrice)
@ -124,9 +122,9 @@ func (b *ContractBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error)
// the backend blockchain. There is no guarantee that this is the true gas limit // the backend blockchain. There is no guarantee that this is the true gas limit
// requirement as other transactions may be added or removed by miners, but it // requirement as other transactions may be added or removed by miners, but it
// should provide a basis for setting a reasonable default. // should provide a basis for setting a reasonable default.
func (b *ContractBackend) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (*big.Int, error) { func (b *ContractBackend) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error) {
out, err := b.bcapi.EstimateGas(ctx, toCallArgs(msg)) gas, err := b.bcapi.EstimateGas(ctx, toCallArgs(msg))
return out.ToInt(), err return uint64(gas), err
} }
// SendTransaction implements bind.ContractTransactor injects the transaction // SendTransaction implements bind.ContractTransactor injects the transaction

View file

@ -118,7 +118,7 @@ func (dl *downloadTester) makeChain(n int, seed byte, parent *types.Block, paren
// If the block number is multiple of 3, send a bonus transaction to the miner // If the block number is multiple of 3, send a bonus transaction to the miner
if parent == dl.genesis && i%3 == 0 { if parent == dl.genesis && i%3 == 0 {
signer := types.MakeSigner(params.TestChainConfig, block.Number()) signer := types.MakeSigner(params.TestChainConfig, block.Number())
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), new(big.Int).SetUint64(params.TxGas), nil, nil), signer, testKey) tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, nil, nil), signer, testKey)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View file

@ -132,7 +132,10 @@ func (d *Downloader) runStateSync(s *stateSync) *stateSync {
// Send the next finished request to the current sync: // Send the next finished request to the current sync:
case deliverReqCh <- deliverReq: case deliverReqCh <- deliverReq:
finished = append(finished[:0], finished[1:]...) // Shift out the first request, but also set the emptied slot to nil for GC
copy(finished, finished[1:])
finished[len(finished)-1] = nil
finished = finished[:len(finished)-1]
// Handle incoming state packs: // Handle incoming state packs:
case pack := <-d.stateCh: case pack := <-d.stateCh:

View file

@ -52,7 +52,7 @@ func makeChain(n int, seed byte, parent *types.Block) ([]common.Hash, map[common
// If the block number is multiple of 3, send a bonus transaction to the miner // If the block number is multiple of 3, send a bonus transaction to the miner
if parent == genesis && i%3 == 0 { if parent == genesis && i%3 == 0 {
signer := types.MakeSigner(params.TestChainConfig, block.Number()) signer := types.MakeSigner(params.TestChainConfig, block.Number())
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), new(big.Int).SetUint64(params.TxGas), nil, nil), signer, testKey) tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, nil, nil), signer, testKey)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View file

@ -195,11 +195,11 @@ func TestPendingTxFilter(t *testing.T) {
api = NewPublicFilterAPI(backend, false) api = NewPublicFilterAPI(backend, false)
transactions = []*types.Transaction{ transactions = []*types.Transaction{
types.NewTransaction(0, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), new(big.Int), new(big.Int), nil), types.NewTransaction(0, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
types.NewTransaction(1, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), new(big.Int), new(big.Int), nil), types.NewTransaction(1, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
types.NewTransaction(2, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), new(big.Int), new(big.Int), nil), types.NewTransaction(2, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
types.NewTransaction(3, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), new(big.Int), new(big.Int), nil), types.NewTransaction(3, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
types.NewTransaction(4, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), new(big.Int), new(big.Int), nil), types.NewTransaction(4, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
} }
hashes []common.Hash hashes []common.Hash

View file

@ -34,7 +34,7 @@ import (
) )
func makeReceipt(addr common.Address) *types.Receipt { func makeReceipt(addr common.Address) *types.Receipt {
receipt := types.NewReceipt(nil, false, new(big.Int)) receipt := types.NewReceipt(nil, false, 0)
receipt.Logs = []*types.Log{ receipt.Logs = []*types.Log{
{Address: addr}, {Address: addr},
} }
@ -136,7 +136,7 @@ func TestFilters(t *testing.T) {
chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) { chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) {
switch i { switch i {
case 1: case 1:
receipt := types.NewReceipt(nil, false, new(big.Int)) receipt := types.NewReceipt(nil, false, 0)
receipt.Logs = []*types.Log{ receipt.Logs = []*types.Log{
{ {
Address: addr, Address: addr,
@ -145,7 +145,7 @@ func TestFilters(t *testing.T) {
} }
gen.AddUncheckedReceipt(receipt) gen.AddUncheckedReceipt(receipt)
case 2: case 2:
receipt := types.NewReceipt(nil, false, new(big.Int)) receipt := types.NewReceipt(nil, false, 0)
receipt.Logs = []*types.Log{ receipt.Logs = []*types.Log{
{ {
Address: addr, Address: addr,
@ -154,7 +154,7 @@ func TestFilters(t *testing.T) {
} }
gen.AddUncheckedReceipt(receipt) gen.AddUncheckedReceipt(receipt)
case 998: case 998:
receipt := types.NewReceipt(nil, false, new(big.Int)) receipt := types.NewReceipt(nil, false, 0)
receipt.Logs = []*types.Log{ receipt.Logs = []*types.Log{
{ {
Address: addr, Address: addr,
@ -163,7 +163,7 @@ func TestFilters(t *testing.T) {
} }
gen.AddUncheckedReceipt(receipt) gen.AddUncheckedReceipt(receipt)
case 999: case 999:
receipt := types.NewReceipt(nil, false, new(big.Int)) receipt := types.NewReceipt(nil, false, 0)
receipt.Logs = []*types.Log{ receipt.Logs = []*types.Log{
{ {
Address: addr, Address: addr,

View file

@ -394,14 +394,14 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
case query.Reverse: case query.Reverse:
// Number based traversal towards the genesis block // Number based traversal towards the genesis block
if query.Origin.Number >= query.Skip+1 { if query.Origin.Number >= query.Skip+1 {
query.Origin.Number -= (query.Skip + 1) query.Origin.Number -= query.Skip + 1
} else { } else {
unknown = true unknown = true
} }
case !query.Reverse: case !query.Reverse:
// Number based traversal towards the leaf block // Number based traversal towards the leaf block
query.Origin.Number += (query.Skip + 1) query.Origin.Number += query.Skip + 1
} }
} }
return p.SendBlockHeaders(headers) return p.SendBlockHeaders(headers)
@ -744,10 +744,10 @@ func (self *ProtocolManager) txBroadcastLoop() {
} }
} }
// EthNodeInfo represents a short summary of the Ethereum sub-protocol metadata known // NodeInfo represents a short summary of the Ethereum sub-protocol metadata
// about the host peer. // known about the host peer.
type EthNodeInfo struct { type NodeInfo struct {
Network uint64 `json:"network"` // Ethereum network ID (1=Frontier, 2=Morden, Ropsten=3) Network uint64 `json:"network"` // Ethereum network ID (1=Frontier, 2=Morden, Ropsten=3, Rinkeby=4)
Difficulty *big.Int `json:"difficulty"` // Total difficulty of the host's blockchain Difficulty *big.Int `json:"difficulty"` // Total difficulty of the host's blockchain
Genesis common.Hash `json:"genesis"` // SHA3 hash of the host's genesis block Genesis common.Hash `json:"genesis"` // SHA3 hash of the host's genesis block
Config *params.ChainConfig `json:"config"` // Chain configuration for the fork rules Config *params.ChainConfig `json:"config"` // Chain configuration for the fork rules
@ -755,9 +755,9 @@ type EthNodeInfo struct {
} }
// NodeInfo retrieves some protocol metadata about the running host node. // NodeInfo retrieves some protocol metadata about the running host node.
func (self *ProtocolManager) NodeInfo() *EthNodeInfo { func (self *ProtocolManager) NodeInfo() *NodeInfo {
currentBlock := self.blockchain.CurrentBlock() currentBlock := self.blockchain.CurrentBlock()
return &EthNodeInfo{ return &NodeInfo{
Network: self.networkId, Network: self.networkId,
Difficulty: self.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64()), Difficulty: self.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64()),
Genesis: self.blockchain.Genesis().Hash(), Genesis: self.blockchain.Genesis().Hash(),

View file

@ -37,8 +37,6 @@ import (
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
var bigTxGas = new(big.Int).SetUint64(params.TxGas)
// Tests that protocol versions and modes of operations are matched up properly. // Tests that protocol versions and modes of operations are matched up properly.
func TestProtocolCompatibility(t *testing.T) { func TestProtocolCompatibility(t *testing.T) {
// Define the compatibility chart // Define the compatibility chart
@ -315,13 +313,13 @@ func testGetNodeData(t *testing.T, protocol int) {
switch i { switch i {
case 0: case 0:
// In block 1, the test bank sends account #1 some ether. // In block 1, the test bank sends account #1 some ether.
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), bigTxGas, nil, nil), signer, testBankKey) tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey)
block.AddTx(tx) block.AddTx(tx)
case 1: case 1:
// In block 2, the test bank sends some more ether to account #1. // In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2. // acc1Addr passes it on to account #2.
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, testBankKey) tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey)
tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, acc1Key) tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key)
block.AddTx(tx1) block.AddTx(tx1)
block.AddTx(tx2) block.AddTx(tx2)
case 2: case 2:
@ -407,13 +405,13 @@ func testGetReceipt(t *testing.T, protocol int) {
switch i { switch i {
case 0: case 0:
// In block 1, the test bank sends account #1 some ether. // In block 1, the test bank sends account #1 some ether.
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), bigTxGas, nil, nil), signer, testBankKey) tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey)
block.AddTx(tx) block.AddTx(tx)
case 1: case 1:
// In block 2, the test bank sends some more ether to account #1. // In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2. // acc1Addr passes it on to account #2.
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, testBankKey) tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey)
tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, acc1Key) tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key)
block.AddTx(tx1) block.AddTx(tx1)
block.AddTx(tx2) block.AddTx(tx2)
case 2: case 2:

View file

@ -130,7 +130,7 @@ func (p *testTxPool) SubscribeTxPreEvent(ch chan<- core.TxPreEvent) event.Subscr
// newTestTransaction create a new dummy transaction. // newTestTransaction create a new dummy transaction.
func newTestTransaction(from *ecdsa.PrivateKey, nonce uint64, datasize int) *types.Transaction { func newTestTransaction(from *ecdsa.PrivateKey, nonce uint64, datasize int) *types.Transaction {
tx := types.NewTransaction(nonce, common.Address{}, big.NewInt(0), big.NewInt(100000), big.NewInt(0), make([]byte, datasize)) tx := types.NewTransaction(nonce, common.Address{}, big.NewInt(0), 100000, big.NewInt(0), make([]byte, datasize))
tx, _ = types.SignTx(tx, types.HomesteadSigner{}, from) tx, _ = types.SignTx(tx, types.HomesteadSigner{}, from)
return tx return tx
} }

View file

@ -156,7 +156,7 @@ func TestCallTracer(t *testing.T) {
BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)), BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
Time: new(big.Int).SetUint64(uint64(test.Context.Time)), Time: new(big.Int).SetUint64(uint64(test.Context.Time)),
Difficulty: (*big.Int)(test.Context.Difficulty), Difficulty: (*big.Int)(test.Context.Difficulty),
GasLimit: new(big.Int).SetUint64(uint64(test.Context.GasLimit)), GasLimit: uint64(test.Context.GasLimit),
GasPrice: tx.GasPrice(), GasPrice: tx.GasPrice(),
} }
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
@ -174,7 +174,7 @@ func TestCallTracer(t *testing.T) {
t.Fatalf("failed to prepare transaction for tracing: %v", err) t.Fatalf("failed to prepare transaction for tracing: %v", err)
} }
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas())) st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if _, _, _, _, err = st.TransitionDb(); err != nil { if _, _, _, err = st.TransitionDb(); err != nil {
t.Fatalf("failed to execute transaction: %v", err) t.Fatalf("failed to execute transaction: %v", err)
} }
// Retrieve the trace result and compare against the etalon // Retrieve the trace result and compare against the etalon

View file

@ -455,13 +455,13 @@ func (ec *Client) SuggestGasPrice(ctx context.Context) (*big.Int, error) {
// the current pending state of the backend blockchain. There is no guarantee that this is // the current pending state of the backend blockchain. There is no guarantee that this is
// the true gas limit requirement as other transactions may be added or removed by miners, // the true gas limit requirement as other transactions may be added or removed by miners,
// but it should provide a basis for setting a reasonable default. // but it should provide a basis for setting a reasonable default.
func (ec *Client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (*big.Int, error) { func (ec *Client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error) {
var hex hexutil.Big var hex hexutil.Uint64
err := ec.c.CallContext(ctx, &hex, "eth_estimateGas", toCallArg(msg)) err := ec.c.CallContext(ctx, &hex, "eth_estimateGas", toCallArg(msg))
if err != nil { if err != nil {
return nil, err return 0, err
} }
return (*big.Int)(&hex), nil return uint64(hex), nil
} }
// SendTransaction injects a signed transaction into the pending pool for execution. // SendTransaction injects a signed transaction into the pending pool for execution.
@ -487,8 +487,8 @@ func toCallArg(msg ethereum.CallMsg) interface{} {
if msg.Value != nil { if msg.Value != nil {
arg["value"] = (*hexutil.Big)(msg.Value) arg["value"] = (*hexutil.Big)(msg.Value)
} }
if msg.Gas != nil { if msg.Gas != 0 {
arg["gas"] = (*hexutil.Big)(msg.Gas) arg["gas"] = hexutil.Uint64(msg.Gas)
} }
if msg.GasPrice != nil { if msg.GasPrice != nil {
arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice) arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice)

View file

@ -374,10 +374,10 @@ func (s *Service) login(conn *websocket.Conn) error {
var network, protocol string var network, protocol string
if info := infos.Protocols["eth"]; info != nil { if info := infos.Protocols["eth"]; info != nil {
network = fmt.Sprintf("%d", info.(*eth.EthNodeInfo).Network) network = fmt.Sprintf("%d", info.(*eth.NodeInfo).Network)
protocol = fmt.Sprintf("eth/%d", eth.ProtocolVersions[0]) protocol = fmt.Sprintf("eth/%d", eth.ProtocolVersions[0])
} else { } else {
network = fmt.Sprintf("%d", infos.Protocols["les"].(*eth.EthNodeInfo).Network) network = fmt.Sprintf("%d", infos.Protocols["les"].(*les.NodeInfo).Network)
protocol = fmt.Sprintf("les/%d", les.ClientProtocolVersions[0]) protocol = fmt.Sprintf("les/%d", les.ClientProtocolVersions[0])
} }
auth := &authMsg{ auth := &authMsg{
@ -473,8 +473,8 @@ type blockStats struct {
ParentHash common.Hash `json:"parentHash"` ParentHash common.Hash `json:"parentHash"`
Timestamp *big.Int `json:"timestamp"` Timestamp *big.Int `json:"timestamp"`
Miner common.Address `json:"miner"` Miner common.Address `json:"miner"`
GasUsed *big.Int `json:"gasUsed"` GasUsed uint64 `json:"gasUsed"`
GasLimit *big.Int `json:"gasLimit"` GasLimit uint64 `json:"gasLimit"`
Diff string `json:"difficulty"` Diff string `json:"difficulty"`
TotalDiff string `json:"totalDifficulty"` TotalDiff string `json:"totalDifficulty"`
Txs []txStats `json:"transactions"` Txs []txStats `json:"transactions"`
@ -559,8 +559,8 @@ func (s *Service) assembleBlockStats(block *types.Block) *blockStats {
ParentHash: header.ParentHash, ParentHash: header.ParentHash,
Timestamp: header.Time, Timestamp: header.Time,
Miner: author, Miner: author,
GasUsed: new(big.Int).Set(header.GasUsed), GasUsed: header.GasUsed,
GasLimit: new(big.Int).Set(header.GasLimit), GasLimit: header.GasLimit,
Diff: header.Difficulty.String(), Diff: header.Difficulty.String(),
TotalDiff: td.String(), TotalDiff: td.String(),
Txs: txs, Txs: txs,

View file

@ -115,7 +115,7 @@ type ChainSyncReader interface {
type CallMsg struct { type CallMsg struct {
From common.Address // the sender of the 'transaction' From common.Address // the sender of the 'transaction'
To *common.Address // the destination contract (nil for contract creation) To *common.Address // the destination contract (nil for contract creation)
Gas *big.Int // if nil, the call executes with near-infinite gas Gas uint64 // if 0, the call executes with near-infinite gas
GasPrice *big.Int // wei <-> gas exchange ratio GasPrice *big.Int // wei <-> gas exchange ratio
Value *big.Int // amount of wei sent along with the call Value *big.Int // amount of wei sent along with the call
Data []byte // input data, usually an ABI-encoded contract method invocation Data []byte // input data, usually an ABI-encoded contract method invocation
@ -200,7 +200,7 @@ type PendingContractCaller interface {
// true gas limit requirement as other transactions may be added or removed by miners, but // true gas limit requirement as other transactions may be added or removed by miners, but
// it should provide a basis for setting a reasonable default. // it should provide a basis for setting a reasonable default.
type GasEstimator interface { type GasEstimator interface {
EstimateGas(ctx context.Context, call CallMsg) (usedGas *big.Int, err error) EstimateGas(ctx context.Context, call CallMsg) (uint64, error)
} }
// A PendingStateEventer provides access to real time notifications about changes to the // A PendingStateEventer provides access to real time notifications about changes to the

View file

@ -45,7 +45,6 @@ import (
) )
const ( const (
defaultGas = 90000
defaultGasPrice = 50 * params.Shannon defaultGasPrice = 50 * params.Shannon
) )
@ -575,18 +574,18 @@ func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.A
type CallArgs struct { type CallArgs struct {
From common.Address `json:"from"` From common.Address `json:"from"`
To *common.Address `json:"to"` To *common.Address `json:"to"`
Gas hexutil.Big `json:"gas"` Gas hexutil.Uint64 `json:"gas"`
GasPrice hexutil.Big `json:"gasPrice"` GasPrice hexutil.Big `json:"gasPrice"`
Value hexutil.Big `json:"value"` Value hexutil.Big `json:"value"`
Data hexutil.Bytes `json:"data"` Data hexutil.Bytes `json:"data"`
} }
func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config) ([]byte, *big.Int, bool, error) { func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config) ([]byte, uint64, bool, error) {
defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now())
state, header, err := s.b.StateAndHeaderByNumber(ctx, blockNr) state, header, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
if state == nil || err != nil { if state == nil || err != nil {
return nil, common.Big0, false, err return nil, 0, false, err
} }
// Set sender address or use a default if none specified // Set sender address or use a default if none specified
addr := args.From addr := args.From
@ -598,9 +597,9 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
} }
} }
// Set default gas & gas price if none were set // Set default gas & gas price if none were set
gas, gasPrice := args.Gas.ToInt(), args.GasPrice.ToInt() gas, gasPrice := uint64(args.Gas), args.GasPrice.ToInt()
if gas.Sign() == 0 { if gas == 0 {
gas = big.NewInt(50000000) gas = 50000000
} }
if gasPrice.Sign() == 0 { if gasPrice.Sign() == 0 {
gasPrice = new(big.Int).SetUint64(defaultGasPrice) gasPrice = new(big.Int).SetUint64(defaultGasPrice)
@ -624,7 +623,7 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
// Get a new instance of the EVM. // Get a new instance of the EVM.
evm, vmError, err := s.b.GetEVM(ctx, msg, state, header, vmCfg) evm, vmError, err := s.b.GetEVM(ctx, msg, state, header, vmCfg)
if err != nil { if err != nil {
return nil, common.Big0, false, err return nil, 0, false, err
} }
// Wait for the context to be done and cancel the evm. Even if the // Wait for the context to be done and cancel the evm. Even if the
// EVM has finished, cancelling may be done (repeatedly) // EVM has finished, cancelling may be done (repeatedly)
@ -635,10 +634,10 @@ 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(math.MaxBig256) gp := new(core.GasPool).AddGas(math.MaxUint64)
res, gas, failed, err := core.ApplyMessage(evm, msg, gp) res, gas, failed, err := core.ApplyMessage(evm, msg, gp)
if err := vmError(); err != nil { if err := vmError(); err != nil {
return nil, common.Big0, false, err return nil, 0, false, err
} }
return res, gas, failed, err return res, gas, failed, err
} }
@ -652,28 +651,29 @@ func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr r
// EstimateGas returns an estimate of the amount of gas needed to execute the // EstimateGas returns an estimate of the amount of gas needed to execute the
// given transaction against the current pending block. // given transaction against the current pending block.
func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (*hexutil.Big, error) { func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (hexutil.Uint64, error) {
// Determine the lowest and highest possible gas limits to binary search in between // Binary search the gas requirement, as it may be higher than the amount used
var ( var (
lo uint64 = params.TxGas - 1 lo uint64 = params.TxGas - 1
hi uint64 hi uint64
cap uint64 cap uint64
) )
if (*big.Int)(&args.Gas).Uint64() >= params.TxGas { if uint64(args.Gas) >= params.TxGas {
hi = (*big.Int)(&args.Gas).Uint64() hi = uint64(args.Gas)
} else { } else {
// Retrieve the current pending block to act as the gas ceiling // Retrieve the current pending block to act as the gas ceiling
block, err := s.b.BlockByNumber(ctx, rpc.PendingBlockNumber) block, err := s.b.BlockByNumber(ctx, rpc.PendingBlockNumber)
if err != nil { if err != nil {
return nil, err return 0, err
} }
hi = block.GasLimit().Uint64() hi = block.GasLimit()
} }
cap = hi cap = hi
// Create a helper to check if a gas allowance results in an executable transaction // Create a helper to check if a gas allowance results in an executable transaction
executable := func(gas uint64) bool { executable := func(gas uint64) bool {
(*big.Int)(&args.Gas).SetUint64(gas) args.Gas = hexutil.Uint64(gas)
_, _, failed, err := s.doCall(ctx, args, rpc.PendingBlockNumber, vm.Config{}) _, _, failed, err := s.doCall(ctx, args, rpc.PendingBlockNumber, vm.Config{})
if err != nil || failed { if err != nil || failed {
return false return false
@ -692,17 +692,17 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (*
// Reject the transaction as invalid if it still fails at the highest allowance // Reject the transaction as invalid if it still fails at the highest allowance
if hi == cap { if hi == cap {
if !executable(hi) { if !executable(hi) {
return nil, fmt.Errorf("gas required exceeds allowance or always failing transaction") return 0, fmt.Errorf("gas required exceeds allowance or always failing transaction")
} }
} }
return (*hexutil.Big)(new(big.Int).SetUint64(hi)), nil return hexutil.Uint64(hi), nil
} }
// ExecutionResult groups all structured logs emitted by the EVM // ExecutionResult groups all structured logs emitted by the EVM
// while replaying a transaction in debug mode as well as transaction // while replaying a transaction in debug mode as well as transaction
// execution status, the amount of gas used and the return value // execution status, the amount of gas used and the return value
type ExecutionResult struct { type ExecutionResult struct {
Gas *big.Int `json:"gas"` Gas uint64 `json:"gas"`
Failed bool `json:"failed"` Failed bool `json:"failed"`
ReturnValue string `json:"returnValue"` ReturnValue string `json:"returnValue"`
StructLogs []StructLogRes `json:"structLogs"` StructLogs []StructLogRes `json:"structLogs"`
@ -778,8 +778,8 @@ func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx
"totalDifficulty": (*hexutil.Big)(s.b.GetTd(b.Hash())), "totalDifficulty": (*hexutil.Big)(s.b.GetTd(b.Hash())),
"extraData": hexutil.Bytes(head.Extra), "extraData": hexutil.Bytes(head.Extra),
"size": hexutil.Uint64(uint64(b.Size().Int64())), "size": hexutil.Uint64(uint64(b.Size().Int64())),
"gasLimit": (*hexutil.Big)(head.GasLimit), "gasLimit": hexutil.Uint64(head.GasLimit),
"gasUsed": (*hexutil.Big)(head.GasUsed), "gasUsed": hexutil.Uint64(head.GasUsed),
"timestamp": (*hexutil.Big)(head.Time), "timestamp": (*hexutil.Big)(head.Time),
"transactionsRoot": head.TxHash, "transactionsRoot": head.TxHash,
"receiptsRoot": head.ReceiptHash, "receiptsRoot": head.ReceiptHash,
@ -822,7 +822,7 @@ type RPCTransaction struct {
BlockHash common.Hash `json:"blockHash"` BlockHash common.Hash `json:"blockHash"`
BlockNumber *hexutil.Big `json:"blockNumber"` BlockNumber *hexutil.Big `json:"blockNumber"`
From common.Address `json:"from"` From common.Address `json:"from"`
Gas *hexutil.Big `json:"gas"` Gas hexutil.Uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"` GasPrice *hexutil.Big `json:"gasPrice"`
Hash common.Hash `json:"hash"` Hash common.Hash `json:"hash"`
Input hexutil.Bytes `json:"input"` Input hexutil.Bytes `json:"input"`
@ -847,7 +847,7 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
result := &RPCTransaction{ result := &RPCTransaction{
From: from, From: from,
Gas: (*hexutil.Big)(tx.Gas()), Gas: hexutil.Uint64(tx.Gas()),
GasPrice: (*hexutil.Big)(tx.GasPrice()), GasPrice: (*hexutil.Big)(tx.GasPrice()),
Hash: tx.Hash(), Hash: tx.Hash(),
Input: hexutil.Bytes(tx.Data()), Input: hexutil.Bytes(tx.Data()),
@ -1024,8 +1024,8 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(hash common.Hash) (map[
"transactionIndex": hexutil.Uint64(index), "transactionIndex": hexutil.Uint64(index),
"from": from, "from": from,
"to": tx.To(), "to": tx.To(),
"gasUsed": (*hexutil.Big)(receipt.GasUsed), "gasUsed": hexutil.Uint64(receipt.GasUsed),
"cumulativeGasUsed": (*hexutil.Big)(receipt.CumulativeGasUsed), "cumulativeGasUsed": hexutil.Uint64(receipt.CumulativeGasUsed),
"contractAddress": nil, "contractAddress": nil,
"logs": receipt.Logs, "logs": receipt.Logs,
"logsBloom": receipt.Bloom, "logsBloom": receipt.Bloom,
@ -1068,7 +1068,7 @@ func (s *PublicTransactionPoolAPI) sign(addr common.Address, tx *types.Transacti
type SendTxArgs struct { type SendTxArgs struct {
From common.Address `json:"from"` From common.Address `json:"from"`
To *common.Address `json:"to"` To *common.Address `json:"to"`
Gas *hexutil.Big `json:"gas"` Gas *hexutil.Uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"` GasPrice *hexutil.Big `json:"gasPrice"`
Value *hexutil.Big `json:"value"` Value *hexutil.Big `json:"value"`
Nonce *hexutil.Uint64 `json:"nonce"` Nonce *hexutil.Uint64 `json:"nonce"`
@ -1081,7 +1081,8 @@ type SendTxArgs struct {
// setDefaults is a helper function that fills in default values for unspecified tx fields. // setDefaults is a helper function that fills in default values for unspecified tx fields.
func (args *SendTxArgs) setDefaults(ctx context.Context, b Backend) error { func (args *SendTxArgs) setDefaults(ctx context.Context, b Backend) error {
if args.Gas == nil { if args.Gas == nil {
args.Gas = (*hexutil.Big)(big.NewInt(defaultGas)) args.Gas = new(hexutil.Uint64)
*(*uint64)(args.Gas) = 90000
} }
if args.GasPrice == nil { if args.GasPrice == nil {
price, err := b.SuggestPrice(ctx) price, err := b.SuggestPrice(ctx)
@ -1114,9 +1115,9 @@ func (args *SendTxArgs) toTransaction() *types.Transaction {
input = *args.Input input = *args.Input
} }
if args.To == nil { if args.To == nil {
return types.NewContractCreation(uint64(*args.Nonce), (*big.Int)(args.Value), (*big.Int)(args.Gas), (*big.Int)(args.GasPrice), input) return types.NewContractCreation(uint64(*args.Nonce), (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input)
} }
return types.NewTransaction(uint64(*args.Nonce), *args.To, (*big.Int)(args.Value), (*big.Int)(args.Gas), (*big.Int)(args.GasPrice), input) return types.NewTransaction(uint64(*args.Nonce), *args.To, (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input)
} }
// submitTransaction is a helper function that submits tx to txPool and logs a message. // submitTransaction is a helper function that submits tx to txPool and logs a message.
@ -1264,7 +1265,7 @@ func (s *PublicTransactionPoolAPI) PendingTransactions() ([]*RPCTransaction, err
// Resend accepts an existing transaction and a new gas price and limit. It will remove // Resend accepts an existing transaction and a new gas price and limit. It will remove
// the given transaction from the pool and reinsert it with the new gas price and limit. // the given transaction from the pool and reinsert it with the new gas price and limit.
func (s *PublicTransactionPoolAPI) Resend(ctx context.Context, sendArgs SendTxArgs, gasPrice, gasLimit *hexutil.Big) (common.Hash, error) { func (s *PublicTransactionPoolAPI) Resend(ctx context.Context, sendArgs SendTxArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error) {
if sendArgs.Nonce == nil { if sendArgs.Nonce == nil {
return common.Hash{}, fmt.Errorf("missing transaction nonce in transaction spec") return common.Hash{}, fmt.Errorf("missing transaction nonce in transaction spec")
} }

View file

@ -37,13 +37,14 @@ import (
// Backend interface provides the common API services (that are provided by // Backend interface provides the common API services (that are provided by
// both full and light clients) with access to necessary functions. // both full and light clients) with access to necessary functions.
type Backend interface { type Backend interface {
// general Ethereum API // General Ethereum API
Downloader() *downloader.Downloader Downloader() *downloader.Downloader
ProtocolVersion() int ProtocolVersion() int
SuggestPrice(ctx context.Context) (*big.Int, error) SuggestPrice(ctx context.Context) (*big.Int, error)
ChainDb() ethdb.Database ChainDb() ethdb.Database
EventMux() *event.TypeMux EventMux() *event.TypeMux
AccountManager() *accounts.Manager AccountManager() *accounts.Manager
// BlockChain API // BlockChain API
SetHead(number uint64) SetHead(number uint64)
HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error)

View file

@ -32,7 +32,6 @@ import (
"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"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
@ -73,6 +72,7 @@ func errResp(code errCode, format string, v ...interface{}) error {
} }
type BlockChain interface { type BlockChain interface {
Config() *params.ChainConfig
HasHeader(hash common.Hash, number uint64) bool HasHeader(hash common.Hash, number uint64) bool
GetHeader(hash common.Hash, number uint64) *types.Header GetHeader(hash common.Hash, number uint64) *types.Header
GetHeaderByHash(hash common.Hash) *types.Header GetHeaderByHash(hash common.Hash) *types.Header
@ -454,14 +454,14 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
case query.Reverse: case query.Reverse:
// Number based traversal towards the genesis block // Number based traversal towards the genesis block
if query.Origin.Number >= query.Skip+1 { if query.Origin.Number >= query.Skip+1 {
query.Origin.Number -= (query.Skip + 1) query.Origin.Number -= query.Skip + 1
} else { } else {
unknown = true unknown = true
} }
case !query.Reverse: case !query.Reverse:
// Number based traversal towards the leaf block // Number based traversal towards the leaf block
query.Origin.Number += (query.Skip + 1) query.Origin.Number += query.Skip + 1
} }
} }
@ -1123,12 +1123,23 @@ func (pm *ProtocolManager) txStatus(hashes []common.Hash) []txStatus {
return stats return stats
} }
// NodeInfo represents a short summary of the Ethereum sub-protocol metadata
// known about the host peer.
type NodeInfo struct {
Network uint64 `json:"network"` // Ethereum network ID (1=Frontier, 2=Morden, Ropsten=3, Rinkeby=4)
Difficulty *big.Int `json:"difficulty"` // Total difficulty of the host's blockchain
Genesis common.Hash `json:"genesis"` // SHA3 hash of the host's genesis block
Config *params.ChainConfig `json:"config"` // Chain configuration for the fork rules
Head common.Hash `json:"head"` // SHA3 hash of the host's best owned block
}
// NodeInfo retrieves some protocol metadata about the running host node. // NodeInfo retrieves some protocol metadata about the running host node.
func (self *ProtocolManager) NodeInfo() *eth.EthNodeInfo { func (self *ProtocolManager) NodeInfo() *NodeInfo {
return &eth.EthNodeInfo{ return &NodeInfo{
Network: self.networkId, Network: self.networkId,
Difficulty: self.blockchain.GetTdByHash(self.blockchain.LastBlockHash()), Difficulty: self.blockchain.GetTdByHash(self.blockchain.LastBlockHash()),
Genesis: self.blockchain.Genesis().Hash(), Genesis: self.blockchain.Genesis().Hash(),
Config: self.blockchain.Config(),
Head: self.blockchain.LastBlockHash(), Head: self.blockchain.LastBlockHash(),
} }
} }

View file

@ -443,16 +443,16 @@ func TestTransactionStatusLes2(t *testing.T) {
signer := types.HomesteadSigner{} signer := types.HomesteadSigner{}
// test error status by sending an underpriced transaction // test error status by sending an underpriced transaction
tx0, _ := types.SignTx(types.NewTransaction(0, acc1Addr, big.NewInt(10000), bigTxGas, nil, nil), signer, testBankKey) tx0, _ := types.SignTx(types.NewTransaction(0, acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey)
test(tx0, true, txStatus{Status: core.TxStatusUnknown, Error: core.ErrUnderpriced}) test(tx0, true, txStatus{Status: core.TxStatusUnknown, Error: core.ErrUnderpriced})
tx1, _ := types.SignTx(types.NewTransaction(0, acc1Addr, big.NewInt(10000), bigTxGas, big.NewInt(100000000000), nil), signer, testBankKey) tx1, _ := types.SignTx(types.NewTransaction(0, acc1Addr, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, testBankKey)
test(tx1, false, txStatus{Status: core.TxStatusUnknown}) // query before sending, should be unknown test(tx1, false, txStatus{Status: core.TxStatusUnknown}) // query before sending, should be unknown
test(tx1, true, txStatus{Status: core.TxStatusPending}) // send valid processable tx, should return pending test(tx1, true, txStatus{Status: core.TxStatusPending}) // send valid processable tx, should return pending
test(tx1, true, txStatus{Status: core.TxStatusPending}) // adding it again should not return an error test(tx1, true, txStatus{Status: core.TxStatusPending}) // adding it again should not return an error
tx2, _ := types.SignTx(types.NewTransaction(1, acc1Addr, big.NewInt(10000), bigTxGas, big.NewInt(100000000000), nil), signer, testBankKey) tx2, _ := types.SignTx(types.NewTransaction(1, acc1Addr, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, testBankKey)
tx3, _ := types.SignTx(types.NewTransaction(2, acc1Addr, big.NewInt(10000), bigTxGas, big.NewInt(100000000000), nil), signer, testBankKey) tx3, _ := types.SignTx(types.NewTransaction(2, acc1Addr, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, testBankKey)
// send transactions in the wrong order, tx3 should be queued // send transactions in the wrong order, tx3 should be queued
test(tx3, true, txStatus{Status: core.TxStatusQueued}) test(tx3, true, txStatus{Status: core.TxStatusQueued})
test(tx2, true, txStatus{Status: core.TxStatusPending}) test(tx2, true, txStatus{Status: core.TxStatusPending})

View file

@ -56,8 +56,6 @@ var (
testContractDeployed = uint64(2) testContractDeployed = uint64(2)
testBufLimit = uint64(100) testBufLimit = uint64(100)
bigTxGas = new(big.Int).SetUint64(params.TxGas)
) )
/* /*
@ -81,17 +79,17 @@ func testChainGen(i int, block *core.BlockGen) {
switch i { switch i {
case 0: case 0:
// In block 1, the test bank sends account #1 some ether. // In block 1, the test bank sends account #1 some ether.
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), bigTxGas, nil, nil), signer, testBankKey) tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey)
block.AddTx(tx) block.AddTx(tx)
case 1: case 1:
// In block 2, the test bank sends some more ether to account #1. // In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2. // acc1Addr passes it on to account #2.
// acc1Addr creates a test contract. // acc1Addr creates a test contract.
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, testBankKey) tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey)
nonce := block.TxNonce(acc1Addr) nonce := block.TxNonce(acc1Addr)
tx2, _ := types.SignTx(types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, acc1Key) tx2, _ := types.SignTx(types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key)
nonce++ nonce++
tx3, _ := types.SignTx(types.NewContractCreation(nonce, big.NewInt(0), big.NewInt(200000), big.NewInt(0), testContractCode), signer, acc1Key) tx3, _ := types.SignTx(types.NewContractCreation(nonce, big.NewInt(0), 200000, big.NewInt(0), testContractCode), signer, acc1Key)
testContractAddr = crypto.CreateAddress(acc1Addr, nonce) testContractAddr = crypto.CreateAddress(acc1Addr, nonce)
block.AddTx(tx1) block.AddTx(tx1)
block.AddTx(tx2) block.AddTx(tx2)
@ -101,7 +99,7 @@ func testChainGen(i int, block *core.BlockGen) {
block.SetCoinbase(acc2Addr) block.SetCoinbase(acc2Addr)
block.SetExtra([]byte("yeehaw")) block.SetExtra([]byte("yeehaw"))
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001") data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001")
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data), signer, testBankKey) tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), 100000, nil, data), signer, testBankKey)
block.AddTx(tx) block.AddTx(tx)
case 3: case 3:
// Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data). // Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data).
@ -112,7 +110,7 @@ func testChainGen(i int, block *core.BlockGen) {
b3.Extra = []byte("foo") b3.Extra = []byte("foo")
block.AddUncle(b3) block.AddUncle(b3)
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002") data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002")
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data), signer, testBankKey) tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), 100000, nil, data), signer, testBankKey)
block.AddTx(tx) block.AddTx(tx)
} }
} }

View file

@ -129,13 +129,13 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
from := statedb.GetOrNewStateObject(testBankAddress) from := statedb.GetOrNewStateObject(testBankAddress)
from.SetBalance(math.MaxBig256) 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), 100000, new(big.Int), data, false)}
context := core.NewEVMContext(msg, header, bc, nil) context := core.NewEVMContext(msg, header, bc, nil)
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(math.MaxBig256) gp := new(core.GasPool).AddGas(math.MaxUint64)
ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp) ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp)
res = append(res, ret...) res = append(res, ret...)
} }
@ -143,10 +143,10 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
header := lc.GetHeaderByHash(bhash) header := lc.GetHeaderByHash(bhash)
state := light.NewState(ctx, header, lc.Odr()) state := light.NewState(ctx, header, lc.Odr())
state.SetBalance(testBankAddress, math.MaxBig256) state.SetBalance(testBankAddress, math.MaxBig256)
msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), big.NewInt(100000), new(big.Int), data, false)} msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false)}
context := core.NewEVMContext(msg, header, lc, nil) context := core.NewEVMContext(msg, header, lc, nil)
vmenv := vm.NewEVM(context, state, config, vm.Config{}) vmenv := vm.NewEVM(context, state, config, vm.Config{})
gp := new(core.GasPool).AddGas(math.MaxBig256) gp := new(core.GasPool).AddGas(math.MaxUint64)
ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp) ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp)
if state.Error() == nil { if state.Error() == nil {
res = append(res, ret...) res = append(res, ret...)

View file

@ -618,7 +618,7 @@ func (e *knownEntry) Weight() int64 {
if e.state != psNotConnected || !e.known || e.delayedRetry { if e.state != psNotConnected || !e.known || e.delayedRetry {
return 0 return 0
} }
return int64(1000000000 * e.connectStats.recentAvg() * math.Exp(-float64(e.lastConnected.fails)*failDropLn-e.responseStats.recentAvg()/float64(responseScoreTC)-e.delayStats.recentAvg()/float64(delayScoreTC)) * math.Pow((1-e.timeoutStats.recentAvg()), timeoutPow)) return int64(1000000000 * e.connectStats.recentAvg() * math.Exp(-float64(e.lastConnected.fails)*failDropLn-e.responseStats.recentAvg()/float64(responseScoreTC)-e.delayStats.recentAvg()/float64(delayScoreTC)) * math.Pow(1-e.timeoutStats.recentAvg(), timeoutPow))
} }
// poolEntryAddress is a separate object because currently it is necessary to remember // poolEntryAddress is a separate object because currently it is necessary to remember

View file

@ -169,7 +169,7 @@ func (bc *LightChain) SetHead(head uint64) {
} }
// GasLimit returns the gas limit of the current HEAD block. // GasLimit returns the gas limit of the current HEAD block.
func (self *LightChain) GasLimit() *big.Int { func (self *LightChain) GasLimit() uint64 {
self.mu.RLock() self.mu.RLock()
defer self.mu.RUnlock() defer self.mu.RUnlock()
@ -457,6 +457,9 @@ func (self *LightChain) GetHeaderByNumberOdr(ctx context.Context, number uint64)
return GetHeaderByNumber(ctx, self.odr, number) return GetHeaderByNumber(ctx, self.odr, number)
} }
// Config retrieves the header chain's chain configuration.
func (self *LightChain) Config() *params.ChainConfig { return self.hc.Config() }
func (self *LightChain) SyncCht(ctx context.Context) bool { func (self *LightChain) SyncCht(ctx context.Context) bool {
if self.odr.ChtIndexer() == nil { if self.odr.ChtIndexer() == nil {
return false return false

View file

@ -50,8 +50,6 @@ var (
testContractCode = common.Hex2Bytes("606060405260cc8060106000396000f360606040526000357c01000000000000000000000000000000000000000000000000000000009004806360cd2685146041578063c16431b914606b57603f565b005b6055600480803590602001909190505060a9565b6040518082815260200191505060405180910390f35b60886004808035906020019091908035906020019091905050608a565b005b80600060005083606481101560025790900160005b50819055505b5050565b6000600060005082606481101560025790900160005b5054905060c7565b91905056") testContractCode = common.Hex2Bytes("606060405260cc8060106000396000f360606040526000357c01000000000000000000000000000000000000000000000000000000009004806360cd2685146041578063c16431b914606b57603f565b005b6055600480803590602001909190505060a9565b6040518082815260200191505060405180910390f35b60886004808035906020019091908035906020019091905050608a565b005b80600060005083606481101560025790900160005b50819055505b5050565b6000600060005082606481101560025790900160005b5054905060c7565b91905056")
testContractAddr common.Address testContractAddr common.Address
bigTxGas = new(big.Int).SetUint64(params.TxGas)
) )
type testOdr struct { type testOdr struct {
@ -178,10 +176,10 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
// Perform read-only call. // Perform read-only call.
st.SetBalance(testBankAddress, math.MaxBig256) st.SetBalance(testBankAddress, math.MaxBig256)
msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), big.NewInt(1000000), new(big.Int), data, false)} msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, new(big.Int), data, false)}
context := core.NewEVMContext(msg, header, chain, nil) context := core.NewEVMContext(msg, header, chain, nil)
vmenv := vm.NewEVM(context, st, config, vm.Config{}) vmenv := vm.NewEVM(context, st, config, vm.Config{})
gp := new(core.GasPool).AddGas(math.MaxBig256) gp := new(core.GasPool).AddGas(math.MaxUint64)
ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp) ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp)
res = append(res, ret...) res = append(res, ret...)
if st.Error() != nil { if st.Error() != nil {
@ -196,17 +194,17 @@ func testChainGen(i int, block *core.BlockGen) {
switch i { switch i {
case 0: case 0:
// In block 1, the test bank sends account #1 some ether. // In block 1, the test bank sends account #1 some ether.
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), bigTxGas, nil, nil), signer, testBankKey) tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey)
block.AddTx(tx) block.AddTx(tx)
case 1: case 1:
// In block 2, the test bank sends some more ether to account #1. // In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2. // acc1Addr passes it on to account #2.
// acc1Addr creates a test contract. // acc1Addr creates a test contract.
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, testBankKey) tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey)
nonce := block.TxNonce(acc1Addr) nonce := block.TxNonce(acc1Addr)
tx2, _ := types.SignTx(types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, acc1Key) tx2, _ := types.SignTx(types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key)
nonce++ nonce++
tx3, _ := types.SignTx(types.NewContractCreation(nonce, big.NewInt(0), big.NewInt(1000000), big.NewInt(0), testContractCode), signer, acc1Key) tx3, _ := types.SignTx(types.NewContractCreation(nonce, big.NewInt(0), 1000000, big.NewInt(0), testContractCode), signer, acc1Key)
testContractAddr = crypto.CreateAddress(acc1Addr, nonce) testContractAddr = crypto.CreateAddress(acc1Addr, nonce)
block.AddTx(tx1) block.AddTx(tx1)
block.AddTx(tx2) block.AddTx(tx2)
@ -216,7 +214,7 @@ func testChainGen(i int, block *core.BlockGen) {
block.SetCoinbase(acc2Addr) block.SetCoinbase(acc2Addr)
block.SetExtra([]byte("yeehaw")) block.SetExtra([]byte("yeehaw"))
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001") data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001")
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data), signer, testBankKey) tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), 100000, nil, data), signer, testBankKey)
block.AddTx(tx) block.AddTx(tx)
case 3: case 3:
// Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data). // Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data).
@ -227,7 +225,7 @@ func testChainGen(i int, block *core.BlockGen) {
b3.Extra = []byte("foo") b3.Extra = []byte("foo")
block.AddUncle(b3) block.AddUncle(b3)
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002") data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002")
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data), signer, testBankKey) tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), 100000, nil, data), signer, testBankKey)
block.AddTx(tx) block.AddTx(tx)
} }
} }

View file

@ -358,7 +358,7 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
// Check the transaction doesn't exceed the current // Check the transaction doesn't exceed the current
// block limit gas. // block limit gas.
header := pool.chain.GetHeaderByHash(pool.head) header := pool.chain.GetHeaderByHash(pool.head)
if header.GasLimit.Cmp(tx.Gas()) < 0 { if header.GasLimit < tx.Gas() {
return core.ErrGasLimit return core.ErrGasLimit
} }
@ -376,10 +376,13 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
} }
// Should supply enough intrinsic gas // Should supply enough intrinsic gas
if tx.Gas().Cmp(core.IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead)) < 0 { gas, err := core.IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead)
if err != nil {
return err
}
if tx.Gas() < gas {
return core.ErrIntrinsicGas return core.ErrIntrinsicGas
} }
return currentState.Error() return currentState.Error()
} }

View file

@ -77,7 +77,7 @@ func txPoolTestChainGen(i int, block *core.BlockGen) {
func TestTxPool(t *testing.T) { func TestTxPool(t *testing.T) {
for i := range testTx { for i := range testTx {
testTx[i], _ = types.SignTx(types.NewTransaction(uint64(i), acc1Addr, big.NewInt(10000), bigTxGas, nil, nil), types.HomesteadSigner{}, testBankKey) testTx[i], _ = types.SignTx(types.NewTransaction(uint64(i), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), types.HomesteadSigner{}, testBankKey)
} }
var ( var (

View file

@ -413,7 +413,6 @@ func (self *worker) commitNewWork() {
ParentHash: parent.Hash(), ParentHash: parent.Hash(),
Number: num.Add(num, common.Big1), Number: num.Add(num, common.Big1),
GasLimit: core.CalcGasLimit(parent), GasLimit: core.CalcGasLimit(parent),
GasUsed: new(big.Int),
Extra: self.extra, Extra: self.extra,
Time: big.NewInt(tstamp), Time: big.NewInt(tstamp),
} }
@ -588,7 +587,7 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB
func (env *Work) commitTransaction(tx *types.Transaction, bc *core.BlockChain, coinbase common.Address, gp *core.GasPool) (error, []*types.Log) { func (env *Work) commitTransaction(tx *types.Transaction, bc *core.BlockChain, coinbase common.Address, gp *core.GasPool) (error, []*types.Log) {
snap := env.state.Snapshot() snap := env.state.Snapshot()
receipt, _, err := core.ApplyTransaction(env.config, bc, &coinbase, gp, env.state, env.header, tx, env.header.GasUsed, vm.Config{}) receipt, _, err := core.ApplyTransaction(env.config, bc, &coinbase, gp, env.state, env.header, tx, &env.header.GasUsed, vm.Config{})
if err != nil { if err != nil {
env.state.RevertToSnapshot(snap) env.state.RevertToSnapshot(snap)
return err, nil return err, nil

View file

@ -77,7 +77,7 @@ func (opts *TransactOpts) GetFrom() *Address { return &Address{opts.opts.From
func (opts *TransactOpts) GetNonce() int64 { return opts.opts.Nonce.Int64() } func (opts *TransactOpts) GetNonce() int64 { return opts.opts.Nonce.Int64() }
func (opts *TransactOpts) GetValue() *BigInt { return &BigInt{opts.opts.Value} } func (opts *TransactOpts) GetValue() *BigInt { return &BigInt{opts.opts.Value} }
func (opts *TransactOpts) GetGasPrice() *BigInt { return &BigInt{opts.opts.GasPrice} } func (opts *TransactOpts) GetGasPrice() *BigInt { return &BigInt{opts.opts.GasPrice} }
func (opts *TransactOpts) GetGasLimit() int64 { return opts.opts.GasLimit.Int64() } func (opts *TransactOpts) GetGasLimit() int64 { return int64(opts.opts.GasLimit) }
// GetSigner cannot be reliably implemented without identity preservation (https://github.com/golang/go/issues/16876) // GetSigner cannot be reliably implemented without identity preservation (https://github.com/golang/go/issues/16876)
// func (opts *TransactOpts) GetSigner() Signer { return &signer{opts.opts.Signer} } // func (opts *TransactOpts) GetSigner() Signer { return &signer{opts.opts.Signer} }
@ -99,7 +99,7 @@ func (opts *TransactOpts) SetSigner(s Signer) {
} }
func (opts *TransactOpts) SetValue(value *BigInt) { opts.opts.Value = value.bigint } func (opts *TransactOpts) SetValue(value *BigInt) { opts.opts.Value = value.bigint }
func (opts *TransactOpts) SetGasPrice(price *BigInt) { opts.opts.GasPrice = price.bigint } func (opts *TransactOpts) SetGasPrice(price *BigInt) { opts.opts.GasPrice = price.bigint }
func (opts *TransactOpts) SetGasLimit(limit int64) { opts.opts.GasLimit = big.NewInt(limit) } func (opts *TransactOpts) SetGasLimit(limit int64) { opts.opts.GasLimit = uint64(limit) }
func (opts *TransactOpts) SetContext(context *Context) { opts.opts.Context = context.context } func (opts *TransactOpts) SetContext(context *Context) { opts.opts.Context = context.context }
// BoundContract is the base wrapper object that reflects a contract on the // BoundContract is the base wrapper object that reflects a contract on the

View file

@ -298,9 +298,9 @@ func (ec *EthereumClient) SuggestGasPrice(ctx *Context) (price *BigInt, _ error)
// the current pending state of the backend blockchain. There is no guarantee that this is // the current pending state of the backend blockchain. There is no guarantee that this is
// the true gas limit requirement as other transactions may be added or removed by miners, // the true gas limit requirement as other transactions may be added or removed by miners,
// but it should provide a basis for setting a reasonable default. // but it should provide a basis for setting a reasonable default.
func (ec *EthereumClient) EstimateGas(ctx *Context, msg *CallMsg) (gas *BigInt, _ error) { func (ec *EthereumClient) EstimateGas(ctx *Context, msg *CallMsg) (gas int64, _ error) {
rawGas, err := ec.client.EstimateGas(ctx.context, msg.msg) rawGas, err := ec.client.EstimateGas(ctx.context, msg.msg)
return &BigInt{rawGas}, err return int64(rawGas), err
} }
// SendTransaction injects a signed transaction into the pending pool for execution. // SendTransaction injects a signed transaction into the pending pool for execution.

View file

@ -20,7 +20,6 @@ package geth
import ( import (
"errors" "errors"
"math/big"
ethereum "github.com/ethereum/go-ethereum" ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -49,7 +48,7 @@ func NewCallMsg() *CallMsg {
} }
func (msg *CallMsg) GetFrom() *Address { return &Address{msg.msg.From} } func (msg *CallMsg) GetFrom() *Address { return &Address{msg.msg.From} }
func (msg *CallMsg) GetGas() int64 { return msg.msg.Gas.Int64() } func (msg *CallMsg) GetGas() int64 { return int64(msg.msg.Gas) }
func (msg *CallMsg) GetGasPrice() *BigInt { return &BigInt{msg.msg.GasPrice} } func (msg *CallMsg) GetGasPrice() *BigInt { return &BigInt{msg.msg.GasPrice} }
func (msg *CallMsg) GetValue() *BigInt { return &BigInt{msg.msg.Value} } func (msg *CallMsg) GetValue() *BigInt { return &BigInt{msg.msg.Value} }
func (msg *CallMsg) GetData() []byte { return msg.msg.Data } func (msg *CallMsg) GetData() []byte { return msg.msg.Data }
@ -61,7 +60,7 @@ func (msg *CallMsg) GetTo() *Address {
} }
func (msg *CallMsg) SetFrom(address *Address) { msg.msg.From = address.address } func (msg *CallMsg) SetFrom(address *Address) { msg.msg.From = address.address }
func (msg *CallMsg) SetGas(gas int64) { msg.msg.Gas = big.NewInt(gas) } func (msg *CallMsg) SetGas(gas int64) { msg.msg.Gas = uint64(gas) }
func (msg *CallMsg) SetGasPrice(price *BigInt) { msg.msg.GasPrice = price.bigint } func (msg *CallMsg) SetGasPrice(price *BigInt) { msg.msg.GasPrice = price.bigint }
func (msg *CallMsg) SetValue(value *BigInt) { msg.msg.Value = value.bigint } func (msg *CallMsg) SetValue(value *BigInt) { msg.msg.Value = value.bigint }
func (msg *CallMsg) SetData(data []byte) { msg.msg.Data = common.CopyBytes(data) } func (msg *CallMsg) SetData(data []byte) { msg.msg.Data = common.CopyBytes(data) }

View file

@ -112,8 +112,8 @@ func (h *Header) GetReceiptHash() *Hash { return &Hash{h.header.ReceiptHash} }
func (h *Header) GetBloom() *Bloom { return &Bloom{h.header.Bloom} } func (h *Header) GetBloom() *Bloom { return &Bloom{h.header.Bloom} }
func (h *Header) GetDifficulty() *BigInt { return &BigInt{h.header.Difficulty} } func (h *Header) GetDifficulty() *BigInt { return &BigInt{h.header.Difficulty} }
func (h *Header) GetNumber() int64 { return h.header.Number.Int64() } func (h *Header) GetNumber() int64 { return h.header.Number.Int64() }
func (h *Header) GetGasLimit() int64 { return h.header.GasLimit.Int64() } func (h *Header) GetGasLimit() int64 { return int64(h.header.GasLimit) }
func (h *Header) GetGasUsed() int64 { return h.header.GasUsed.Int64() } func (h *Header) GetGasUsed() int64 { return int64(h.header.GasUsed) }
func (h *Header) GetTime() int64 { return h.header.Time.Int64() } func (h *Header) GetTime() int64 { return h.header.Time.Int64() }
func (h *Header) GetExtra() []byte { return h.header.Extra } func (h *Header) GetExtra() []byte { return h.header.Extra }
func (h *Header) GetMixDigest() *Hash { return &Hash{h.header.MixDigest} } func (h *Header) GetMixDigest() *Hash { return &Hash{h.header.MixDigest} }
@ -189,8 +189,8 @@ func (b *Block) GetReceiptHash() *Hash { return &Hash{b.block.ReceiptHash()} }
func (b *Block) GetBloom() *Bloom { return &Bloom{b.block.Bloom()} } func (b *Block) GetBloom() *Bloom { return &Bloom{b.block.Bloom()} }
func (b *Block) GetDifficulty() *BigInt { return &BigInt{b.block.Difficulty()} } func (b *Block) GetDifficulty() *BigInt { return &BigInt{b.block.Difficulty()} }
func (b *Block) GetNumber() int64 { return b.block.Number().Int64() } func (b *Block) GetNumber() int64 { return b.block.Number().Int64() }
func (b *Block) GetGasLimit() int64 { return b.block.GasLimit().Int64() } func (b *Block) GetGasLimit() int64 { return int64(b.block.GasLimit()) }
func (b *Block) GetGasUsed() int64 { return b.block.GasUsed().Int64() } func (b *Block) GetGasUsed() int64 { return int64(b.block.GasUsed()) }
func (b *Block) GetTime() int64 { return b.block.Time().Int64() } func (b *Block) GetTime() int64 { return b.block.Time().Int64() }
func (b *Block) GetExtra() []byte { return b.block.Extra() } func (b *Block) GetExtra() []byte { return b.block.Extra() }
func (b *Block) GetMixDigest() *Hash { return &Hash{b.block.MixDigest()} } func (b *Block) GetMixDigest() *Hash { return &Hash{b.block.MixDigest()} }
@ -212,8 +212,8 @@ type Transaction struct {
} }
// NewTransaction creates a new transaction with the given properties. // NewTransaction creates a new transaction with the given properties.
func NewTransaction(nonce int64, to *Address, amount, gasLimit, gasPrice *BigInt, data []byte) *Transaction { func NewTransaction(nonce int64, to *Address, amount *BigInt, gasLimit int64, gasPrice *BigInt, data []byte) *Transaction {
return &Transaction{types.NewTransaction(uint64(nonce), to.address, amount.bigint, gasLimit.bigint, gasPrice.bigint, common.CopyBytes(data))} return &Transaction{types.NewTransaction(uint64(nonce), to.address, amount.bigint, uint64(gasLimit), gasPrice.bigint, common.CopyBytes(data))}
} }
// NewTransactionFromRLP parses a transaction from an RLP data dump. // NewTransactionFromRLP parses a transaction from an RLP data dump.
@ -256,7 +256,7 @@ func (tx *Transaction) String() string {
} }
func (tx *Transaction) GetData() []byte { return tx.tx.Data() } func (tx *Transaction) GetData() []byte { return tx.tx.Data() }
func (tx *Transaction) GetGas() int64 { return tx.tx.Gas().Int64() } func (tx *Transaction) GetGas() int64 { return int64(tx.tx.Gas()) }
func (tx *Transaction) GetGasPrice() *BigInt { return &BigInt{tx.tx.GasPrice()} } func (tx *Transaction) GetGasPrice() *BigInt { return &BigInt{tx.tx.GasPrice()} }
func (tx *Transaction) GetValue() *BigInt { return &BigInt{tx.tx.Value()} } func (tx *Transaction) GetValue() *BigInt { return &BigInt{tx.tx.Value()} }
func (tx *Transaction) GetNonce() int64 { return int64(tx.tx.Nonce()) } func (tx *Transaction) GetNonce() int64 { return int64(tx.tx.Nonce()) }
@ -354,9 +354,9 @@ func (r *Receipt) String() string {
} }
func (r *Receipt) GetPostState() []byte { return r.receipt.PostState } func (r *Receipt) GetPostState() []byte { return r.receipt.PostState }
func (r *Receipt) GetCumulativeGasUsed() *BigInt { return &BigInt{r.receipt.CumulativeGasUsed} } func (r *Receipt) GetCumulativeGasUsed() int64 { return int64(r.receipt.CumulativeGasUsed) }
func (r *Receipt) GetBloom() *Bloom { return &Bloom{r.receipt.Bloom} } func (r *Receipt) GetBloom() *Bloom { return &Bloom{r.receipt.Bloom} }
func (r *Receipt) GetLogs() *Logs { return &Logs{r.receipt.Logs} } func (r *Receipt) GetLogs() *Logs { return &Logs{r.receipt.Logs} }
func (r *Receipt) GetTxHash() *Hash { return &Hash{r.receipt.TxHash} } func (r *Receipt) GetTxHash() *Hash { return &Hash{r.receipt.TxHash} }
func (r *Receipt) GetContractAddress() *Address { return &Address{r.receipt.ContractAddress} } func (r *Receipt) GetContractAddress() *Address { return &Address{r.receipt.ContractAddress} }
func (r *Receipt) GetGasUsed() *BigInt { return &BigInt{r.receipt.GasUsed} } func (r *Receipt) GetGasUsed() int64 { return int64(r.receipt.GasUsed) }

View file

@ -239,14 +239,14 @@ func (db *nodeDB) ensureExpirer() {
// expirer should be started in a go routine, and is responsible for looping ad // expirer should be started in a go routine, and is responsible for looping ad
// infinitum and dropping stale data from the database. // infinitum and dropping stale data from the database.
func (db *nodeDB) expirer() { func (db *nodeDB) expirer() {
tick := time.Tick(nodeDBCleanupCycle) tick := time.NewTicker(nodeDBCleanupCycle)
defer tick.Stop()
for { for {
select { select {
case <-tick: case <-tick.C:
if err := db.expireNodes(); err != nil { if err := db.expireNodes(); err != nil {
log.Error(fmt.Sprintf("Failed to expire nodedb items: %v", err)) log.Error(fmt.Sprintf("Failed to expire nodedb items: %v", err))
} }
case <-db.quit: case <-db.quit:
return return
} }

View file

@ -51,16 +51,9 @@ const (
const testTopic = "foo" const testTopic = "foo"
const ( const (
printDebugLogs = false
printTestImgLogs = false printTestImgLogs = false
) )
func debugLog(s string) {
if printDebugLogs {
fmt.Println(s)
}
}
// Network manages the table and all protocol interaction. // Network manages the table and all protocol interaction.
type Network struct { type Network struct {
db *nodeDB // database of known nodes db *nodeDB // database of known nodes
@ -388,14 +381,14 @@ func (net *Network) loop() {
} }
}() }()
resetNextTicket := func() { resetNextTicket := func() {
t, timeout := net.ticketStore.nextFilteredTicket() ticket, timeout := net.ticketStore.nextFilteredTicket()
if t != nextTicket { if nextTicket != ticket {
nextTicket = t nextTicket = ticket
if nextRegisterTimer != nil { if nextRegisterTimer != nil {
nextRegisterTimer.Stop() nextRegisterTimer.Stop()
nextRegisterTime = nil nextRegisterTime = nil
} }
if t != nil { if ticket != nil {
nextRegisterTimer = time.NewTimer(timeout) nextRegisterTimer = time.NewTimer(timeout)
nextRegisterTime = nextRegisterTimer.C nextRegisterTime = nextRegisterTimer.C
} }
@ -423,13 +416,13 @@ loop:
select { select {
case <-net.closeReq: case <-net.closeReq:
debugLog("<-net.closeReq") log.Trace("<-net.closeReq")
break loop break loop
// Ingress packet handling. // Ingress packet handling.
case pkt := <-net.read: case pkt := <-net.read:
//fmt.Println("read", pkt.ev) //fmt.Println("read", pkt.ev)
debugLog("<-net.read") log.Trace("<-net.read")
n := net.internNode(&pkt) n := net.internNode(&pkt)
prestate := n.state prestate := n.state
status := "ok" status := "ok"
@ -444,7 +437,7 @@ loop:
// State transition timeouts. // State transition timeouts.
case timeout := <-net.timeout: case timeout := <-net.timeout:
debugLog("<-net.timeout") log.Trace("<-net.timeout")
if net.timeoutTimers[timeout] == nil { if net.timeoutTimers[timeout] == nil {
// Stale timer (was aborted). // Stale timer (was aborted).
continue continue
@ -462,20 +455,20 @@ loop:
// Querying. // Querying.
case q := <-net.queryReq: case q := <-net.queryReq:
debugLog("<-net.queryReq") log.Trace("<-net.queryReq")
if !q.start(net) { if !q.start(net) {
q.remote.deferQuery(q) q.remote.deferQuery(q)
} }
// Interacting with the table. // Interacting with the table.
case f := <-net.tableOpReq: case f := <-net.tableOpReq:
debugLog("<-net.tableOpReq") log.Trace("<-net.tableOpReq")
f() f()
net.tableOpResp <- struct{}{} net.tableOpResp <- struct{}{}
// Topic registration stuff. // Topic registration stuff.
case req := <-net.topicRegisterReq: case req := <-net.topicRegisterReq:
debugLog("<-net.topicRegisterReq") log.Trace("<-net.topicRegisterReq")
if !req.add { if !req.add {
net.ticketStore.removeRegisterTopic(req.topic) net.ticketStore.removeRegisterTopic(req.topic)
continue continue
@ -486,7 +479,7 @@ loop:
// determination for new topics. // determination for new topics.
// if topicRegisterLookupDone == nil { // if topicRegisterLookupDone == nil {
if topicRegisterLookupTarget.target == (common.Hash{}) { if topicRegisterLookupTarget.target == (common.Hash{}) {
debugLog("topicRegisterLookupTarget == null") log.Trace("topicRegisterLookupTarget == null")
if topicRegisterLookupTick.Stop() { if topicRegisterLookupTick.Stop() {
<-topicRegisterLookupTick.C <-topicRegisterLookupTick.C
} }
@ -496,7 +489,7 @@ loop:
} }
case nodes := <-topicRegisterLookupDone: case nodes := <-topicRegisterLookupDone:
debugLog("<-topicRegisterLookupDone") log.Trace("<-topicRegisterLookupDone")
net.ticketStore.registerLookupDone(topicRegisterLookupTarget, nodes, func(n *Node) []byte { net.ticketStore.registerLookupDone(topicRegisterLookupTarget, nodes, func(n *Node) []byte {
net.ping(n, n.addr()) net.ping(n, n.addr())
return n.pingEcho return n.pingEcho
@ -507,7 +500,7 @@ loop:
topicRegisterLookupDone = nil topicRegisterLookupDone = nil
case <-topicRegisterLookupTick.C: case <-topicRegisterLookupTick.C:
debugLog("<-topicRegisterLookupTick") log.Trace("<-topicRegisterLookupTick")
if (topicRegisterLookupTarget.target == common.Hash{}) { if (topicRegisterLookupTarget.target == common.Hash{}) {
target, delay := net.ticketStore.nextRegisterLookup() target, delay := net.ticketStore.nextRegisterLookup()
topicRegisterLookupTarget = target topicRegisterLookupTarget = target
@ -520,14 +513,14 @@ loop:
} }
case <-nextRegisterTime: case <-nextRegisterTime:
debugLog("<-nextRegisterTime") log.Trace("<-nextRegisterTime")
net.ticketStore.ticketRegistered(*nextTicket) net.ticketStore.ticketRegistered(*nextTicket)
//fmt.Println("sendTopicRegister", nextTicket.t.node.addr().String(), nextTicket.t.topics, nextTicket.idx, nextTicket.t.pong) //fmt.Println("sendTopicRegister", nextTicket.t.node.addr().String(), nextTicket.t.topics, nextTicket.idx, nextTicket.t.pong)
net.conn.sendTopicRegister(nextTicket.t.node, nextTicket.t.topics, nextTicket.idx, nextTicket.t.pong) net.conn.sendTopicRegister(nextTicket.t.node, nextTicket.t.topics, nextTicket.idx, nextTicket.t.pong)
case req := <-net.topicSearchReq: case req := <-net.topicSearchReq:
if refreshDone == nil { if refreshDone == nil {
debugLog("<-net.topicSearchReq") log.Trace("<-net.topicSearchReq")
info, ok := searchInfo[req.topic] info, ok := searchInfo[req.topic]
if ok { if ok {
if req.delay == time.Duration(0) { if req.delay == time.Duration(0) {
@ -588,7 +581,7 @@ loop:
}) })
case <-statsDump.C: case <-statsDump.C:
debugLog("<-statsDump.C") log.Trace("<-statsDump.C")
/*r, ok := net.ticketStore.radius[testTopic] /*r, ok := net.ticketStore.radius[testTopic]
if !ok { if !ok {
fmt.Printf("(%x) no radius @ %v\n", net.tab.self.ID[:8], time.Now()) fmt.Printf("(%x) no radius @ %v\n", net.tab.self.ID[:8], time.Now())
@ -617,7 +610,7 @@ loop:
// Periodic / lookup-initiated bucket refresh. // Periodic / lookup-initiated bucket refresh.
case <-refreshTimer.C: case <-refreshTimer.C:
debugLog("<-refreshTimer.C") log.Trace("<-refreshTimer.C")
// TODO: ideally we would start the refresh timer after // TODO: ideally we would start the refresh timer after
// fallback nodes have been set for the first time. // fallback nodes have been set for the first time.
if refreshDone == nil { if refreshDone == nil {
@ -631,7 +624,7 @@ loop:
bucketRefreshTimer.Reset(bucketRefreshInterval) bucketRefreshTimer.Reset(bucketRefreshInterval)
}() }()
case newNursery := <-net.refreshReq: case newNursery := <-net.refreshReq:
debugLog("<-net.refreshReq") log.Trace("<-net.refreshReq")
if newNursery != nil { if newNursery != nil {
net.nursery = newNursery net.nursery = newNursery
} }
@ -641,7 +634,7 @@ loop:
} }
net.refreshResp <- refreshDone net.refreshResp <- refreshDone
case <-refreshDone: case <-refreshDone:
debugLog("<-net.refreshDone") log.Trace("<-net.refreshDone")
refreshDone = nil refreshDone = nil
list := searchReqWhenRefreshDone list := searchReqWhenRefreshDone
searchReqWhenRefreshDone = nil searchReqWhenRefreshDone = nil
@ -652,7 +645,7 @@ loop:
}() }()
} }
} }
debugLog("loop stopped") log.Trace("loop stopped")
log.Debug(fmt.Sprintf("shutting down")) log.Debug(fmt.Sprintf("shutting down"))
if net.conn != nil { if net.conn != nil {
@ -1109,14 +1102,14 @@ func (net *Network) ping(n *Node, addr *net.UDPAddr) {
//fmt.Println(" not sent") //fmt.Println(" not sent")
return return
} }
debugLog(fmt.Sprintf("ping(node = %x)", n.ID[:8])) log.Trace("Pinging remote node", "node", n.ID)
n.pingTopics = net.ticketStore.regTopicSet() n.pingTopics = net.ticketStore.regTopicSet()
n.pingEcho = net.conn.sendPing(n, addr, n.pingTopics) n.pingEcho = net.conn.sendPing(n, addr, n.pingTopics)
net.timedEvent(respTimeout, n, pongTimeout) net.timedEvent(respTimeout, n, pongTimeout)
} }
func (net *Network) handlePing(n *Node, pkt *ingressPacket) { func (net *Network) handlePing(n *Node, pkt *ingressPacket) {
debugLog(fmt.Sprintf("handlePing(node = %x)", n.ID[:8])) log.Trace("Handling remote ping", "node", n.ID)
ping := pkt.data.(*ping) ping := pkt.data.(*ping)
n.TCP = ping.From.TCP n.TCP = ping.From.TCP
t := net.topictab.getTicket(n, ping.Topics) t := net.topictab.getTicket(n, ping.Topics)
@ -1131,7 +1124,7 @@ func (net *Network) handlePing(n *Node, pkt *ingressPacket) {
} }
func (net *Network) handleKnownPong(n *Node, pkt *ingressPacket) error { func (net *Network) handleKnownPong(n *Node, pkt *ingressPacket) error {
debugLog(fmt.Sprintf("handleKnownPong(node = %x)", n.ID[:8])) log.Trace("Handling known pong", "node", n.ID)
net.abortTimedEvent(n, pongTimeout) net.abortTimedEvent(n, pongTimeout)
now := mclock.Now() now := mclock.Now()
ticket, err := pongToTicket(now, n.pingTopics, n, pkt) ticket, err := pongToTicket(now, n.pingTopics, n, pkt)
@ -1139,9 +1132,8 @@ func (net *Network) handleKnownPong(n *Node, pkt *ingressPacket) error {
// fmt.Printf("(%x) ticket: %+v\n", net.tab.self.ID[:8], pkt.data) // fmt.Printf("(%x) ticket: %+v\n", net.tab.self.ID[:8], pkt.data)
net.ticketStore.addTicket(now, pkt.data.(*pong).ReplyTok, ticket) net.ticketStore.addTicket(now, pkt.data.(*pong).ReplyTok, ticket)
} else { } else {
debugLog(fmt.Sprintf(" error: %v", err)) log.Trace("Failed to convert pong to ticket", "err", err)
} }
n.pingEcho = nil n.pingEcho = nil
n.pingTopics = nil n.pingTopics = nil
return err return err

View file

@ -273,6 +273,11 @@ func (n NodeID) GoString() string {
return fmt.Sprintf("discover.HexID(\"%x\")", n[:]) return fmt.Sprintf("discover.HexID(\"%x\")", n[:])
} }
// TerminalString returns a shortened hex string for terminal logging.
func (n NodeID) TerminalString() string {
return hex.EncodeToString(n[:8])
}
// HexID converts a hex string to a NodeID. // HexID converts a hex string to a NodeID.
// The string may be prefixed with 0x. // The string may be prefixed with 0x.
func HexID(in string) (NodeID, error) { func HexID(in string) (NodeID, error) {

View file

@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
) )
const ( const (
@ -128,8 +129,11 @@ type ticketStore struct {
// Contains buckets (for each absolute minute) of tickets // Contains buckets (for each absolute minute) of tickets
// that can be used in that minute. // that can be used in that minute.
// This is only set if the topic is being registered. // This is only set if the topic is being registered.
tickets map[Topic]topicTickets tickets map[Topic]*topicTickets
regtopics []Topic
regQueue []Topic // Topic registration queue for round robin attempts
regSet map[Topic]struct{} // Topic registration queue contents for fast filling
nodes map[*Node]*ticket nodes map[*Node]*ticket
nodeLastReq map[*Node]reqInfo nodeLastReq map[*Node]reqInfo
@ -153,13 +157,15 @@ type sentQuery struct {
type topicTickets struct { type topicTickets struct {
buckets map[timeBucket][]ticketRef buckets map[timeBucket][]ticketRef
nextLookup, nextReg mclock.AbsTime nextLookup mclock.AbsTime
nextReg mclock.AbsTime
} }
func newTicketStore() *ticketStore { func newTicketStore() *ticketStore {
return &ticketStore{ return &ticketStore{
radius: make(map[Topic]*topicRadius), radius: make(map[Topic]*topicRadius),
tickets: make(map[Topic]topicTickets), tickets: make(map[Topic]*topicTickets),
regSet: make(map[Topic]struct{}),
nodes: make(map[*Node]*ticket), nodes: make(map[*Node]*ticket),
nodeLastReq: make(map[*Node]reqInfo), nodeLastReq: make(map[*Node]reqInfo),
searchTopicMap: make(map[Topic]searchTopic), searchTopicMap: make(map[Topic]searchTopic),
@ -169,13 +175,13 @@ func newTicketStore() *ticketStore {
// addTopic starts tracking a topic. If register is true, // addTopic starts tracking a topic. If register is true,
// the local node will register the topic and tickets will be collected. // the local node will register the topic and tickets will be collected.
func (s *ticketStore) addTopic(t Topic, register bool) { func (s *ticketStore) addTopic(topic Topic, register bool) {
debugLog(fmt.Sprintf(" addTopic(%v, %v)", t, register)) log.Trace("Adding discovery topic", "topic", topic, "register", register)
if s.radius[t] == nil { if s.radius[topic] == nil {
s.radius[t] = newTopicRadius(t) s.radius[topic] = newTopicRadius(topic)
} }
if register && s.tickets[t].buckets == nil { if register && s.tickets[topic] == nil {
s.tickets[t] = topicTickets{buckets: make(map[timeBucket][]ticketRef)} s.tickets[topic] = &topicTickets{buckets: make(map[timeBucket][]ticketRef)}
} }
} }
@ -194,7 +200,11 @@ func (s *ticketStore) removeSearchTopic(t Topic) {
// removeRegisterTopic deletes all tickets for the given topic. // removeRegisterTopic deletes all tickets for the given topic.
func (s *ticketStore) removeRegisterTopic(topic Topic) { func (s *ticketStore) removeRegisterTopic(topic Topic) {
debugLog(fmt.Sprintf(" removeRegisterTopic(%v)", topic)) log.Trace("Removing discovery topic", "topic", topic)
if s.tickets[topic] == nil {
log.Warn("Removing non-existent discovery topic", "topic", topic)
return
}
for _, list := range s.tickets[topic].buckets { for _, list := range s.tickets[topic].buckets {
for _, ref := range list { for _, ref := range list {
ref.t.refCnt-- ref.t.refCnt--
@ -216,23 +226,35 @@ func (s *ticketStore) regTopicSet() []Topic {
} }
// nextRegisterLookup returns the target of the next lookup for ticket collection. // nextRegisterLookup returns the target of the next lookup for ticket collection.
func (s *ticketStore) nextRegisterLookup() (lookup lookupInfo, delay time.Duration) { func (s *ticketStore) nextRegisterLookup() (lookupInfo, time.Duration) {
debugLog("nextRegisterLookup()") // Queue up any new topics (or discarded ones), preserving iteration order
firstTopic, ok := s.iterRegTopics() for topic := range s.tickets {
for topic := firstTopic; ok; { if _, ok := s.regSet[topic]; !ok {
debugLog(fmt.Sprintf(" checking topic %v, len(s.tickets[topic]) = %d", topic, len(s.tickets[topic].buckets))) s.regQueue = append(s.regQueue, topic)
if s.tickets[topic].buckets != nil && s.needMoreTickets(topic) { s.regSet[topic] = struct{}{}
next := s.radius[topic].nextTarget(false)
debugLog(fmt.Sprintf(" %x 1s", next.target[:8]))
return next, 100 * time.Millisecond
}
topic, ok = s.iterRegTopics()
if topic == firstTopic {
break // We have checked all topics.
} }
} }
debugLog(" null, 40s") // Iterate over the set of all topics and look up the next suitable one
return lookupInfo{}, 40 * time.Second for len(s.regQueue) > 0 {
// Fetch the next topic from the queue, and ensure it still exists
topic := s.regQueue[0]
s.regQueue = s.regQueue[1:]
delete(s.regSet, topic)
if s.tickets[topic] == nil {
continue
}
// If the topic needs more tickets, return it
if s.tickets[topic].nextLookup < mclock.Now() {
next, delay := s.radius[topic].nextTarget(false), 100*time.Millisecond
log.Trace("Found discovery topic to register", "topic", topic, "target", next.target, "delay", delay)
return next, delay
}
}
// No registration topics found or all exhausted, sleep
delay := 40 * time.Second
log.Trace("No topic found to register", "delay", delay)
return lookupInfo{}, delay
} }
func (s *ticketStore) nextSearchLookup(topic Topic) lookupInfo { func (s *ticketStore) nextSearchLookup(topic Topic) lookupInfo {
@ -246,40 +268,22 @@ func (s *ticketStore) nextSearchLookup(topic Topic) lookupInfo {
return target return target
} }
// iterRegTopics returns topics to register in arbitrary order.
// The second return value is false if there are no topics.
func (s *ticketStore) iterRegTopics() (Topic, bool) {
debugLog("iterRegTopics()")
if len(s.regtopics) == 0 {
if len(s.tickets) == 0 {
debugLog(" false")
return "", false
}
// Refill register list.
for t := range s.tickets {
s.regtopics = append(s.regtopics, t)
}
}
topic := s.regtopics[len(s.regtopics)-1]
s.regtopics = s.regtopics[:len(s.regtopics)-1]
debugLog(" " + string(topic) + " true")
return topic, true
}
func (s *ticketStore) needMoreTickets(t Topic) bool {
return s.tickets[t].nextLookup < mclock.Now()
}
// ticketsInWindow returns the tickets of a given topic in the registration window. // ticketsInWindow returns the tickets of a given topic in the registration window.
func (s *ticketStore) ticketsInWindow(t Topic) []ticketRef { func (s *ticketStore) ticketsInWindow(topic Topic) []ticketRef {
ltBucket := s.lastBucketFetched // Sanity check that the topic still exists before operating on it
var res []ticketRef if s.tickets[topic] == nil {
tickets := s.tickets[t].buckets log.Warn("Listing non-existing discovery tickets", "topic", topic)
for g := ltBucket; g < ltBucket+timeWindow; g++ { return nil
res = append(res, tickets[g]...)
} }
debugLog(fmt.Sprintf("ticketsInWindow(%v) = %v", t, len(res))) // Gather all the tickers in the next time window
return res var tickets []ticketRef
buckets := s.tickets[topic].buckets
for idx := timeBucket(0); idx < timeWindow; idx++ {
tickets = append(tickets, buckets[s.lastBucketFetched+idx]...)
}
log.Trace("Retrieved discovery registration tickets", "topic", topic, "from", s.lastBucketFetched, "tickets", len(tickets))
return tickets
} }
func (s *ticketStore) removeExcessTickets(t Topic) { func (s *ticketStore) removeExcessTickets(t Topic) {
@ -317,53 +321,55 @@ func (s ticketRefByWaitTime) Swap(i, j int) {
func (s *ticketStore) addTicketRef(r ticketRef) { func (s *ticketStore) addTicketRef(r ticketRef) {
topic := r.t.topics[r.idx] topic := r.t.topics[r.idx]
t := s.tickets[topic] tickets := s.tickets[topic]
if t.buckets == nil { if tickets == nil {
log.Warn("Adding ticket to non-existent topic", "topic", topic)
return return
} }
bucket := timeBucket(r.t.regTime[r.idx] / mclock.AbsTime(ticketTimeBucketLen)) bucket := timeBucket(r.t.regTime[r.idx] / mclock.AbsTime(ticketTimeBucketLen))
t.buckets[bucket] = append(t.buckets[bucket], r) tickets.buckets[bucket] = append(tickets.buckets[bucket], r)
r.t.refCnt++ r.t.refCnt++
min := mclock.Now() - mclock.AbsTime(collectFrequency)*maxCollectDebt min := mclock.Now() - mclock.AbsTime(collectFrequency)*maxCollectDebt
if t.nextLookup < min { if tickets.nextLookup < min {
t.nextLookup = min tickets.nextLookup = min
} }
t.nextLookup += mclock.AbsTime(collectFrequency) tickets.nextLookup += mclock.AbsTime(collectFrequency)
s.tickets[topic] = t
//s.removeExcessTickets(topic) //s.removeExcessTickets(topic)
} }
func (s *ticketStore) nextFilteredTicket() (t *ticketRef, wait time.Duration) { func (s *ticketStore) nextFilteredTicket() (*ticketRef, time.Duration) {
now := mclock.Now() now := mclock.Now()
for { for {
t, wait = s.nextRegisterableTicket() ticket, wait := s.nextRegisterableTicket()
if t == nil { if ticket == nil {
return return ticket, wait
} }
log.Trace("Found discovery ticket to register", "node", ticket.t.node, "serial", ticket.t.serial, "wait", wait)
regTime := now + mclock.AbsTime(wait) regTime := now + mclock.AbsTime(wait)
topic := t.t.topics[t.idx] topic := ticket.t.topics[ticket.idx]
if regTime >= s.tickets[topic].nextReg { if regTime >= s.tickets[topic].nextReg {
return return ticket, wait
} }
s.removeTicketRef(*t) s.removeTicketRef(*ticket)
} }
} }
func (s *ticketStore) ticketRegistered(t ticketRef) { func (s *ticketStore) ticketRegistered(ref ticketRef) {
now := mclock.Now() now := mclock.Now()
topic := t.t.topics[t.idx] topic := ref.t.topics[ref.idx]
tt := s.tickets[topic] tickets := s.tickets[topic]
min := now - mclock.AbsTime(registerFrequency)*maxRegisterDebt min := now - mclock.AbsTime(registerFrequency)*maxRegisterDebt
if min > tt.nextReg { if min > tickets.nextReg {
tt.nextReg = min tickets.nextReg = min
} }
tt.nextReg += mclock.AbsTime(registerFrequency) tickets.nextReg += mclock.AbsTime(registerFrequency)
s.tickets[topic] = tt s.tickets[topic] = tickets
s.removeTicketRef(t) s.removeTicketRef(ref)
} }
// nextRegisterableTicket returns the next ticket that can be used // nextRegisterableTicket returns the next ticket that can be used
@ -374,16 +380,7 @@ func (s *ticketStore) ticketRegistered(t ticketRef) {
// //
// A ticket can be returned more than once with <= zero wait time in case // A ticket can be returned more than once with <= zero wait time in case
// the ticket contains multiple topics. // the ticket contains multiple topics.
func (s *ticketStore) nextRegisterableTicket() (t *ticketRef, wait time.Duration) { func (s *ticketStore) nextRegisterableTicket() (*ticketRef, time.Duration) {
defer func() {
if t == nil {
debugLog(" nil")
} else {
debugLog(fmt.Sprintf(" node = %x sn = %v wait = %v", t.t.node.ID[:8], t.t.serial, wait))
}
}()
debugLog("nextRegisterableTicket()")
now := mclock.Now() now := mclock.Now()
if s.nextTicketCached != nil { if s.nextTicketCached != nil {
return s.nextTicketCached, time.Duration(s.nextTicketCached.topicRegTime() - now) return s.nextTicketCached, time.Duration(s.nextTicketCached.topicRegTime() - now)
@ -412,9 +409,8 @@ func (s *ticketStore) nextRegisterableTicket() (t *ticketRef, wait time.Duration
return nil, 0 return nil, 0
} }
if nextTicket.t != nil { if nextTicket.t != nil {
wait = time.Duration(nextTicket.topicRegTime() - now)
s.nextTicketCached = &nextTicket s.nextTicketCached = &nextTicket
return &nextTicket, wait return &nextTicket, time.Duration(nextTicket.topicRegTime() - now)
} }
s.lastBucketFetched = bucket s.lastBucketFetched = bucket
} }
@ -422,14 +418,17 @@ func (s *ticketStore) nextRegisterableTicket() (t *ticketRef, wait time.Duration
// removeTicket removes a ticket from the ticket store // removeTicket removes a ticket from the ticket store
func (s *ticketStore) removeTicketRef(ref ticketRef) { func (s *ticketStore) removeTicketRef(ref ticketRef) {
debugLog(fmt.Sprintf("removeTicketRef(node = %x sn = %v)", ref.t.node.ID[:8], ref.t.serial)) log.Trace("Removing discovery ticket reference", "node", ref.t.node.ID, "serial", ref.t.serial)
topic := ref.topic() topic := ref.topic()
tickets := s.tickets[topic].buckets tickets := s.tickets[topic]
if tickets == nil { if tickets == nil {
log.Warn("Removing tickets from unknown topic", "topic", topic)
return return
} }
bucket := timeBucket(ref.t.regTime[ref.idx] / mclock.AbsTime(ticketTimeBucketLen)) bucket := timeBucket(ref.t.regTime[ref.idx] / mclock.AbsTime(ticketTimeBucketLen))
list := tickets[bucket] list := tickets.buckets[bucket]
idx := -1 idx := -1
for i, bt := range list { for i, bt := range list {
if bt.t == ref.t { if bt.t == ref.t {
@ -442,9 +441,9 @@ func (s *ticketStore) removeTicketRef(ref ticketRef) {
} }
list = append(list[:idx], list[idx+1:]...) list = append(list[:idx], list[idx+1:]...)
if len(list) != 0 { if len(list) != 0 {
tickets[bucket] = list tickets.buckets[bucket] = list
} else { } else {
delete(tickets, bucket) delete(tickets.buckets, bucket)
} }
ref.t.refCnt-- ref.t.refCnt--
if ref.t.refCnt == 0 { if ref.t.refCnt == 0 {
@ -523,21 +522,21 @@ func (s *ticketStore) adjustWithTicket(now mclock.AbsTime, targetHash common.Has
} }
} }
func (s *ticketStore) addTicket(localTime mclock.AbsTime, pingHash []byte, t *ticket) { func (s *ticketStore) addTicket(localTime mclock.AbsTime, pingHash []byte, ticket *ticket) {
debugLog(fmt.Sprintf("add(node = %x sn = %v)", t.node.ID[:8], t.serial)) log.Trace("Adding discovery ticket", "node", ticket.node.ID, "serial", ticket.serial)
lastReq, ok := s.nodeLastReq[t.node] lastReq, ok := s.nodeLastReq[ticket.node]
if !(ok && bytes.Equal(pingHash, lastReq.pingHash)) { if !(ok && bytes.Equal(pingHash, lastReq.pingHash)) {
return return
} }
s.adjustWithTicket(localTime, lastReq.lookup.target, t) s.adjustWithTicket(localTime, lastReq.lookup.target, ticket)
if lastReq.lookup.radiusLookup || s.nodes[t.node] != nil { if lastReq.lookup.radiusLookup || s.nodes[ticket.node] != nil {
return return
} }
topic := lastReq.lookup.topic topic := lastReq.lookup.topic
topicIdx := t.findIdx(topic) topicIdx := ticket.findIdx(topic)
if topicIdx == -1 { if topicIdx == -1 {
return return
} }
@ -548,29 +547,29 @@ func (s *ticketStore) addTicket(localTime mclock.AbsTime, pingHash []byte, t *ti
} }
if _, ok := s.tickets[topic]; ok { if _, ok := s.tickets[topic]; ok {
wait := t.regTime[topicIdx] - localTime wait := ticket.regTime[topicIdx] - localTime
rnd := rand.ExpFloat64() rnd := rand.ExpFloat64()
if rnd > 10 { if rnd > 10 {
rnd = 10 rnd = 10
} }
if float64(wait) < float64(keepTicketConst)+float64(keepTicketExp)*rnd { if float64(wait) < float64(keepTicketConst)+float64(keepTicketExp)*rnd {
// use the ticket to register this topic // use the ticket to register this topic
//fmt.Println("addTicket", t.node.ID[:8], t.node.addr().String(), t.serial, t.pong) //fmt.Println("addTicket", ticket.node.ID[:8], ticket.node.addr().String(), ticket.serial, ticket.pong)
s.addTicketRef(ticketRef{t, topicIdx}) s.addTicketRef(ticketRef{ticket, topicIdx})
} }
} }
if t.refCnt > 0 { if ticket.refCnt > 0 {
s.nextTicketCached = nil s.nextTicketCached = nil
s.nodes[t.node] = t s.nodes[ticket.node] = ticket
} }
} }
func (s *ticketStore) getNodeTicket(node *Node) *ticket { func (s *ticketStore) getNodeTicket(node *Node) *ticket {
if s.nodes[node] == nil { if s.nodes[node] == nil {
debugLog(fmt.Sprintf("getNodeTicket(%x) sn = nil", node.ID[:8])) log.Trace("Retrieving node ticket", "node", node.ID, "serial", nil)
} else { } else {
debugLog(fmt.Sprintf("getNodeTicket(%x) sn = %v", node.ID[:8], s.nodes[node].serial)) log.Trace("Retrieving node ticket", "node", node.ID, "serial", s.nodes[node].serial)
} }
return s.nodes[node] return s.nodes[node]
} }

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