mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
Merge branch 'master' into lean_reindex
This commit is contained in:
commit
be4346a8f9
15 changed files with 205 additions and 63 deletions
|
|
@ -39,6 +39,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/eth/filters"
|
"github.com/ethereum/go-ethereum/eth/filters"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
|
|
@ -401,6 +402,27 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
|
||||||
} else {
|
} else {
|
||||||
hi = b.pendingBlock.GasLimit()
|
hi = b.pendingBlock.GasLimit()
|
||||||
}
|
}
|
||||||
|
// Recap the highest gas allowance with account's balance.
|
||||||
|
if call.GasPrice != nil && call.GasPrice.Uint64() != 0 {
|
||||||
|
balance := b.pendingState.GetBalance(call.From) // from can't be nil
|
||||||
|
available := new(big.Int).Set(balance)
|
||||||
|
if call.Value != nil {
|
||||||
|
if call.Value.Cmp(available) >= 0 {
|
||||||
|
return 0, errors.New("insufficient funds for transfer")
|
||||||
|
}
|
||||||
|
available.Sub(available, call.Value)
|
||||||
|
}
|
||||||
|
allowance := new(big.Int).Div(available, call.GasPrice)
|
||||||
|
if hi > allowance.Uint64() {
|
||||||
|
transfer := call.Value
|
||||||
|
if transfer == nil {
|
||||||
|
transfer = new(big.Int)
|
||||||
|
}
|
||||||
|
log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance,
|
||||||
|
"sent", transfer, "gasprice", call.GasPrice, "fundable", allowance)
|
||||||
|
hi = allowance.Uint64()
|
||||||
|
}
|
||||||
|
}
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -466,6 +466,73 @@ func TestSimulatedBackend_EstimateGas(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSimulatedBackend_EstimateGasWithPrice(t *testing.T) {
|
||||||
|
key, _ := crypto.GenerateKey()
|
||||||
|
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
|
||||||
|
sim := NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(params.Ether*2 + 2e17)}}, 10000000)
|
||||||
|
defer sim.Close()
|
||||||
|
|
||||||
|
receipant := common.HexToAddress("deadbeef")
|
||||||
|
var cases = []struct {
|
||||||
|
name string
|
||||||
|
message ethereum.CallMsg
|
||||||
|
expect uint64
|
||||||
|
expectError error
|
||||||
|
}{
|
||||||
|
{"EstimateWithoutPrice", ethereum.CallMsg{
|
||||||
|
From: addr,
|
||||||
|
To: &receipant,
|
||||||
|
Gas: 0,
|
||||||
|
GasPrice: big.NewInt(0),
|
||||||
|
Value: big.NewInt(1000),
|
||||||
|
Data: nil,
|
||||||
|
}, 21000, nil},
|
||||||
|
|
||||||
|
{"EstimateWithPrice", ethereum.CallMsg{
|
||||||
|
From: addr,
|
||||||
|
To: &receipant,
|
||||||
|
Gas: 0,
|
||||||
|
GasPrice: big.NewInt(1000),
|
||||||
|
Value: big.NewInt(1000),
|
||||||
|
Data: nil,
|
||||||
|
}, 21000, nil},
|
||||||
|
|
||||||
|
{"EstimateWithVeryHighPrice", ethereum.CallMsg{
|
||||||
|
From: addr,
|
||||||
|
To: &receipant,
|
||||||
|
Gas: 0,
|
||||||
|
GasPrice: big.NewInt(1e14), // gascost = 2.1ether
|
||||||
|
Value: big.NewInt(1e17), // the remaining balance for fee is 2.1ether
|
||||||
|
Data: nil,
|
||||||
|
}, 21000, nil},
|
||||||
|
|
||||||
|
{"EstimateWithSuperhighPrice", ethereum.CallMsg{
|
||||||
|
From: addr,
|
||||||
|
To: &receipant,
|
||||||
|
Gas: 0,
|
||||||
|
GasPrice: big.NewInt(2e14), // gascost = 4.2ether
|
||||||
|
Value: big.NewInt(1000),
|
||||||
|
Data: nil,
|
||||||
|
}, 21000, errors.New("gas required exceeds allowance (10999)")}, // 10999=(2.2ether-1000wei)/(2e14)
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
got, err := sim.EstimateGas(context.Background(), c.message)
|
||||||
|
if c.expectError != nil {
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("Expect error, got nil")
|
||||||
|
}
|
||||||
|
if c.expectError.Error() != err.Error() {
|
||||||
|
t.Fatalf("Expect error, want %v, got %v", c.expectError, err)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if got != c.expect {
|
||||||
|
t.Fatalf("Gas estimation mismatch, want %d, got %d", c.expect, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestSimulatedBackend_HeaderByHash(t *testing.T) {
|
func TestSimulatedBackend_HeaderByHash(t *testing.T) {
|
||||||
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
|
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,9 @@ Section "Geth" GETH_IDX
|
||||||
|
|
||||||
# Create start menu launcher
|
# Create start menu launcher
|
||||||
createDirectory "$SMPROGRAMS\${APPNAME}"
|
createDirectory "$SMPROGRAMS\${APPNAME}"
|
||||||
createShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\geth.exe" "--fast" "--cache=512"
|
createShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\geth.exe"
|
||||||
createShortCut "$SMPROGRAMS\${APPNAME}\Attach.lnk" "$INSTDIR\geth.exe" "attach" "" ""
|
createShortCut "$SMPROGRAMS\${APPNAME}\Attach.lnk" "$INSTDIR\geth.exe" "attach"
|
||||||
createShortCut "$SMPROGRAMS\${APPNAME}\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "" ""
|
createShortCut "$SMPROGRAMS\${APPNAME}\Uninstall.lnk" "$INSTDIR\uninstall.exe"
|
||||||
|
|
||||||
# Firewall - remove rules (if exists)
|
# Firewall - remove rules (if exists)
|
||||||
SimpleFC::AdvRemoveRule "Geth incoming peers (TCP:30303)"
|
SimpleFC::AdvRemoveRule "Geth incoming peers (TCP:30303)"
|
||||||
|
|
|
||||||
|
|
@ -61,8 +61,8 @@ var (
|
||||||
utils.UnlockedAccountFlag,
|
utils.UnlockedAccountFlag,
|
||||||
utils.PasswordFileFlag,
|
utils.PasswordFileFlag,
|
||||||
utils.BootnodesFlag,
|
utils.BootnodesFlag,
|
||||||
utils.BootnodesV4Flag,
|
utils.LegacyBootnodesV4Flag,
|
||||||
utils.BootnodesV5Flag,
|
utils.LegacyBootnodesV5Flag,
|
||||||
utils.DataDirFlag,
|
utils.DataDirFlag,
|
||||||
utils.AncientFlag,
|
utils.AncientFlag,
|
||||||
utils.KeyStoreDirFlag,
|
utils.KeyStoreDirFlag,
|
||||||
|
|
|
||||||
|
|
@ -184,8 +184,8 @@ var AppHelpFlagGroups = []flagGroup{
|
||||||
Name: "NETWORKING",
|
Name: "NETWORKING",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
utils.BootnodesFlag,
|
utils.BootnodesFlag,
|
||||||
utils.BootnodesV4Flag,
|
utils.LegacyBootnodesV4Flag,
|
||||||
utils.BootnodesV5Flag,
|
utils.LegacyBootnodesV5Flag,
|
||||||
utils.DNSDiscoveryFlag,
|
utils.DNSDiscoveryFlag,
|
||||||
utils.ListenPortFlag,
|
utils.ListenPortFlag,
|
||||||
utils.MaxPeersFlag,
|
utils.MaxPeersFlag,
|
||||||
|
|
|
||||||
|
|
@ -600,17 +600,7 @@ var (
|
||||||
}
|
}
|
||||||
BootnodesFlag = cli.StringFlag{
|
BootnodesFlag = cli.StringFlag{
|
||||||
Name: "bootnodes",
|
Name: "bootnodes",
|
||||||
Usage: "Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)",
|
Usage: "Comma separated enode URLs for P2P discovery bootstrap",
|
||||||
Value: "",
|
|
||||||
}
|
|
||||||
BootnodesV4Flag = cli.StringFlag{
|
|
||||||
Name: "bootnodesv4",
|
|
||||||
Usage: "Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)",
|
|
||||||
Value: "",
|
|
||||||
}
|
|
||||||
BootnodesV5Flag = cli.StringFlag{
|
|
||||||
Name: "bootnodesv5",
|
|
||||||
Usage: "Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)",
|
|
||||||
Value: "",
|
Value: "",
|
||||||
}
|
}
|
||||||
NodeKeyFileFlag = cli.StringFlag{
|
NodeKeyFileFlag = cli.StringFlag{
|
||||||
|
|
@ -798,9 +788,9 @@ func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
|
||||||
func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
|
func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
|
||||||
urls := params.MainnetBootnodes
|
urls := params.MainnetBootnodes
|
||||||
switch {
|
switch {
|
||||||
case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV4Flag.Name):
|
case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(LegacyBootnodesV4Flag.Name):
|
||||||
if ctx.GlobalIsSet(BootnodesV4Flag.Name) {
|
if ctx.GlobalIsSet(LegacyBootnodesV4Flag.Name) {
|
||||||
urls = splitAndTrim(ctx.GlobalString(BootnodesV4Flag.Name))
|
urls = splitAndTrim(ctx.GlobalString(LegacyBootnodesV4Flag.Name))
|
||||||
} else {
|
} else {
|
||||||
urls = splitAndTrim(ctx.GlobalString(BootnodesFlag.Name))
|
urls = splitAndTrim(ctx.GlobalString(BootnodesFlag.Name))
|
||||||
}
|
}
|
||||||
|
|
@ -830,14 +820,16 @@ func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
|
||||||
// setBootstrapNodesV5 creates a list of bootstrap nodes from the command line
|
// setBootstrapNodesV5 creates a list of bootstrap nodes from the command line
|
||||||
// flags, reverting to pre-configured ones if none have been specified.
|
// flags, reverting to pre-configured ones if none have been specified.
|
||||||
func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) {
|
func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) {
|
||||||
urls := params.DiscoveryV5Bootnodes
|
urls := params.MainnetBootnodes
|
||||||
switch {
|
switch {
|
||||||
case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV5Flag.Name):
|
case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(LegacyBootnodesV5Flag.Name):
|
||||||
if ctx.GlobalIsSet(BootnodesV5Flag.Name) {
|
if ctx.GlobalIsSet(LegacyBootnodesV5Flag.Name) {
|
||||||
urls = splitAndTrim(ctx.GlobalString(BootnodesV5Flag.Name))
|
urls = splitAndTrim(ctx.GlobalString(LegacyBootnodesV5Flag.Name))
|
||||||
} else {
|
} else {
|
||||||
urls = splitAndTrim(ctx.GlobalString(BootnodesFlag.Name))
|
urls = splitAndTrim(ctx.GlobalString(BootnodesFlag.Name))
|
||||||
}
|
}
|
||||||
|
case ctx.GlobalBool(RopstenFlag.Name):
|
||||||
|
urls = params.RopstenBootnodes
|
||||||
case ctx.GlobalBool(RinkebyFlag.Name):
|
case ctx.GlobalBool(RinkebyFlag.Name):
|
||||||
urls = params.RinkebyBootnodes
|
urls = params.RinkebyBootnodes
|
||||||
case ctx.GlobalBool(GoerliFlag.Name):
|
case ctx.GlobalBool(GoerliFlag.Name):
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,16 @@ var (
|
||||||
Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices (deprecated, use --gpo.percentile)",
|
Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices (deprecated, use --gpo.percentile)",
|
||||||
Value: eth.DefaultConfig.GPO.Percentile,
|
Value: eth.DefaultConfig.GPO.Percentile,
|
||||||
}
|
}
|
||||||
|
LegacyBootnodesV4Flag = cli.StringFlag{
|
||||||
|
Name: "bootnodesv4",
|
||||||
|
Usage: "Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes) (deprecated, use --bootnodes)",
|
||||||
|
Value: "",
|
||||||
|
}
|
||||||
|
LegacyBootnodesV5Flag = cli.StringFlag{
|
||||||
|
Name: "bootnodesv5",
|
||||||
|
Usage: "Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes) (deprecated, use --bootnodes)",
|
||||||
|
Value: "",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// showDeprecated displays deprecated flags that will be soon removed from the codebase.
|
// showDeprecated displays deprecated flags that will be soon removed from the codebase.
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,9 @@ func (b *bridge) readPinAndReopenWallet(call jsre.Call) (goja.Value, error) {
|
||||||
// original RPC method (saved in jeth.unlockAccount) with it to actually execute
|
// original RPC method (saved in jeth.unlockAccount) with it to actually execute
|
||||||
// the RPC call.
|
// the RPC call.
|
||||||
func (b *bridge) UnlockAccount(call jsre.Call) (goja.Value, error) {
|
func (b *bridge) UnlockAccount(call jsre.Call) (goja.Value, error) {
|
||||||
|
if nArgs := len(call.Arguments); nArgs < 2 {
|
||||||
|
return nil, fmt.Errorf("usage: unlockAccount(account, [ password, duration ])")
|
||||||
|
}
|
||||||
// Make sure we have an account specified to unlock.
|
// Make sure we have an account specified to unlock.
|
||||||
if call.Argument(0).ExportType().Kind() != reflect.String {
|
if call.Argument(0).ExportType().Kind() != reflect.String {
|
||||||
return nil, fmt.Errorf("first argument must be the account to unlock")
|
return nil, fmt.Errorf("first argument must be the account to unlock")
|
||||||
|
|
@ -272,6 +275,9 @@ func (b *bridge) UnlockAccount(call jsre.Call) (goja.Value, error) {
|
||||||
// prompt to acquire the passphrase and executes the original RPC method (saved in
|
// prompt to acquire the passphrase and executes the original RPC method (saved in
|
||||||
// jeth.sign) with it to actually execute the RPC call.
|
// jeth.sign) with it to actually execute the RPC call.
|
||||||
func (b *bridge) Sign(call jsre.Call) (goja.Value, error) {
|
func (b *bridge) Sign(call jsre.Call) (goja.Value, error) {
|
||||||
|
if nArgs := len(call.Arguments); nArgs < 2 {
|
||||||
|
return nil, fmt.Errorf("usage: sign(message, account, [ password ])")
|
||||||
|
}
|
||||||
var (
|
var (
|
||||||
message = call.Argument(0)
|
message = call.Argument(0)
|
||||||
account = call.Argument(1)
|
account = call.Argument(1)
|
||||||
|
|
@ -307,6 +313,9 @@ func (b *bridge) Sign(call jsre.Call) (goja.Value, error) {
|
||||||
|
|
||||||
// Sleep will block the console for the specified number of seconds.
|
// Sleep will block the console for the specified number of seconds.
|
||||||
func (b *bridge) Sleep(call jsre.Call) (goja.Value, error) {
|
func (b *bridge) Sleep(call jsre.Call) (goja.Value, error) {
|
||||||
|
if nArgs := len(call.Arguments); nArgs < 1 {
|
||||||
|
return nil, fmt.Errorf("usage: sleep(<number of seconds>)")
|
||||||
|
}
|
||||||
if !isNumber(call.Argument(0)) {
|
if !isNumber(call.Argument(0)) {
|
||||||
return nil, fmt.Errorf("usage: sleep(<number of seconds>)")
|
return nil, fmt.Errorf("usage: sleep(<number of seconds>)")
|
||||||
}
|
}
|
||||||
|
|
@ -334,7 +343,7 @@ func (b *bridge) SleepBlocks(call jsre.Call) (goja.Value, error) {
|
||||||
blocks = call.Argument(0).ToInteger()
|
blocks = call.Argument(0).ToInteger()
|
||||||
}
|
}
|
||||||
if nArgs >= 2 {
|
if nArgs >= 2 {
|
||||||
if isNumber(call.Argument(1)) {
|
if !isNumber(call.Argument(1)) {
|
||||||
return nil, fmt.Errorf("expected number as second argument")
|
return nil, fmt.Errorf("expected number as second argument")
|
||||||
}
|
}
|
||||||
sleep = call.Argument(1).ToInteger()
|
sleep = call.Argument(1).ToInteger()
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,10 @@ type freezerdb struct {
|
||||||
// the slow ancient tables.
|
// the slow ancient tables.
|
||||||
func (frdb *freezerdb) Close() error {
|
func (frdb *freezerdb) Close() error {
|
||||||
var errs []error
|
var errs []error
|
||||||
if err := frdb.KeyValueStore.Close(); err != nil {
|
if err := frdb.AncientStore.Close(); err != nil {
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
}
|
}
|
||||||
if err := frdb.AncientStore.Close(); err != nil {
|
if err := frdb.KeyValueStore.Close(); err != nil {
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
}
|
}
|
||||||
if len(errs) != 0 {
|
if len(errs) != 0 {
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,7 @@ type freezer struct {
|
||||||
|
|
||||||
tables map[string]*freezerTable // Data tables for storing everything
|
tables map[string]*freezerTable // Data tables for storing everything
|
||||||
instanceLock fileutil.Releaser // File-system lock to prevent double opens
|
instanceLock fileutil.Releaser // File-system lock to prevent double opens
|
||||||
|
quit chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// newFreezer creates a chain freezer that moves ancient chain data into
|
// newFreezer creates a chain freezer that moves ancient chain data into
|
||||||
|
|
@ -101,6 +102,7 @@ func newFreezer(datadir string, namespace string) (*freezer, error) {
|
||||||
freezer := &freezer{
|
freezer := &freezer{
|
||||||
tables: make(map[string]*freezerTable),
|
tables: make(map[string]*freezerTable),
|
||||||
instanceLock: lock,
|
instanceLock: lock,
|
||||||
|
quit: make(chan struct{}),
|
||||||
}
|
}
|
||||||
for name, disableSnappy := range freezerNoSnappy {
|
for name, disableSnappy := range freezerNoSnappy {
|
||||||
table, err := newTable(datadir, name, readMeter, writeMeter, sizeGauge, disableSnappy)
|
table, err := newTable(datadir, name, readMeter, writeMeter, sizeGauge, disableSnappy)
|
||||||
|
|
@ -126,6 +128,7 @@ func newFreezer(datadir string, namespace string) (*freezer, error) {
|
||||||
|
|
||||||
// Close terminates the chain freezer, unmapping all the data files.
|
// Close terminates the chain freezer, unmapping all the data files.
|
||||||
func (f *freezer) Close() error {
|
func (f *freezer) Close() error {
|
||||||
|
f.quit <- struct{}{}
|
||||||
var errs []error
|
var errs []error
|
||||||
for _, table := range f.tables {
|
for _, table := range f.tables {
|
||||||
if err := table.Close(); err != nil {
|
if err := table.Close(); err != nil {
|
||||||
|
|
@ -254,35 +257,50 @@ func (f *freezer) Sync() error {
|
||||||
func (f *freezer) freeze(db ethdb.KeyValueStore) {
|
func (f *freezer) freeze(db ethdb.KeyValueStore) {
|
||||||
nfdb := &nofreezedb{KeyValueStore: db}
|
nfdb := &nofreezedb{KeyValueStore: db}
|
||||||
|
|
||||||
|
backoff := false
|
||||||
for {
|
for {
|
||||||
|
select {
|
||||||
|
case <-f.quit:
|
||||||
|
log.Info("Freezer shutting down")
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
if backoff {
|
||||||
|
select {
|
||||||
|
case <-time.NewTimer(freezerRecheckInterval).C:
|
||||||
|
backoff = false
|
||||||
|
case <-f.quit:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
// Retrieve the freezing threshold.
|
// Retrieve the freezing threshold.
|
||||||
hash := ReadHeadBlockHash(nfdb)
|
hash := ReadHeadBlockHash(nfdb)
|
||||||
if hash == (common.Hash{}) {
|
if hash == (common.Hash{}) {
|
||||||
log.Debug("Current full block hash unavailable") // new chain, empty database
|
log.Debug("Current full block hash unavailable") // new chain, empty database
|
||||||
time.Sleep(freezerRecheckInterval)
|
backoff = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
number := ReadHeaderNumber(nfdb, hash)
|
number := ReadHeaderNumber(nfdb, hash)
|
||||||
switch {
|
switch {
|
||||||
case number == nil:
|
case number == nil:
|
||||||
log.Error("Current full block number unavailable", "hash", hash)
|
log.Error("Current full block number unavailable", "hash", hash)
|
||||||
time.Sleep(freezerRecheckInterval)
|
backoff = true
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case *number < params.ImmutabilityThreshold:
|
case *number < params.ImmutabilityThreshold:
|
||||||
log.Debug("Current full block not old enough", "number", *number, "hash", hash, "delay", params.ImmutabilityThreshold)
|
log.Debug("Current full block not old enough", "number", *number, "hash", hash, "delay", params.ImmutabilityThreshold)
|
||||||
time.Sleep(freezerRecheckInterval)
|
backoff = true
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case *number-params.ImmutabilityThreshold <= f.frozen:
|
case *number-params.ImmutabilityThreshold <= f.frozen:
|
||||||
log.Debug("Ancient blocks frozen already", "number", *number, "hash", hash, "frozen", f.frozen)
|
log.Debug("Ancient blocks frozen already", "number", *number, "hash", hash, "frozen", f.frozen)
|
||||||
time.Sleep(freezerRecheckInterval)
|
backoff = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
head := ReadHeader(nfdb, hash, *number)
|
head := ReadHeader(nfdb, hash, *number)
|
||||||
if head == nil {
|
if head == nil {
|
||||||
log.Error("Current full block unavailable", "number", *number, "hash", hash)
|
log.Error("Current full block unavailable", "number", *number, "hash", hash)
|
||||||
time.Sleep(freezerRecheckInterval)
|
backoff = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Seems we have data ready to be frozen, process in usable batches
|
// Seems we have data ready to be frozen, process in usable batches
|
||||||
|
|
@ -369,7 +387,7 @@ func (f *freezer) freeze(db ethdb.KeyValueStore) {
|
||||||
|
|
||||||
// Avoid database thrashing with tiny writes
|
// Avoid database thrashing with tiny writes
|
||||||
if f.frozen-first < freezerBatchLimit {
|
if f.frozen-first < freezerBatchLimit {
|
||||||
time.Sleep(freezerRecheckInterval)
|
backoff = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -454,6 +454,23 @@ func (s *stateObject) Code(db Database) []byte {
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CodeSize returns the size of the contract code associated with this object,
|
||||||
|
// or zero if none. This methos is an almost mirror of Code, but uses a cache
|
||||||
|
// inside the database to avoid loading codes seen recently.
|
||||||
|
func (s *stateObject) CodeSize(db Database) int {
|
||||||
|
if s.code != nil {
|
||||||
|
return len(s.code)
|
||||||
|
}
|
||||||
|
if bytes.Equal(s.CodeHash(), emptyCodeHash) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
size, err := db.ContractCodeSize(s.addrHash, common.BytesToHash(s.CodeHash()))
|
||||||
|
if err != nil {
|
||||||
|
s.setError(fmt.Errorf("can't load code size %x: %v", s.CodeHash(), err))
|
||||||
|
}
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
func (s *stateObject) SetCode(codeHash common.Hash, code []byte) {
|
func (s *stateObject) SetCode(codeHash common.Hash, code []byte) {
|
||||||
prevcode := s.Code(s.db.db)
|
prevcode := s.Code(s.db.db)
|
||||||
s.db.journal.append(codeChange{
|
s.db.journal.append(codeChange{
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
@ -289,20 +288,10 @@ func (s *StateDB) GetCode(addr common.Address) []byte {
|
||||||
|
|
||||||
func (s *StateDB) GetCodeSize(addr common.Address) int {
|
func (s *StateDB) GetCodeSize(addr common.Address) int {
|
||||||
stateObject := s.getStateObject(addr)
|
stateObject := s.getStateObject(addr)
|
||||||
if stateObject == nil {
|
if stateObject != nil {
|
||||||
return 0
|
return stateObject.CodeSize(s.db)
|
||||||
}
|
}
|
||||||
if stateObject.code != nil {
|
return 0
|
||||||
return len(stateObject.code)
|
|
||||||
}
|
|
||||||
if bytes.Equal(stateObject.CodeHash(), emptyCode[:]) {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
size, err := s.db.ContractCodeSize(stateObject.addrHash, common.BytesToHash(stateObject.CodeHash()))
|
|
||||||
if err != nil {
|
|
||||||
s.setError(fmt.Errorf("GetCodeSize (%x) error: %v", addr[:], err))
|
|
||||||
}
|
|
||||||
return size
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StateDB) GetCodeHash(addr common.Address) common.Hash {
|
func (s *StateDB) GetCodeHash(addr common.Address) common.Hash {
|
||||||
|
|
|
||||||
|
|
@ -906,6 +906,11 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNrOrHash
|
||||||
hi uint64
|
hi uint64
|
||||||
cap uint64
|
cap uint64
|
||||||
)
|
)
|
||||||
|
// Use zero address if sender unspecified.
|
||||||
|
if args.From == nil {
|
||||||
|
args.From = new(common.Address)
|
||||||
|
}
|
||||||
|
// Determine the highest gas limit can be used during the estimation.
|
||||||
if args.Gas != nil && uint64(*args.Gas) >= params.TxGas {
|
if args.Gas != nil && uint64(*args.Gas) >= params.TxGas {
|
||||||
hi = uint64(*args.Gas)
|
hi = uint64(*args.Gas)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -916,16 +921,38 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNrOrHash
|
||||||
}
|
}
|
||||||
hi = block.GasLimit()
|
hi = block.GasLimit()
|
||||||
}
|
}
|
||||||
|
// Recap the highest gas limit with account's available balance.
|
||||||
|
if args.GasPrice != nil && args.GasPrice.ToInt().Uint64() != 0 {
|
||||||
|
state, _, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
balance := state.GetBalance(*args.From) // from can't be nil
|
||||||
|
available := new(big.Int).Set(balance)
|
||||||
|
if args.Value != nil {
|
||||||
|
if args.Value.ToInt().Cmp(available) >= 0 {
|
||||||
|
return 0, errors.New("insufficient funds for transfer")
|
||||||
|
}
|
||||||
|
available.Sub(available, args.Value.ToInt())
|
||||||
|
}
|
||||||
|
allowance := new(big.Int).Div(available, args.GasPrice.ToInt())
|
||||||
|
if hi > allowance.Uint64() {
|
||||||
|
transfer := args.Value
|
||||||
|
if transfer == nil {
|
||||||
|
transfer = new(hexutil.Big)
|
||||||
|
}
|
||||||
|
log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance,
|
||||||
|
"sent", transfer.ToInt(), "gasprice", args.GasPrice.ToInt(), "fundable", allowance)
|
||||||
|
hi = allowance.Uint64()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Recap the highest gas allowance with specified gascap.
|
||||||
if gasCap != nil && hi > gasCap.Uint64() {
|
if gasCap != nil && hi > gasCap.Uint64() {
|
||||||
log.Warn("Caller gas above allowance, capping", "requested", hi, "cap", gasCap)
|
log.Warn("Caller gas above allowance, capping", "requested", hi, "cap", gasCap)
|
||||||
hi = gasCap.Uint64()
|
hi = gasCap.Uint64()
|
||||||
}
|
}
|
||||||
cap = hi
|
cap = hi
|
||||||
|
|
||||||
// Use zero address if sender unspecified.
|
|
||||||
if args.From == nil {
|
|
||||||
args.From = new(common.Address)
|
|
||||||
}
|
|
||||||
// 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, *core.ExecutionResult, error) {
|
executable := func(gas uint64) (bool, *core.ExecutionResult, error) {
|
||||||
args.Gas = (*hexutil.Uint64)(&gas)
|
args.Gas = (*hexutil.Uint64)(&gas)
|
||||||
|
|
|
||||||
|
|
@ -62,8 +62,8 @@ func GoerliGenesis() string {
|
||||||
// FoundationBootnodes returns the enode URLs of the P2P bootstrap nodes operated
|
// FoundationBootnodes returns the enode URLs of the P2P bootstrap nodes operated
|
||||||
// by the foundation running the V5 discovery protocol.
|
// by the foundation running the V5 discovery protocol.
|
||||||
func FoundationBootnodes() *Enodes {
|
func FoundationBootnodes() *Enodes {
|
||||||
nodes := &Enodes{nodes: make([]*discv5.Node, len(params.DiscoveryV5Bootnodes))}
|
nodes := &Enodes{nodes: make([]*discv5.Node, len(params.MainnetBootnodes))}
|
||||||
for i, url := range params.DiscoveryV5Bootnodes {
|
for i, url := range params.MainnetBootnodes {
|
||||||
nodes.nodes[i] = discv5.MustParseNode(url)
|
nodes.nodes[i] = discv5.MustParseNode(url)
|
||||||
}
|
}
|
||||||
return nodes
|
return nodes
|
||||||
|
|
|
||||||
|
|
@ -63,15 +63,6 @@ var GoerliBootnodes = []string{
|
||||||
"enode://a61215641fb8714a373c80edbfa0ea8878243193f57c96eeb44d0bc019ef295abd4e044fd619bfc4c59731a73fb79afe84e9ab6da0c743ceb479cbb6d263fa91@3.11.147.67:30303",
|
"enode://a61215641fb8714a373c80edbfa0ea8878243193f57c96eeb44d0bc019ef295abd4e044fd619bfc4c59731a73fb79afe84e9ab6da0c743ceb479cbb6d263fa91@3.11.147.67:30303",
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiscoveryV5Bootnodes are the enode URLs of the P2P bootstrap nodes for the
|
|
||||||
// experimental RLPx v5 topic-discovery network.
|
|
||||||
var DiscoveryV5Bootnodes = []string{
|
|
||||||
"enode://06051a5573c81934c9554ef2898eb13b33a34b94cf36b202b69fde139ca17a85051979867720d4bdae4323d4943ddf9aeeb6643633aa656e0be843659795007a@35.177.226.168:30303",
|
|
||||||
"enode://0cc5f5ffb5d9098c8b8c62325f3797f56509bff942704687b6530992ac706e2cb946b90a34f1f19548cd3c7baccbcaea354531e5983c7d1bc0dee16ce4b6440b@40.118.3.223:30304",
|
|
||||||
"enode://1c7a64d76c0334b0418c004af2f67c50e36a3be60b5e4790bdac0439d21603469a85fad36f2473c9a80eb043ae60936df905fa28f1ff614c3e5dc34f15dcd2dc@40.118.3.223:30306",
|
|
||||||
"enode://85c85d7143ae8bb96924f2b54f1b3e70d8c4d367af305325d30a61385a432f247d2c75c45c6b4a60335060d072d7f5b35dd1d4c45f76941f62a4f83b6e75daaf@40.118.3.223:30307",
|
|
||||||
}
|
|
||||||
|
|
||||||
const dnsPrefix = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@"
|
const dnsPrefix = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@"
|
||||||
|
|
||||||
// These DNS names provide bootstrap connectivity for public testnets and the mainnet.
|
// These DNS names provide bootstrap connectivity for public testnets and the mainnet.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue