mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 22:56:43 +00:00
Merge branch 'master' of https://github.com/ethereum/go-ethereum into 3498
This commit is contained in:
commit
4e002e78e6
59 changed files with 539 additions and 333 deletions
|
|
@ -65,10 +65,11 @@ matrix:
|
||||||
|
|
||||||
# Build the Android archive and upload it to Maven Central and Azure
|
# Build the Android archive and upload it to Maven Central and Azure
|
||||||
- brew update
|
- brew update
|
||||||
- brew install android-sdk maven gpg
|
- travis_wait 60 brew install android-sdk android-ndk maven gpg
|
||||||
- alias gpg="gpg2"
|
- alias gpg="gpg2"
|
||||||
|
|
||||||
- export ANDROID_HOME=/usr/local/opt/android-sdk
|
- export ANDROID_HOME=/usr/local/opt/android-sdk
|
||||||
|
- export ANDROID_NDK=/usr/local/opt/android-ndk
|
||||||
- echo "y" | android update sdk --no-ui --filter `android list sdk | grep "SDK Platform Android" | grep -E 'API 15|API 19|API 24' | awk '{print $1}' | cut -d '-' -f 1 | tr '\n' ','`
|
- echo "y" | android update sdk --no-ui --filter `android list sdk | grep "SDK Platform Android" | grep -E 'API 15|API 19|API 24' | awk '{print $1}' | cut -d '-' -f 1 | tr '\n' ','`
|
||||||
|
|
||||||
- go run build/ci.go aar -signer ANDROID_SIGNING_KEY -deploy https://oss.sonatype.org -upload gethstore/builds
|
- go run build/ci.go aar -signer ANDROID_SIGNING_KEY -deploy https://oss.sonatype.org -upload gethstore/builds
|
||||||
|
|
|
||||||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
1.5.7
|
1.5.8
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ type SimulatedBackend struct {
|
||||||
func NewSimulatedBackend(accounts ...core.GenesisAccount) *SimulatedBackend {
|
func NewSimulatedBackend(accounts ...core.GenesisAccount) *SimulatedBackend {
|
||||||
database, _ := ethdb.NewMemDatabase()
|
database, _ := ethdb.NewMemDatabase()
|
||||||
core.WriteGenesisBlockForTesting(database, accounts...)
|
core.WriteGenesisBlockForTesting(database, accounts...)
|
||||||
blockchain, _ := core.NewBlockChain(database, chainConfig, new(core.FakePow), new(event.TypeMux))
|
blockchain, _ := core.NewBlockChain(database, chainConfig, new(core.FakePow), new(event.TypeMux), vm.Config{})
|
||||||
backend := &SimulatedBackend{database: database, blockchain: blockchain}
|
backend := &SimulatedBackend{database: database, blockchain: blockchain}
|
||||||
backend.rollback()
|
backend.rollback()
|
||||||
return backend
|
return backend
|
||||||
|
|
@ -201,10 +201,32 @@ func (b *SimulatedBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error
|
||||||
func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (*big.Int, error) {
|
func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (*big.Int, error) {
|
||||||
b.mu.Lock()
|
b.mu.Lock()
|
||||||
defer b.mu.Unlock()
|
defer b.mu.Unlock()
|
||||||
defer b.pendingState.RevertToSnapshot(b.pendingState.Snapshot())
|
|
||||||
|
|
||||||
|
// Binary search the gas requirement, as it may be higher than the amount used
|
||||||
|
var lo, hi uint64
|
||||||
|
if call.Gas != nil {
|
||||||
|
hi = call.Gas.Uint64()
|
||||||
|
} else {
|
||||||
|
hi = b.pendingBlock.GasLimit().Uint64()
|
||||||
|
}
|
||||||
|
for lo+1 < hi {
|
||||||
|
// Take a guess at the gas, and check transaction validity
|
||||||
|
mid := (hi + lo) / 2
|
||||||
|
call.Gas = new(big.Int).SetUint64(mid)
|
||||||
|
|
||||||
|
snapshot := b.pendingState.Snapshot()
|
||||||
_, gas, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState)
|
_, gas, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState)
|
||||||
return gas, err
|
b.pendingState.RevertToSnapshot(snapshot)
|
||||||
|
|
||||||
|
// If the transaction became invalid or used all the gas (failed), raise the gas limit
|
||||||
|
if err != nil || gas.Cmp(call.Gas) == 0 {
|
||||||
|
lo = mid
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Otherwise assume the transaction succeeded, lower the gas limit
|
||||||
|
hi = mid
|
||||||
|
}
|
||||||
|
return new(big.Int).SetUint64(hi), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// callContract implemens common code between normal and pending contract calls.
|
// callContract implemens common code between normal and pending contract calls.
|
||||||
|
|
|
||||||
|
|
@ -365,6 +365,49 @@ var bindTests = []struct {
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
|
// Tests that gas estimation works for contracts with weird gas mechanics too.
|
||||||
|
{
|
||||||
|
`FunkyGasPattern`,
|
||||||
|
`
|
||||||
|
contract FunkyGasPattern {
|
||||||
|
string public field;
|
||||||
|
|
||||||
|
function SetField(string value) {
|
||||||
|
// This check will screw gas estimation! Good, good!
|
||||||
|
if (msg.gas < 100000) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
field = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
`606060405261021c806100126000396000f3606060405260e060020a600035046323fcf32a81146100265780634f28bf0e1461007b575b005b6040805160206004803580820135601f8101849004840285018401909552848452610024949193602493909291840191908190840183828082843750949650505050505050620186a05a101561014e57610002565b6100db60008054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281529291908301828280156102145780601f106101e957610100808354040283529160200191610214565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f16801561013b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b505050565b8060006000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106101b557805160ff19168380011785555b506101499291505b808211156101e557600081556001016101a1565b82800160010185558215610199579182015b828111156101995782518260005055916020019190600101906101c7565b5090565b820191906000526020600020905b8154815290600101906020018083116101f757829003601f168201915b50505050508156`,
|
||||||
|
`[{"constant":false,"inputs":[{"name":"value","type":"string"}],"name":"SetField","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"field","outputs":[{"name":"","type":"string"}],"type":"function"}]`,
|
||||||
|
`
|
||||||
|
// Generate a new random account and a funded simulator
|
||||||
|
key, _ := crypto.GenerateKey()
|
||||||
|
auth := bind.NewKeyedTransactor(key)
|
||||||
|
sim := backends.NewSimulatedBackend(core.GenesisAccount{Address: auth.From, Balance: big.NewInt(10000000000)})
|
||||||
|
|
||||||
|
// Deploy a funky gas pattern contract
|
||||||
|
_, _, limiter, err := DeployFunkyGasPattern(auth, sim)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to deploy funky contract: %v", err)
|
||||||
|
}
|
||||||
|
sim.Commit()
|
||||||
|
|
||||||
|
// Set the field with automatic estimation and check that it succeeds
|
||||||
|
auth.GasLimit = nil
|
||||||
|
if _, err := limiter.SetField(auth, "automatic"); err != nil {
|
||||||
|
t.Fatalf("Failed to call automatically gased transaction: %v", err)
|
||||||
|
}
|
||||||
|
sim.Commit()
|
||||||
|
|
||||||
|
if field, _ := limiter.Field(nil); field != "automatic" {
|
||||||
|
t.Fatalf("Field mismatch: have %v, want %v", field, "automatic")
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that packages generated by the binder can be successfully compiled and
|
// Tests that packages generated by the binder can be successfully compiled and
|
||||||
|
|
|
||||||
|
|
@ -113,9 +113,9 @@ func (am *Manager) Accounts() []Account {
|
||||||
return am.cache.accounts()
|
return am.cache.accounts()
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteAccount deletes the key matched by account if the passphrase is correct.
|
// Delete deletes the key matched by account if the passphrase is correct.
|
||||||
// If a contains no filename, the address must match a unique key.
|
// If the account contains no filename, the address must match a unique key.
|
||||||
func (am *Manager) DeleteAccount(a Account, passphrase string) error {
|
func (am *Manager) Delete(a Account, passphrase string) error {
|
||||||
// Decrypting the key isn't really necessary, but we do
|
// Decrypting the key isn't really necessary, but we do
|
||||||
// it anyway to check the password and zero out the key
|
// it anyway to check the password and zero out the key
|
||||||
// immediately afterwards.
|
// immediately afterwards.
|
||||||
|
|
|
||||||
|
|
@ -53,14 +53,14 @@ func TestManager(t *testing.T) {
|
||||||
if err := am.Update(a, "foo", "bar"); err != nil {
|
if err := am.Update(a, "foo", "bar"); err != nil {
|
||||||
t.Errorf("Update error: %v", err)
|
t.Errorf("Update error: %v", err)
|
||||||
}
|
}
|
||||||
if err := am.DeleteAccount(a, "bar"); err != nil {
|
if err := am.Delete(a, "bar"); err != nil {
|
||||||
t.Errorf("DeleteAccount error: %v", err)
|
t.Errorf("Delete error: %v", err)
|
||||||
}
|
}
|
||||||
if common.FileExist(a.File) {
|
if common.FileExist(a.File) {
|
||||||
t.Errorf("account file %s should be gone after DeleteAccount", a.File)
|
t.Errorf("account file %s should be gone after Delete", a.File)
|
||||||
}
|
}
|
||||||
if am.HasAddress(a.Address) {
|
if am.HasAddress(a.Address) {
|
||||||
t.Errorf("HasAccount(%x) should've returned true after DeleteAccount", a.Address)
|
t.Errorf("HasAccount(%x) should've returned true after Delete", a.Address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -700,9 +700,16 @@ func doAndroidArchive(cmdline []string) {
|
||||||
flag.CommandLine.Parse(cmdline)
|
flag.CommandLine.Parse(cmdline)
|
||||||
env := build.Env()
|
env := build.Env()
|
||||||
|
|
||||||
|
// Sanity check that the SDK and NDK are installed and set
|
||||||
|
if os.Getenv("ANDROID_HOME") == "" {
|
||||||
|
log.Fatal("Please ensure ANDROID_HOME points to your Android SDK")
|
||||||
|
}
|
||||||
|
if os.Getenv("ANDROID_NDK") == "" {
|
||||||
|
log.Fatal("Please ensure ANDROID_NDK points to your Android NDK")
|
||||||
|
}
|
||||||
// Build the Android archive and Maven resources
|
// Build the Android archive and Maven resources
|
||||||
build.MustRun(goTool("get", "golang.org/x/mobile/cmd/gomobile"))
|
build.MustRun(goTool("get", "golang.org/x/mobile/cmd/gomobile"))
|
||||||
build.MustRun(gomobileTool("init"))
|
build.MustRun(gomobileTool("init", "--ndk", os.Getenv("ANDROID_NDK")))
|
||||||
build.MustRun(gomobileTool("bind", "--target", "android", "--javapkg", "org.ethereum", "-v", "github.com/ethereum/go-ethereum/mobile"))
|
build.MustRun(gomobileTool("bind", "--target", "android", "--javapkg", "org.ethereum", "-v", "github.com/ethereum/go-ethereum/mobile"))
|
||||||
|
|
||||||
if *local {
|
if *local {
|
||||||
|
|
|
||||||
|
|
@ -161,6 +161,7 @@ func run(ctx *cli.Context) error {
|
||||||
Value: common.Big(ctx.GlobalString(ValueFlag.Name)),
|
Value: common.Big(ctx.GlobalString(ValueFlag.Name)),
|
||||||
EVMConfig: vm.Config{
|
EVMConfig: vm.Config{
|
||||||
Tracer: logger,
|
Tracer: logger,
|
||||||
|
Debug: ctx.GlobalBool(DebugFlag.Name),
|
||||||
DisableGasMetering: ctx.GlobalBool(DisableGasMeteringFlag.Name),
|
DisableGasMetering: ctx.GlobalBool(DisableGasMeteringFlag.Name),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
@ -176,6 +177,7 @@ func run(ctx *cli.Context) error {
|
||||||
Value: common.Big(ctx.GlobalString(ValueFlag.Name)),
|
Value: common.Big(ctx.GlobalString(ValueFlag.Name)),
|
||||||
EVMConfig: vm.Config{
|
EVMConfig: vm.Config{
|
||||||
Tracer: logger,
|
Tracer: logger,
|
||||||
|
Debug: ctx.GlobalBool(DebugFlag.Name),
|
||||||
DisableGasMetering: ctx.GlobalBool(DisableGasMeteringFlag.Name),
|
DisableGasMetering: ctx.GlobalBool(DisableGasMeteringFlag.Name),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,6 @@ func init() {
|
||||||
utils.AutoDAGFlag,
|
utils.AutoDAGFlag,
|
||||||
utils.TargetGasLimitFlag,
|
utils.TargetGasLimitFlag,
|
||||||
utils.NATFlag,
|
utils.NATFlag,
|
||||||
utils.NatspecEnabledFlag,
|
|
||||||
utils.NoDiscoverFlag,
|
utils.NoDiscoverFlag,
|
||||||
utils.DiscoveryV5Flag,
|
utils.DiscoveryV5Flag,
|
||||||
utils.NetrestrictFlag,
|
utils.NetrestrictFlag,
|
||||||
|
|
@ -132,6 +131,7 @@ func init() {
|
||||||
utils.VMForceJitFlag,
|
utils.VMForceJitFlag,
|
||||||
utils.VMJitCacheFlag,
|
utils.VMJitCacheFlag,
|
||||||
utils.VMEnableJitFlag,
|
utils.VMEnableJitFlag,
|
||||||
|
utils.VMEnableDebugFlag,
|
||||||
utils.NetworkIdFlag,
|
utils.NetworkIdFlag,
|
||||||
utils.RPCCORSDomainFlag,
|
utils.RPCCORSDomainFlag,
|
||||||
utils.EthStatsURLFlag,
|
utils.EthStatsURLFlag,
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,7 @@ var AppHelpFlagGroups = []flagGroup{
|
||||||
utils.VMEnableJitFlag,
|
utils.VMEnableJitFlag,
|
||||||
utils.VMForceJitFlag,
|
utils.VMForceJitFlag,
|
||||||
utils.VMJitCacheFlag,
|
utils.VMJitCacheFlag,
|
||||||
|
utils.VMEnableDebugFlag,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -169,7 +170,6 @@ var AppHelpFlagGroups = []flagGroup{
|
||||||
Name: "EXPERIMENTAL",
|
Name: "EXPERIMENTAL",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
utils.WhisperEnabledFlag,
|
utils.WhisperEnabledFlag,
|
||||||
utils.NatspecEnabledFlag,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ import (
|
||||||
"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/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
|
@ -130,10 +131,6 @@ var (
|
||||||
Name: "identity",
|
Name: "identity",
|
||||||
Usage: "Custom node name",
|
Usage: "Custom node name",
|
||||||
}
|
}
|
||||||
NatspecEnabledFlag = cli.BoolFlag{
|
|
||||||
Name: "natspec",
|
|
||||||
Usage: "Enable NatSpec confirmation notice",
|
|
||||||
}
|
|
||||||
DocRootFlag = DirectoryFlag{
|
DocRootFlag = DirectoryFlag{
|
||||||
Name: "docroot",
|
Name: "docroot",
|
||||||
Usage: "Document Root for HTTPClient file scheme",
|
Usage: "Document Root for HTTPClient file scheme",
|
||||||
|
|
@ -230,6 +227,10 @@ var (
|
||||||
Name: "jitvm",
|
Name: "jitvm",
|
||||||
Usage: "Enable the JIT VM",
|
Usage: "Enable the JIT VM",
|
||||||
}
|
}
|
||||||
|
VMEnableDebugFlag = cli.BoolFlag{
|
||||||
|
Name: "vmdebug",
|
||||||
|
Usage: "Record information useful for VM and contract debugging",
|
||||||
|
}
|
||||||
// Logging and debug settings
|
// Logging and debug settings
|
||||||
EthStatsURLFlag = cli.StringFlag{
|
EthStatsURLFlag = cli.StringFlag{
|
||||||
Name: "ethstats",
|
Name: "ethstats",
|
||||||
|
|
@ -730,7 +731,6 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
|
||||||
NetworkId: ctx.GlobalInt(NetworkIdFlag.Name),
|
NetworkId: ctx.GlobalInt(NetworkIdFlag.Name),
|
||||||
MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name),
|
MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name),
|
||||||
ExtraData: MakeMinerExtra(extra, ctx),
|
ExtraData: MakeMinerExtra(extra, ctx),
|
||||||
NatSpec: ctx.GlobalBool(NatspecEnabledFlag.Name),
|
|
||||||
DocRoot: ctx.GlobalString(DocRootFlag.Name),
|
DocRoot: ctx.GlobalString(DocRootFlag.Name),
|
||||||
GasPrice: common.String2Big(ctx.GlobalString(GasPriceFlag.Name)),
|
GasPrice: common.String2Big(ctx.GlobalString(GasPriceFlag.Name)),
|
||||||
GpoMinGasPrice: common.String2Big(ctx.GlobalString(GpoMinGasPriceFlag.Name)),
|
GpoMinGasPrice: common.String2Big(ctx.GlobalString(GpoMinGasPriceFlag.Name)),
|
||||||
|
|
@ -741,6 +741,7 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
|
||||||
GpobaseCorrectionFactor: ctx.GlobalInt(GpobaseCorrectionFactorFlag.Name),
|
GpobaseCorrectionFactor: ctx.GlobalInt(GpobaseCorrectionFactorFlag.Name),
|
||||||
SolcPath: ctx.GlobalString(SolcPathFlag.Name),
|
SolcPath: ctx.GlobalString(SolcPathFlag.Name),
|
||||||
AutoDAG: ctx.GlobalBool(AutoDAGFlag.Name) || ctx.GlobalBool(MiningEnabledFlag.Name),
|
AutoDAG: ctx.GlobalBool(AutoDAGFlag.Name) || ctx.GlobalBool(MiningEnabledFlag.Name),
|
||||||
|
EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override any default configs in dev mode or the test net
|
// Override any default configs in dev mode or the test net
|
||||||
|
|
@ -912,7 +913,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai
|
||||||
if !ctx.GlobalBool(FakePoWFlag.Name) {
|
if !ctx.GlobalBool(FakePoWFlag.Name) {
|
||||||
pow = ethash.New()
|
pow = ethash.New()
|
||||||
}
|
}
|
||||||
chain, err = core.NewBlockChain(chainDb, chainConfig, pow, new(event.TypeMux))
|
chain, err = core.NewBlockChain(chainDb, chainConfig, pow, new(event.TypeMux), vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("Could not start chainmanager: %v", err)
|
Fatalf("Could not start chainmanager: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ contract test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
testInfo = `{"source":"\ncontract test {\n /// @notice Will multiply ` + "`a`" + ` by 7.\n function multiply(uint a) returns(uint d) {\n return a * 7;\n }\n}\n","language":"Solidity","languageVersion":"0.1.1","compilerVersion":"0.1.1","compilerOptions":"--binary file --json-abi file --natspec-user file --natspec-dev file --add-std 1","abiDefinition":[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"type":"function"}],"userDoc":{"methods":{"multiply(uint256)":{"notice":"Will multiply ` + "`a`" + ` by 7."}}},"developerDoc":{"methods":{}}}`
|
testInfo = `{"source":"\ncontract test {\n /// @notice Will multiply ` + "`a`" + ` by 7.\n function multiply(uint a) returns(uint d) {\n return a * 7;\n }\n}\n","language":"Solidity","languageVersion":"0.1.1","compilerVersion":"0.1.1","compilerOptions":"--binary file --json-abi file --add-std 1","abiDefinition":[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"type":"function"}],"userDoc":{"methods":{"multiply(uint256)":{"notice":"Will multiply ` + "`a`" + ` by 7."}}},"developerDoc":{"methods":{}}}`
|
||||||
)
|
)
|
||||||
|
|
||||||
func skipWithoutSolc(t *testing.T) {
|
func skipWithoutSolc(t *testing.T) {
|
||||||
|
|
@ -99,7 +99,7 @@ func TestSaveInfo(t *testing.T) {
|
||||||
if string(got) != testInfo {
|
if string(got) != testInfo {
|
||||||
t.Errorf("incorrect info.json extracted, expected:\n%s\ngot\n%s", testInfo, string(got))
|
t.Errorf("incorrect info.json extracted, expected:\n%s\ngot\n%s", testInfo, string(got))
|
||||||
}
|
}
|
||||||
wantHash := common.HexToHash("0x9f3803735e7f16120c5a140ab3f02121fd3533a9655c69b33a10e78752cc49b0")
|
wantHash := common.HexToHash("0x22450a77f0c3ff7a395948d07bc1456881226a1b6325f4189cb5f1254a824080")
|
||||||
if cinfohash != wantHash {
|
if cinfohash != wantHash {
|
||||||
t.Errorf("content hash for info is incorrect. expected %v, got %v", wantHash.Hex(), cinfohash.Hex())
|
t.Errorf("content hash for info is incorrect. expected %v, got %v", wantHash.Hex(), cinfohash.Hex())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -169,12 +169,7 @@ func EncodeBig(bigint *big.Int) string {
|
||||||
if nbits == 0 {
|
if nbits == 0 {
|
||||||
return "0x0"
|
return "0x0"
|
||||||
}
|
}
|
||||||
enc := make([]byte, 2, (nbits/8)*2+2)
|
return fmt.Sprintf("0x%x", bigint)
|
||||||
copy(enc, "0x")
|
|
||||||
for i := len(bigint.Bits()) - 1; i >= 0; i-- {
|
|
||||||
enc = strconv.AppendUint(enc, uint64(bigint.Bits()[i]), 16)
|
|
||||||
}
|
|
||||||
return string(enc)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func has0xPrefix(input string) bool {
|
func has0xPrefix(input string) bool {
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ var (
|
||||||
{referenceBig("1"), "0x1"},
|
{referenceBig("1"), "0x1"},
|
||||||
{referenceBig("ff"), "0xff"},
|
{referenceBig("ff"), "0xff"},
|
||||||
{referenceBig("112233445566778899aabbccddeeff"), "0x112233445566778899aabbccddeeff"},
|
{referenceBig("112233445566778899aabbccddeeff"), "0x112233445566778899aabbccddeeff"},
|
||||||
|
{referenceBig("80a7f2c1bcc396c00"), "0x80a7f2c1bcc396c00"},
|
||||||
}
|
}
|
||||||
|
|
||||||
encodeUint64Tests = []marshalTest{
|
encodeUint64Tests = []marshalTest{
|
||||||
|
|
|
||||||
|
|
@ -109,13 +109,8 @@ func (b *Big) MarshalJSON() ([]byte, error) {
|
||||||
if nbits == 0 {
|
if nbits == 0 {
|
||||||
return jsonZero, nil
|
return jsonZero, nil
|
||||||
}
|
}
|
||||||
enc := make([]byte, 3, (nbits/8)*2+4)
|
enc := fmt.Sprintf(`"0x%x"`, bigint)
|
||||||
copy(enc, `"0x`)
|
return []byte(enc), nil
|
||||||
for i := len(bigint.Bits()) - 1; i >= 0; i-- {
|
|
||||||
enc = strconv.AppendUint(enc, uint64(bigint.Bits()[i]), 16)
|
|
||||||
}
|
|
||||||
enc = append(enc, '"')
|
|
||||||
return enc, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements json.Unmarshaler.
|
// UnmarshalJSON implements json.Unmarshaler.
|
||||||
|
|
|
||||||
|
|
@ -137,10 +137,14 @@ func (c *Console) init(preload []string) error {
|
||||||
continue // manually mapped or ignore
|
continue // manually mapped or ignore
|
||||||
}
|
}
|
||||||
if file, ok := web3ext.Modules[api]; ok {
|
if file, ok := web3ext.Modules[api]; ok {
|
||||||
|
// Load our extension for the module.
|
||||||
if err = c.jsre.Compile(fmt.Sprintf("%s.js", api), file); err != nil {
|
if err = c.jsre.Compile(fmt.Sprintf("%s.js", api), file); err != nil {
|
||||||
return fmt.Errorf("%s.js: %v", api, err)
|
return fmt.Errorf("%s.js: %v", api, err)
|
||||||
}
|
}
|
||||||
flatten += fmt.Sprintf("var %s = web3.%s; ", api, api)
|
flatten += fmt.Sprintf("var %s = web3.%s; ", api, api)
|
||||||
|
} else if obj, err := c.jsre.Run("web3." + api); err == nil && obj.IsObject() {
|
||||||
|
// Enable web3.js built-in extension if available.
|
||||||
|
flatten += fmt.Sprintf("var %s = web3.%s; ", api, api)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, err = c.jsre.Run(flatten); err != nil {
|
if _, err = c.jsre.Run(flatten); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
FROM alpine:3.4
|
FROM alpine:3.5
|
||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
apk add --update go git make gcc musl-dev && \
|
apk add --update go git make gcc musl-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 && \
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,15 @@
|
||||||
FROM ubuntu:wily
|
FROM ubuntu:xenial
|
||||||
MAINTAINER caktux
|
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND noninteractive
|
RUN \
|
||||||
|
apt-get update && apt-get upgrade -q -y && \
|
||||||
RUN apt-get update && \
|
apt-get install -y --no-install-recommends golang git make gcc libc-dev ca-certificates && \
|
||||||
apt-get upgrade -q -y && \
|
git clone --depth 1 https://github.com/ethereum/go-ethereum && \
|
||||||
apt-get dist-upgrade -q -y && \
|
(cd go-ethereum && make geth) && \
|
||||||
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 923F6CA9 && \
|
cp go-ethereum/build/bin/geth /geth && \
|
||||||
echo "deb http://ppa.launchpad.net/ethereum/ethereum-dev/ubuntu wily main" | tee -a /etc/apt/sources.list.d/ethereum.list && \
|
apt-get remove -y golang git make gcc libc-dev && apt autoremove -y && apt-get clean && \
|
||||||
apt-get update && \
|
rm -rf /go-ethereum
|
||||||
apt-get install -q -y geth
|
|
||||||
|
|
||||||
EXPOSE 8545
|
EXPOSE 8545
|
||||||
EXPOSE 30303
|
EXPOSE 30303
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/bin/geth"]
|
ENTRYPOINT ["/geth"]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
FROM alpine:3.4
|
FROM alpine:3.5
|
||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
apk add --update go git make gcc musl-dev && \
|
apk add --update go git make gcc musl-dev ca-certificates && \
|
||||||
git clone --depth 1 --branch release/1.5 https://github.com/ethereum/go-ethereum && \
|
git clone --depth 1 --branch release/1.5 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 && \
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,15 @@
|
||||||
FROM ubuntu:wily
|
FROM ubuntu:xenial
|
||||||
MAINTAINER caktux
|
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND noninteractive
|
RUN \
|
||||||
|
apt-get update && apt-get upgrade -q -y && \
|
||||||
RUN apt-get update && \
|
apt-get install -y --no-install-recommends golang git make gcc libc-dev ca-certificates && \
|
||||||
apt-get upgrade -q -y && \
|
git clone --depth 1 --branch release/1.5 https://github.com/ethereum/go-ethereum && \
|
||||||
apt-get dist-upgrade -q -y && \
|
(cd go-ethereum && make geth) && \
|
||||||
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 923F6CA9 && \
|
cp go-ethereum/build/bin/geth /geth && \
|
||||||
echo "deb http://ppa.launchpad.net/ethereum/ethereum/ubuntu wily main" | tee -a /etc/apt/sources.list.d/ethereum.list && \
|
apt-get remove -y golang git make gcc libc-dev && apt autoremove -y && apt-get clean && \
|
||||||
apt-get update && \
|
rm -rf /go-ethereum
|
||||||
apt-get install -q -y geth
|
|
||||||
|
|
||||||
EXPOSE 8545
|
EXPOSE 8545
|
||||||
EXPOSE 30303
|
EXPOSE 30303
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/bin/geth"]
|
ENTRYPOINT ["/geth"]
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"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/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
|
@ -168,7 +169,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
|
||||||
// Time the insertion of the new chain.
|
// Time the insertion of the new chain.
|
||||||
// State and blocks are stored in the same DB.
|
// State and blocks are stored in the same DB.
|
||||||
evmux := new(event.TypeMux)
|
evmux := new(event.TypeMux)
|
||||||
chainman, _ := NewBlockChain(db, ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}, FakePow{}, evmux)
|
chainman, _ := NewBlockChain(db, ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}, FakePow{}, evmux, vm.Config{})
|
||||||
defer chainman.Stop()
|
defer chainman.Stop()
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
@ -278,7 +279,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error opening database at %v: %v", dir, err)
|
b.Fatalf("error opening database at %v: %v", dir, err)
|
||||||
}
|
}
|
||||||
chain, err := NewBlockChain(db, testChainConfig(), FakePow{}, new(event.TypeMux))
|
chain, err := NewBlockChain(db, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error creating chain: %v", err)
|
b.Fatalf("error creating chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"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/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -39,7 +40,7 @@ func proc() (Validator, *BlockChain) {
|
||||||
var mux event.TypeMux
|
var mux event.TypeMux
|
||||||
|
|
||||||
WriteTestNetGenesisBlock(db)
|
WriteTestNetGenesisBlock(db)
|
||||||
blockchain, err := NewBlockChain(db, testChainConfig(), thePow(), &mux)
|
blockchain, err := NewBlockChain(db, testChainConfig(), thePow(), &mux, vm.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -107,12 +107,13 @@ type BlockChain struct {
|
||||||
pow pow.PoW
|
pow pow.PoW
|
||||||
processor Processor // block processor interface
|
processor Processor // block processor interface
|
||||||
validator Validator // block and state validator interface
|
validator Validator // block and state validator interface
|
||||||
|
vmConfig vm.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlockChain returns a fully initialised block chain using information
|
// NewBlockChain returns a fully initialised block chain using information
|
||||||
// available in the database. It initialiser the default Ethereum Validator and
|
// available in the database. It initialiser the default Ethereum Validator and
|
||||||
// Processor.
|
// Processor.
|
||||||
func NewBlockChain(chainDb ethdb.Database, config *params.ChainConfig, pow pow.PoW, mux *event.TypeMux) (*BlockChain, error) {
|
func NewBlockChain(chainDb ethdb.Database, config *params.ChainConfig, pow pow.PoW, mux *event.TypeMux, vmConfig vm.Config) (*BlockChain, error) {
|
||||||
bodyCache, _ := lru.New(bodyCacheLimit)
|
bodyCache, _ := lru.New(bodyCacheLimit)
|
||||||
bodyRLPCache, _ := lru.New(bodyCacheLimit)
|
bodyRLPCache, _ := lru.New(bodyCacheLimit)
|
||||||
blockCache, _ := lru.New(blockCacheLimit)
|
blockCache, _ := lru.New(blockCacheLimit)
|
||||||
|
|
@ -128,6 +129,7 @@ func NewBlockChain(chainDb ethdb.Database, config *params.ChainConfig, pow pow.P
|
||||||
blockCache: blockCache,
|
blockCache: blockCache,
|
||||||
futureBlocks: futureBlocks,
|
futureBlocks: futureBlocks,
|
||||||
pow: pow,
|
pow: pow,
|
||||||
|
vmConfig: vmConfig,
|
||||||
}
|
}
|
||||||
bc.SetValidator(NewBlockValidator(config, bc, pow))
|
bc.SetValidator(NewBlockValidator(config, bc, pow))
|
||||||
bc.SetProcessor(NewStateProcessor(config, bc))
|
bc.SetProcessor(NewStateProcessor(config, bc))
|
||||||
|
|
@ -954,7 +956,7 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
// Process block using the parent state as reference point.
|
// Process block using the parent state as reference point.
|
||||||
receipts, logs, usedGas, err := self.processor.Process(block, self.stateCache, vm.Config{})
|
receipts, logs, usedGas, err := self.processor.Process(block, self.stateCache, self.vmConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.reportBlock(block, receipts, err)
|
self.reportBlock(block, receipts, err)
|
||||||
return i, err
|
return i, err
|
||||||
|
|
@ -1004,6 +1006,10 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
|
||||||
if err := WriteMipmapBloom(self.chainDb, block.NumberU64(), receipts); err != nil {
|
if err := WriteMipmapBloom(self.chainDb, block.NumberU64(), receipts); err != nil {
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
// Write hash preimages
|
||||||
|
if err := WritePreimages(self.chainDb, block.NumberU64(), self.stateCache.Preimages()); err != nil {
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
case SideStatTy:
|
case SideStatTy:
|
||||||
if glog.V(logger.Detail) {
|
if glog.V(logger.Detail) {
|
||||||
glog.Infof("inserted forked block #%d [%x…] (TD=%v) in %9v: %3d txs %d uncles.", block.Number(), block.Hash().Bytes()[0:4], block.Difficulty(), common.PrettyDuration(time.Since(bstart)), len(block.Transactions()), len(block.Uncles()))
|
glog.Infof("inserted forked block #%d [%x…] (TD=%v) in %9v: %3d txs %d uncles.", block.Number(), block.Hash().Bytes()[0:4], block.Difficulty(), common.PrettyDuration(time.Since(bstart)), len(block.Transactions()), len(block.Uncles()))
|
||||||
|
|
@ -1082,8 +1088,6 @@ func (self *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
|
||||||
newChain types.Blocks
|
newChain types.Blocks
|
||||||
oldChain types.Blocks
|
oldChain types.Blocks
|
||||||
commonBlock *types.Block
|
commonBlock *types.Block
|
||||||
oldStart = oldBlock
|
|
||||||
newStart = newBlock
|
|
||||||
deletedTxs types.Transactions
|
deletedTxs types.Transactions
|
||||||
deletedLogs []*types.Log
|
deletedLogs []*types.Log
|
||||||
// collectLogs collects the logs that were generated during the
|
// collectLogs collects the logs that were generated during the
|
||||||
|
|
@ -1124,7 +1128,6 @@ func (self *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
|
||||||
return fmt.Errorf("Invalid new chain")
|
return fmt.Errorf("Invalid new chain")
|
||||||
}
|
}
|
||||||
|
|
||||||
numSplit := newBlock.Number()
|
|
||||||
for {
|
for {
|
||||||
if oldBlock.Hash() == newBlock.Hash() {
|
if oldBlock.Hash() == newBlock.Hash() {
|
||||||
commonBlock = oldBlock
|
commonBlock = oldBlock
|
||||||
|
|
@ -1145,9 +1148,19 @@ func (self *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if glog.V(logger.Debug) {
|
if oldLen := len(oldChain); oldLen > 63 || glog.V(logger.Debug) {
|
||||||
commonHash := commonBlock.Hash()
|
newLen := len(newChain)
|
||||||
glog.Infof("Chain split detected @ %x. Reorganising chain from #%v %x to %x", commonHash[:4], numSplit, oldStart.Hash().Bytes()[:4], newStart.Hash().Bytes()[:4])
|
newLast := newChain[0]
|
||||||
|
newFirst := newChain[newLen-1]
|
||||||
|
oldLast := oldChain[0]
|
||||||
|
oldFirst := oldChain[oldLen-1]
|
||||||
|
glog.Infof("Chain split detected after #%v [%x…]. Reorganising chain (-%v +%v blocks), rejecting #%v-#%v [%x…/%x…] in favour of #%v-#%v [%x…/%x…]",
|
||||||
|
commonBlock.Number(), commonBlock.Hash().Bytes()[:4],
|
||||||
|
oldLen, newLen,
|
||||||
|
oldFirst.Number(), oldLast.Number(),
|
||||||
|
oldFirst.Hash().Bytes()[:4], oldLast.Hash().Bytes()[:4],
|
||||||
|
newFirst.Number(), newLast.Number(),
|
||||||
|
newFirst.Hash().Bytes()[:4], newLast.Hash().Bytes()[:4])
|
||||||
}
|
}
|
||||||
|
|
||||||
var addedTxs types.Transactions
|
var addedTxs types.Transactions
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ func thePow() pow.PoW {
|
||||||
func theBlockChain(db ethdb.Database, t *testing.T) *BlockChain {
|
func theBlockChain(db ethdb.Database, t *testing.T) *BlockChain {
|
||||||
var eventMux event.TypeMux
|
var eventMux event.TypeMux
|
||||||
WriteTestNetGenesisBlock(db)
|
WriteTestNetGenesisBlock(db)
|
||||||
blockchain, err := NewBlockChain(db, testChainConfig(), thePow(), &eventMux)
|
blockchain, err := NewBlockChain(db, testChainConfig(), thePow(), &eventMux, vm.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("failed creating blockchain:", err)
|
t.Error("failed creating blockchain:", err)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
|
|
@ -614,7 +614,7 @@ func testReorgBadHashes(t *testing.T, full bool) {
|
||||||
defer func() { delete(BadHashes, headers[3].Hash()) }()
|
defer func() { delete(BadHashes, headers[3].Hash()) }()
|
||||||
}
|
}
|
||||||
// Create a new chain manager and check it rolled back the state
|
// Create a new chain manager and check it rolled back the state
|
||||||
ncm, err := NewBlockChain(db, testChainConfig(), FakePow{}, new(event.TypeMux))
|
ncm, err := NewBlockChain(db, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create new chain manager: %v", err)
|
t.Fatalf("failed to create new chain manager: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -735,7 +735,7 @@ func TestFastVsFullChains(t *testing.T) {
|
||||||
archiveDb, _ := ethdb.NewMemDatabase()
|
archiveDb, _ := ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
|
WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
|
||||||
|
|
||||||
archive, _ := NewBlockChain(archiveDb, testChainConfig(), FakePow{}, new(event.TypeMux))
|
archive, _ := NewBlockChain(archiveDb, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
if n, err := archive.InsertChain(blocks); err != nil {
|
if n, err := archive.InsertChain(blocks); err != nil {
|
||||||
t.Fatalf("failed to process block %d: %v", n, err)
|
t.Fatalf("failed to process block %d: %v", n, err)
|
||||||
|
|
@ -743,7 +743,7 @@ func TestFastVsFullChains(t *testing.T) {
|
||||||
// Fast import the chain as a non-archive node to test
|
// Fast import the chain as a non-archive node to test
|
||||||
fastDb, _ := ethdb.NewMemDatabase()
|
fastDb, _ := ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
|
WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
|
||||||
fast, _ := NewBlockChain(fastDb, testChainConfig(), FakePow{}, new(event.TypeMux))
|
fast, _ := NewBlockChain(fastDb, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
headers := make([]*types.Header, len(blocks))
|
headers := make([]*types.Header, len(blocks))
|
||||||
for i, block := range blocks {
|
for i, block := range blocks {
|
||||||
|
|
@ -819,7 +819,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
||||||
archiveDb, _ := ethdb.NewMemDatabase()
|
archiveDb, _ := ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
|
WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
|
||||||
|
|
||||||
archive, _ := NewBlockChain(archiveDb, testChainConfig(), FakePow{}, new(event.TypeMux))
|
archive, _ := NewBlockChain(archiveDb, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
if n, err := archive.InsertChain(blocks); err != nil {
|
if n, err := archive.InsertChain(blocks); err != nil {
|
||||||
t.Fatalf("failed to process block %d: %v", n, err)
|
t.Fatalf("failed to process block %d: %v", n, err)
|
||||||
|
|
@ -831,7 +831,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
||||||
// Import the chain as a non-archive node and ensure all pointers are updated
|
// Import the chain as a non-archive node and ensure all pointers are updated
|
||||||
fastDb, _ := ethdb.NewMemDatabase()
|
fastDb, _ := ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
|
WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
|
||||||
fast, _ := NewBlockChain(fastDb, testChainConfig(), FakePow{}, new(event.TypeMux))
|
fast, _ := NewBlockChain(fastDb, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
headers := make([]*types.Header, len(blocks))
|
headers := make([]*types.Header, len(blocks))
|
||||||
for i, block := range blocks {
|
for i, block := range blocks {
|
||||||
|
|
@ -850,7 +850,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
||||||
// Import the chain as a light node and ensure all pointers are updated
|
// Import the chain as a light node and ensure all pointers are updated
|
||||||
lightDb, _ := ethdb.NewMemDatabase()
|
lightDb, _ := ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(lightDb, GenesisAccount{address, funds})
|
WriteGenesisBlockForTesting(lightDb, GenesisAccount{address, funds})
|
||||||
light, _ := NewBlockChain(lightDb, testChainConfig(), FakePow{}, new(event.TypeMux))
|
light, _ := NewBlockChain(lightDb, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
if n, err := light.InsertHeaderChain(headers, 1); err != nil {
|
if n, err := light.InsertHeaderChain(headers, 1); err != nil {
|
||||||
t.Fatalf("failed to insert header %d: %v", n, err)
|
t.Fatalf("failed to insert header %d: %v", n, err)
|
||||||
|
|
@ -916,7 +916,7 @@ func TestChainTxReorgs(t *testing.T) {
|
||||||
})
|
})
|
||||||
// Import the chain. This runs all block validation rules.
|
// Import the chain. This runs all block validation rules.
|
||||||
evmux := &event.TypeMux{}
|
evmux := &event.TypeMux{}
|
||||||
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
|
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux, vm.Config{})
|
||||||
if i, err := blockchain.InsertChain(chain); err != nil {
|
if i, err := blockchain.InsertChain(chain); err != nil {
|
||||||
t.Fatalf("failed to insert original chain[%d]: %v", i, err)
|
t.Fatalf("failed to insert original chain[%d]: %v", i, err)
|
||||||
}
|
}
|
||||||
|
|
@ -990,7 +990,7 @@ func TestLogReorgs(t *testing.T) {
|
||||||
)
|
)
|
||||||
|
|
||||||
evmux := &event.TypeMux{}
|
evmux := &event.TypeMux{}
|
||||||
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
|
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux, vm.Config{})
|
||||||
|
|
||||||
subs := evmux.Subscribe(RemovedLogsEvent{})
|
subs := evmux.Subscribe(RemovedLogsEvent{})
|
||||||
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 2, func(i int, gen *BlockGen) {
|
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 2, func(i int, gen *BlockGen) {
|
||||||
|
|
@ -1027,7 +1027,7 @@ func TestReorgSideEvent(t *testing.T) {
|
||||||
)
|
)
|
||||||
|
|
||||||
evmux := &event.TypeMux{}
|
evmux := &event.TypeMux{}
|
||||||
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
|
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux, vm.Config{})
|
||||||
|
|
||||||
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 3, func(i int, gen *BlockGen) {})
|
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 3, func(i int, gen *BlockGen) {})
|
||||||
if _, err := blockchain.InsertChain(chain); err != nil {
|
if _, err := blockchain.InsertChain(chain); err != nil {
|
||||||
|
|
@ -1103,7 +1103,7 @@ func TestCanonicalBlockRetrieval(t *testing.T) {
|
||||||
)
|
)
|
||||||
|
|
||||||
evmux := &event.TypeMux{}
|
evmux := &event.TypeMux{}
|
||||||
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
|
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux, vm.Config{})
|
||||||
|
|
||||||
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 10, func(i int, gen *BlockGen) {})
|
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 10, func(i int, gen *BlockGen) {})
|
||||||
|
|
||||||
|
|
@ -1146,7 +1146,7 @@ func TestEIP155Transition(t *testing.T) {
|
||||||
mux event.TypeMux
|
mux event.TypeMux
|
||||||
)
|
)
|
||||||
|
|
||||||
blockchain, _ := NewBlockChain(db, config, FakePow{}, &mux)
|
blockchain, _ := NewBlockChain(db, config, FakePow{}, &mux, vm.Config{})
|
||||||
blocks, _ := GenerateChain(config, genesis, db, 4, func(i int, block *BlockGen) {
|
blocks, _ := GenerateChain(config, genesis, db, 4, func(i int, block *BlockGen) {
|
||||||
var (
|
var (
|
||||||
tx *types.Transaction
|
tx *types.Transaction
|
||||||
|
|
@ -1250,7 +1250,7 @@ func TestEIP161AccountRemoval(t *testing.T) {
|
||||||
}
|
}
|
||||||
mux event.TypeMux
|
mux event.TypeMux
|
||||||
|
|
||||||
blockchain, _ = NewBlockChain(db, config, FakePow{}, &mux)
|
blockchain, _ = NewBlockChain(db, config, FakePow{}, &mux, vm.Config{})
|
||||||
)
|
)
|
||||||
blocks, _ := GenerateChain(config, genesis, db, 3, func(i int, block *BlockGen) {
|
blocks, _ := GenerateChain(config, genesis, db, 3, func(i int, block *BlockGen) {
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -256,7 +256,7 @@ func newCanonical(n int, full bool) (ethdb.Database, *BlockChain, error) {
|
||||||
// Initialize a fresh chain with only a genesis block
|
// Initialize a fresh chain with only a genesis block
|
||||||
genesis, _ := WriteTestNetGenesisBlock(db)
|
genesis, _ := WriteTestNetGenesisBlock(db)
|
||||||
|
|
||||||
blockchain, _ := NewBlockChain(db, MakeChainConfig(), FakePow{}, evmux)
|
blockchain, _ := NewBlockChain(db, MakeChainConfig(), FakePow{}, evmux, vm.Config{})
|
||||||
// Create and inject the requested chain
|
// Create and inject the requested chain
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return db, blockchain, nil
|
return db, blockchain, nil
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"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/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
|
@ -81,7 +82,7 @@ func ExampleGenerateChain() {
|
||||||
|
|
||||||
// Import the chain. This runs all block validation rules.
|
// Import the chain. This runs all block validation rules.
|
||||||
evmux := &event.TypeMux{}
|
evmux := &event.TypeMux{}
|
||||||
blockchain, _ := NewBlockChain(db, chainConfig, FakePow{}, evmux)
|
blockchain, _ := NewBlockChain(db, chainConfig, FakePow{}, evmux, vm.Config{})
|
||||||
if i, err := blockchain.InsertChain(chain); err != nil {
|
if i, err := blockchain.InsertChain(chain); err != nil {
|
||||||
fmt.Printf("insert error (block %d): %v\n", chain[i].NumberU64(), err)
|
fmt.Printf("insert error (block %d): %v\n", chain[i].NumberU64(), err)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -39,12 +40,12 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
proDb, _ := ethdb.NewMemDatabase()
|
proDb, _ := ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(proDb)
|
WriteGenesisBlockForTesting(proDb)
|
||||||
proConf := ¶ms.ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: true}
|
proConf := ¶ms.ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: true}
|
||||||
proBc, _ := NewBlockChain(proDb, proConf, new(FakePow), new(event.TypeMux))
|
proBc, _ := NewBlockChain(proDb, proConf, new(FakePow), new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
conDb, _ := ethdb.NewMemDatabase()
|
conDb, _ := ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(conDb)
|
WriteGenesisBlockForTesting(conDb)
|
||||||
conConf := ¶ms.ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: false}
|
conConf := ¶ms.ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: false}
|
||||||
conBc, _ := NewBlockChain(conDb, conConf, new(FakePow), new(event.TypeMux))
|
conBc, _ := NewBlockChain(conDb, conConf, new(FakePow), new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
if _, err := proBc.InsertChain(prefix); err != nil {
|
if _, err := proBc.InsertChain(prefix); err != nil {
|
||||||
t.Fatalf("pro-fork: failed to import chain prefix: %v", err)
|
t.Fatalf("pro-fork: failed to import chain prefix: %v", err)
|
||||||
|
|
@ -57,7 +58,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
// Create a pro-fork block, and try to feed into the no-fork chain
|
// Create a pro-fork block, and try to feed into the no-fork chain
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db, _ = ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(db)
|
WriteGenesisBlockForTesting(db)
|
||||||
bc, _ := NewBlockChain(db, conConf, new(FakePow), new(event.TypeMux))
|
bc, _ := NewBlockChain(db, conConf, new(FakePow), new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()+1))
|
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()+1))
|
||||||
for j := 0; j < len(blocks)/2; j++ {
|
for j := 0; j < len(blocks)/2; j++ {
|
||||||
|
|
@ -78,7 +79,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
// Create a no-fork block, and try to feed into the pro-fork chain
|
// Create a no-fork block, and try to feed into the pro-fork chain
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db, _ = ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(db)
|
WriteGenesisBlockForTesting(db)
|
||||||
bc, _ = NewBlockChain(db, proConf, new(FakePow), new(event.TypeMux))
|
bc, _ = NewBlockChain(db, proConf, new(FakePow), new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()+1))
|
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()+1))
|
||||||
for j := 0; j < len(blocks)/2; j++ {
|
for j := 0; j < len(blocks)/2; j++ {
|
||||||
|
|
@ -100,7 +101,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
// Verify that contra-forkers accept pro-fork extra-datas after forking finishes
|
// Verify that contra-forkers accept pro-fork extra-datas after forking finishes
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db, _ = ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(db)
|
WriteGenesisBlockForTesting(db)
|
||||||
bc, _ := NewBlockChain(db, conConf, new(FakePow), new(event.TypeMux))
|
bc, _ := NewBlockChain(db, conConf, new(FakePow), new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()+1))
|
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()+1))
|
||||||
for j := 0; j < len(blocks)/2; j++ {
|
for j := 0; j < len(blocks)/2; j++ {
|
||||||
|
|
@ -116,7 +117,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
// Verify that pro-forkers accept contra-fork extra-datas after forking finishes
|
// Verify that pro-forkers accept contra-fork extra-datas after forking finishes
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db, _ = ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(db)
|
WriteGenesisBlockForTesting(db)
|
||||||
bc, _ = NewBlockChain(db, proConf, new(FakePow), new(event.TypeMux))
|
bc, _ = NewBlockChain(db, proConf, new(FakePow), new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()+1))
|
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()+1))
|
||||||
for j := 0; j < len(blocks)/2; j++ {
|
for j := 0; j < len(blocks)/2; j++ {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
|
|
@ -45,6 +46,7 @@ var (
|
||||||
blockHashPrefix = []byte("H") // blockHashPrefix + hash -> num (uint64 big endian)
|
blockHashPrefix = []byte("H") // blockHashPrefix + hash -> num (uint64 big endian)
|
||||||
bodyPrefix = []byte("b") // bodyPrefix + num (uint64 big endian) + hash -> block body
|
bodyPrefix = []byte("b") // bodyPrefix + num (uint64 big endian) + hash -> block body
|
||||||
blockReceiptsPrefix = []byte("r") // blockReceiptsPrefix + num (uint64 big endian) + hash -> block receipts
|
blockReceiptsPrefix = []byte("r") // blockReceiptsPrefix + num (uint64 big endian) + hash -> block receipts
|
||||||
|
preimagePrefix = "secure-key-" // preimagePrefix + hash -> preimage
|
||||||
|
|
||||||
txMetaSuffix = []byte{0x01}
|
txMetaSuffix = []byte{0x01}
|
||||||
receiptsPrefix = []byte("receipts-")
|
receiptsPrefix = []byte("receipts-")
|
||||||
|
|
@ -66,6 +68,9 @@ var (
|
||||||
ChainConfigNotFoundErr = errors.New("ChainConfig not found") // general config not found error
|
ChainConfigNotFoundErr = errors.New("ChainConfig not found") // general config not found error
|
||||||
|
|
||||||
mipmapBloomMu sync.Mutex // protect against race condition when updating mipmap blooms
|
mipmapBloomMu sync.Mutex // protect against race condition when updating mipmap blooms
|
||||||
|
|
||||||
|
preimageCounter = metrics.NewCounter("db/preimage/total")
|
||||||
|
preimageHitCounter = metrics.NewCounter("db/preimage/hits")
|
||||||
)
|
)
|
||||||
|
|
||||||
// encodeBlockNumber encodes a block number as big endian uint64
|
// encodeBlockNumber encodes a block number as big endian uint64
|
||||||
|
|
@ -595,6 +600,34 @@ func GetMipmapBloom(db ethdb.Database, number, level uint64) types.Bloom {
|
||||||
return types.BytesToBloom(bloomDat)
|
return types.BytesToBloom(bloomDat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PreimageTable returns a Database instance with the key prefix for preimage entries.
|
||||||
|
func PreimageTable(db ethdb.Database) ethdb.Database {
|
||||||
|
return ethdb.NewTable(db, preimagePrefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WritePreimages writes the provided set of preimages to the database. `number` is the
|
||||||
|
// current block number, and is used for debug messages only.
|
||||||
|
func WritePreimages(db ethdb.Database, number uint64, preimages map[common.Hash][]byte) error {
|
||||||
|
table := PreimageTable(db)
|
||||||
|
batch := table.NewBatch()
|
||||||
|
hitCount := 0
|
||||||
|
for hash, preimage := range preimages {
|
||||||
|
if _, err := table.Get(hash.Bytes()); err != nil {
|
||||||
|
batch.Put(hash.Bytes(), preimage)
|
||||||
|
hitCount += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
preimageCounter.Inc(int64(len(preimages)))
|
||||||
|
preimageHitCounter.Inc(int64(hitCount))
|
||||||
|
if hitCount > 0 {
|
||||||
|
if err := batch.Write(); err != nil {
|
||||||
|
return fmt.Errorf("preimage write fail for block %d: %v", number, err)
|
||||||
|
}
|
||||||
|
glog.V(logger.Debug).Infof("%d preimages in block %d, including %d new", len(preimages), number, hitCount)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetBlockChainVersion reads the version number from db.
|
// GetBlockChainVersion reads the version number from db.
|
||||||
func GetBlockChainVersion(db ethdb.Database) int {
|
func GetBlockChainVersion(db ethdb.Database) int {
|
||||||
var vsn uint
|
var vsn uint
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,9 @@ type (
|
||||||
addLogChange struct {
|
addLogChange struct {
|
||||||
txhash common.Hash
|
txhash common.Hash
|
||||||
}
|
}
|
||||||
|
addPreimageChange struct {
|
||||||
|
hash common.Hash
|
||||||
|
}
|
||||||
touchChange struct {
|
touchChange struct {
|
||||||
account *common.Address
|
account *common.Address
|
||||||
prev bool
|
prev bool
|
||||||
|
|
@ -127,3 +130,7 @@ func (ch addLogChange) undo(s *StateDB) {
|
||||||
s.logs[ch.txhash] = logs[:len(logs)-1]
|
s.logs[ch.txhash] = logs[:len(logs)-1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ch addPreimageChange) undo(s *StateDB) {
|
||||||
|
delete(s.preimages, ch.hash)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,8 @@ type StateDB struct {
|
||||||
logs map[common.Hash][]*types.Log
|
logs map[common.Hash][]*types.Log
|
||||||
logSize uint
|
logSize uint
|
||||||
|
|
||||||
|
preimages map[common.Hash][]byte
|
||||||
|
|
||||||
// Journal of state modifications. This is the backbone of
|
// Journal of state modifications. This is the backbone of
|
||||||
// Snapshot and RevertToSnapshot.
|
// Snapshot and RevertToSnapshot.
|
||||||
journal journal
|
journal journal
|
||||||
|
|
@ -99,6 +101,7 @@ func New(root common.Hash, db ethdb.Database) (*StateDB, error) {
|
||||||
stateObjectsDirty: make(map[common.Address]struct{}),
|
stateObjectsDirty: make(map[common.Address]struct{}),
|
||||||
refund: new(big.Int),
|
refund: new(big.Int),
|
||||||
logs: make(map[common.Hash][]*types.Log),
|
logs: make(map[common.Hash][]*types.Log),
|
||||||
|
preimages: make(map[common.Hash][]byte),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,6 +123,7 @@ func (self *StateDB) New(root common.Hash) (*StateDB, error) {
|
||||||
stateObjectsDirty: make(map[common.Address]struct{}),
|
stateObjectsDirty: make(map[common.Address]struct{}),
|
||||||
refund: new(big.Int),
|
refund: new(big.Int),
|
||||||
logs: make(map[common.Hash][]*types.Log),
|
logs: make(map[common.Hash][]*types.Log),
|
||||||
|
preimages: make(map[common.Hash][]byte),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,6 +145,7 @@ func (self *StateDB) Reset(root common.Hash) error {
|
||||||
self.txIndex = 0
|
self.txIndex = 0
|
||||||
self.logs = make(map[common.Hash][]*types.Log)
|
self.logs = make(map[common.Hash][]*types.Log)
|
||||||
self.logSize = 0
|
self.logSize = 0
|
||||||
|
self.preimages = make(map[common.Hash][]byte)
|
||||||
self.clearJournalAndRefund()
|
self.clearJournalAndRefund()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -199,6 +204,21 @@ func (self *StateDB) Logs() []*types.Log {
|
||||||
return logs
|
return logs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddPreimage records a SHA3 preimage seen by the VM.
|
||||||
|
func (self *StateDB) AddPreimage(hash common.Hash, preimage []byte) {
|
||||||
|
if _, ok := self.preimages[hash]; !ok {
|
||||||
|
self.journal = append(self.journal, addPreimageChange{hash: hash})
|
||||||
|
pi := make([]byte, len(preimage))
|
||||||
|
copy(pi, preimage)
|
||||||
|
self.preimages[hash] = pi
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preimages returns a list of SHA3 preimages that have been submitted.
|
||||||
|
func (self *StateDB) Preimages() map[common.Hash][]byte {
|
||||||
|
return self.preimages
|
||||||
|
}
|
||||||
|
|
||||||
func (self *StateDB) AddRefund(gas *big.Int) {
|
func (self *StateDB) AddRefund(gas *big.Int) {
|
||||||
self.journal = append(self.journal, refundChange{prev: new(big.Int).Set(self.refund)})
|
self.journal = append(self.journal, refundChange{prev: new(big.Int).Set(self.refund)})
|
||||||
self.refund.Add(self.refund, gas)
|
self.refund.Add(self.refund, gas)
|
||||||
|
|
@ -477,8 +497,9 @@ func (self *StateDB) Copy() *StateDB {
|
||||||
refund: new(big.Int).Set(self.refund),
|
refund: new(big.Int).Set(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),
|
||||||
}
|
}
|
||||||
// Copy the dirty states and logs
|
// Copy the dirty states, logs, and preimages
|
||||||
for addr := range self.stateObjectsDirty {
|
for addr := range self.stateObjectsDirty {
|
||||||
state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state, state.MarkStateObjectDirty)
|
state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state, state.MarkStateObjectDirty)
|
||||||
state.stateObjectsDirty[addr] = struct{}{}
|
state.stateObjectsDirty[addr] = struct{}{}
|
||||||
|
|
@ -487,6 +508,9 @@ func (self *StateDB) Copy() *StateDB {
|
||||||
state.logs[hash] = make([]*types.Log, len(logs))
|
state.logs[hash] = make([]*types.Log, len(logs))
|
||||||
copy(state.logs[hash], logs)
|
copy(state.logs[hash], logs)
|
||||||
}
|
}
|
||||||
|
for hash, preimage := range self.preimages {
|
||||||
|
state.preimages[hash] = preimage
|
||||||
|
}
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, gp *GasPool, s
|
||||||
context := NewEVMContext(msg, header, bc)
|
context := NewEVMContext(msg, header, bc)
|
||||||
// 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(context, statedb, config, vm.Config{})
|
vmenv := vm.NewEVM(context, statedb, config, cfg)
|
||||||
// Apply the transaction to the current state (included in the env)
|
// Apply the transaction to the current state (included in the env)
|
||||||
_, gas, err := ApplyMessage(vmenv, msg, gp)
|
_, gas, err := ApplyMessage(vmenv, msg, gp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -233,9 +233,6 @@ func (self *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *b
|
||||||
)
|
)
|
||||||
if contractCreation {
|
if contractCreation {
|
||||||
ret, _, vmerr = vmenv.Create(sender, self.data, self.gas, self.value)
|
ret, _, vmerr = vmenv.Create(sender, self.data, self.gas, self.value)
|
||||||
if homestead && err == vm.ErrCodeStoreOutOfGas {
|
|
||||||
self.gas = Big0
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Increment the nonce for the next transaction
|
// Increment the nonce for the next transaction
|
||||||
self.state.SetNonce(sender.Address(), self.state.GetNonce(sender.Address())+1)
|
self.state.SetNonce(sender.Address(), self.state.GetNonce(sender.Address())+1)
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ func (tx *Transaction) ChainId() *big.Int {
|
||||||
return deriveChainId(tx.data.V)
|
return deriveChainId(tx.data.V)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Protected returns whether the transaction is pretected from replay protection
|
// Protected returns whether the transaction is protected from replay protection.
|
||||||
func (tx *Transaction) Protected() bool {
|
func (tx *Transaction) Protected() bool {
|
||||||
return isProtectedV(tx.data.V)
|
return isProtectedV(tx.data.V)
|
||||||
}
|
}
|
||||||
|
|
@ -198,7 +198,8 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
|
||||||
|
|
||||||
var V byte
|
var V byte
|
||||||
if isProtectedV((*big.Int)(dec.V)) {
|
if isProtectedV((*big.Int)(dec.V)) {
|
||||||
V = byte((new(big.Int).Sub((*big.Int)(dec.V), deriveChainId((*big.Int)(dec.V))).Uint64()) - 35)
|
chainId := deriveChainId((*big.Int)(dec.V)).Uint64()
|
||||||
|
V = byte(dec.V.ToInt().Uint64() - 35 - 2*chainId)
|
||||||
} else {
|
} else {
|
||||||
V = byte(((*big.Int)(dec.V)).Uint64() - 27)
|
V = byte(((*big.Int)(dec.V)).Uint64() - 27)
|
||||||
}
|
}
|
||||||
|
|
@ -310,16 +311,20 @@ func (tx *Transaction) RawSignatureValues() (*big.Int, *big.Int, *big.Int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) String() string {
|
func (tx *Transaction) String() string {
|
||||||
|
var from, to string
|
||||||
|
if tx.data.V != nil {
|
||||||
// make a best guess about the signer and use that to derive
|
// make a best guess about the signer and use that to derive
|
||||||
// the sender.
|
// the sender.
|
||||||
signer := deriveSigner(tx.data.V)
|
signer := deriveSigner(tx.data.V)
|
||||||
|
|
||||||
var from, to string
|
|
||||||
if f, err := Sender(signer, tx); err != nil { // derive but don't cache
|
if f, err := Sender(signer, tx); err != nil { // derive but don't cache
|
||||||
from = "[invalid sender: invalid sig]"
|
from = "[invalid sender: invalid sig]"
|
||||||
} else {
|
} else {
|
||||||
from = fmt.Sprintf("%x", f[:])
|
from = fmt.Sprintf("%x", f[:])
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
from = "[invalid sender: nil V field]"
|
||||||
|
}
|
||||||
|
|
||||||
if tx.data.Recipient == nil {
|
if tx.data.Recipient == nil {
|
||||||
to = "[contract creation]"
|
to = "[contract creation]"
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -332,13 +337,13 @@ func (tx *Transaction) String() string {
|
||||||
From: %s
|
From: %s
|
||||||
To: %s
|
To: %s
|
||||||
Nonce: %v
|
Nonce: %v
|
||||||
GasPrice: %v
|
GasPrice: %#x
|
||||||
GasLimit %v
|
GasLimit %#x
|
||||||
Value: %v
|
Value: %#x
|
||||||
Data: 0x%x
|
Data: 0x%x
|
||||||
V: 0x%x
|
V: %#x
|
||||||
R: 0x%x
|
R: %#x
|
||||||
S: 0x%x
|
S: %#x
|
||||||
Hex: %x
|
Hex: %x
|
||||||
`,
|
`,
|
||||||
tx.Hash(),
|
tx.Hash(),
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ func (s EIP155Signer) PublicKey(tx *Transaction) ([]byte, error) {
|
||||||
// needs to be in the [R || S || V] format where V is 0 or 1.
|
// needs to be in the [R || S || V] format where V is 0 or 1.
|
||||||
func (s EIP155Signer) WithSignature(tx *Transaction, sig []byte) (*Transaction, error) {
|
func (s EIP155Signer) WithSignature(tx *Transaction, sig []byte) (*Transaction, error) {
|
||||||
if len(sig) != 65 {
|
if len(sig) != 65 {
|
||||||
panic(fmt.Sprintf("wrong size for snature: got %d, want 65", len(sig)))
|
panic(fmt.Sprintf("wrong size for signature: got %d, want 65", len(sig)))
|
||||||
}
|
}
|
||||||
|
|
||||||
cpy := &Transaction{data: tx.data}
|
cpy := &Transaction{data: tx.data}
|
||||||
|
|
|
||||||
|
|
@ -247,7 +247,12 @@ func opMulmod(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *S
|
||||||
|
|
||||||
func opSha3(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
func opSha3(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
offset, size := stack.pop(), stack.pop()
|
offset, size := stack.pop(), stack.pop()
|
||||||
hash := crypto.Keccak256(memory.Get(offset.Int64(), size.Int64()))
|
data := memory.Get(offset.Int64(), size.Int64())
|
||||||
|
hash := crypto.Keccak256(data)
|
||||||
|
|
||||||
|
if env.vmConfig.EnablePreimageRecording {
|
||||||
|
env.StateDB.AddPreimage(common.BytesToHash(hash), data)
|
||||||
|
}
|
||||||
|
|
||||||
stack.push(common.BytesToBig(hash))
|
stack.push(common.BytesToBig(hash))
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ type StateDB interface {
|
||||||
Snapshot() int
|
Snapshot() int
|
||||||
|
|
||||||
AddLog(*types.Log)
|
AddLog(*types.Log)
|
||||||
|
AddPreimage(common.Hash, []byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account represents a contract or basic ethereum account.
|
// Account represents a contract or basic ethereum account.
|
||||||
|
|
|
||||||
|
|
@ -67,3 +67,4 @@ func (NoopStateDB) Empty(common.Address) bool { return f
|
||||||
func (NoopStateDB) RevertToSnapshot(int) {}
|
func (NoopStateDB) RevertToSnapshot(int) {}
|
||||||
func (NoopStateDB) Snapshot() int { return 0 }
|
func (NoopStateDB) Snapshot() int { return 0 }
|
||||||
func (NoopStateDB) AddLog(*types.Log) {}
|
func (NoopStateDB) AddLog(*types.Log) {}
|
||||||
|
func (NoopStateDB) AddPreimage(common.Hash, []byte) {}
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,8 @@ type Config struct {
|
||||||
NoRecursion bool
|
NoRecursion bool
|
||||||
// Disable gas metering
|
// Disable gas metering
|
||||||
DisableGasMetering bool
|
DisableGasMetering bool
|
||||||
|
// Enable recording of SHA3/keccak preimages
|
||||||
|
EnablePreimageRecording bool
|
||||||
// JumpTable contains the EVM instruction table. This
|
// JumpTable contains the EVM instruction table. This
|
||||||
// may me left uninitialised and will be set the default
|
// may me left uninitialised and will be set the default
|
||||||
// table.
|
// table.
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto/randentropy"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -90,12 +88,10 @@ func Sign(msg []byte, seckey []byte) ([]byte, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
msgdata = (*C.uchar)(unsafe.Pointer(&msg[0]))
|
msgdata = (*C.uchar)(unsafe.Pointer(&msg[0]))
|
||||||
nonce = randentropy.GetEntropyCSPRNG(32)
|
noncefunc = C.secp256k1_nonce_function_rfc6979
|
||||||
noncefunc = &(*C.secp256k1_nonce_function_default)
|
|
||||||
noncefuncData = unsafe.Pointer(&nonce[0])
|
|
||||||
sigstruct C.secp256k1_ecdsa_recoverable_signature
|
sigstruct C.secp256k1_ecdsa_recoverable_signature
|
||||||
)
|
)
|
||||||
if C.secp256k1_ecdsa_sign_recoverable(context, &sigstruct, msgdata, seckeydata, noncefunc, noncefuncData) == 0 {
|
if C.secp256k1_ecdsa_sign_recoverable(context, &sigstruct, msgdata, seckeydata, noncefunc, nil) == 0 {
|
||||||
return nil, ErrSignFailed
|
return nil, ErrSignFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,24 @@ func TestSignAndRecover(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSignDeterministic(t *testing.T) {
|
||||||
|
_, seckey := generateKeyPair()
|
||||||
|
msg := make([]byte, 32)
|
||||||
|
copy(msg, "hi there")
|
||||||
|
|
||||||
|
sig1, err := Sign(msg, seckey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
sig2, err := Sign(msg, seckey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(sig1, sig2) {
|
||||||
|
t.Fatal("signatures not equal")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRandomMessagesWithSameKey(t *testing.T) {
|
func TestRandomMessagesWithSameKey(t *testing.T) {
|
||||||
pubkey, seckey := generateKeyPair()
|
pubkey, seckey := generateKeyPair()
|
||||||
keys := func() ([]byte, []byte) {
|
keys := func() ([]byte, []byte) {
|
||||||
|
|
|
||||||
|
|
@ -560,3 +560,9 @@ func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, txHash common.
|
||||||
}
|
}
|
||||||
return nil, errors.New("database inconsistency")
|
return nil, errors.New("database inconsistency")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Preimage is a debug API function that returns the preimage for a sha3 hash, if known.
|
||||||
|
func (api *PrivateDebugAPI) Preimage(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
|
||||||
|
db := core.PreimageTable(api.eth.ChainDb())
|
||||||
|
return db.Get(hash.Bytes())
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ import (
|
||||||
"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/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||||
"github.com/ethereum/go-ethereum/eth/filters"
|
"github.com/ethereum/go-ethereum/eth/filters"
|
||||||
"github.com/ethereum/go-ethereum/eth/gasprice"
|
"github.com/ethereum/go-ethereum/eth/gasprice"
|
||||||
|
|
@ -77,7 +78,6 @@ type Config struct {
|
||||||
DatabaseCache int
|
DatabaseCache int
|
||||||
DatabaseHandles int
|
DatabaseHandles int
|
||||||
|
|
||||||
NatSpec bool
|
|
||||||
DocRoot string
|
DocRoot string
|
||||||
AutoDAG bool
|
AutoDAG bool
|
||||||
PowFake bool
|
PowFake bool
|
||||||
|
|
@ -97,8 +97,7 @@ type Config struct {
|
||||||
GpobaseStepUp int
|
GpobaseStepUp int
|
||||||
GpobaseCorrectionFactor int
|
GpobaseCorrectionFactor int
|
||||||
|
|
||||||
EnableJit bool
|
EnablePreimageRecording bool
|
||||||
ForceJit bool
|
|
||||||
|
|
||||||
TestGenesisBlock *types.Block // Genesis block to seed the chain database with (testing only!)
|
TestGenesisBlock *types.Block // Genesis block to seed the chain database with (testing only!)
|
||||||
TestGenesisState ethdb.Database // Genesis state to seed the database with (testing only!)
|
TestGenesisState ethdb.Database // Genesis state to seed the database with (testing only!)
|
||||||
|
|
@ -140,7 +139,6 @@ type Ethereum struct {
|
||||||
etherbase common.Address
|
etherbase common.Address
|
||||||
solcPath string
|
solcPath string
|
||||||
|
|
||||||
NatSpec bool
|
|
||||||
netVersionId int
|
netVersionId int
|
||||||
netRPCService *ethapi.PublicNetAPI
|
netRPCService *ethapi.PublicNetAPI
|
||||||
}
|
}
|
||||||
|
|
@ -174,7 +172,6 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||||
shutdownChan: make(chan bool),
|
shutdownChan: make(chan bool),
|
||||||
stopDbUpgrade: stopDbUpgrade,
|
stopDbUpgrade: stopDbUpgrade,
|
||||||
netVersionId: config.NetworkId,
|
netVersionId: config.NetworkId,
|
||||||
NatSpec: config.NatSpec,
|
|
||||||
etherbase: config.Etherbase,
|
etherbase: config.Etherbase,
|
||||||
MinerThreads: config.MinerThreads,
|
MinerThreads: config.MinerThreads,
|
||||||
AutoDAG: config.AutoDAG,
|
AutoDAG: config.AutoDAG,
|
||||||
|
|
@ -218,7 +215,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||||
|
|
||||||
glog.V(logger.Info).Infoln("Chain config:", eth.chainConfig)
|
glog.V(logger.Info).Infoln("Chain config:", eth.chainConfig)
|
||||||
|
|
||||||
eth.blockchain, err = core.NewBlockChain(chainDb, eth.chainConfig, eth.pow, eth.EventMux())
|
eth.blockchain, err = core.NewBlockChain(chainDb, eth.chainConfig, eth.pow, eth.EventMux(), vm.Config{EnablePreimageRecording: config.EnablePreimageRecording})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == core.ErrNoGenesis {
|
if err == core.ErrNoGenesis {
|
||||||
return nil, fmt.Errorf(`No chain found. Please initialise a new chain using the "init" subcommand.`)
|
return nil, fmt.Errorf(`No chain found. Please initialise a new chain using the "init" subcommand.`)
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
|
@ -103,8 +102,7 @@ type queue struct {
|
||||||
|
|
||||||
stateDatabase ethdb.Database // [eth/63] Trie database to populate during state reassembly
|
stateDatabase ethdb.Database // [eth/63] Trie database to populate during state reassembly
|
||||||
stateScheduler *state.StateSync // [eth/63] State trie synchronisation scheduler and integrator
|
stateScheduler *state.StateSync // [eth/63] State trie synchronisation scheduler and integrator
|
||||||
stateProcessors int32 // [eth/63] Number of currently running state processors
|
stateWriters int // [eth/63] Number of running state DB writer goroutines
|
||||||
stateSchedLock sync.RWMutex // [eth/63] Lock serialising access to the state scheduler
|
|
||||||
|
|
||||||
resultCache []*fetchResult // Downloaded but not yet delivered fetch results
|
resultCache []*fetchResult // Downloaded but not yet delivered fetch results
|
||||||
resultOffset uint64 // Offset of the first cached fetch result in the block chain
|
resultOffset uint64 // Offset of the first cached fetch result in the block chain
|
||||||
|
|
@ -143,9 +141,6 @@ func (q *queue) Reset() {
|
||||||
q.lock.Lock()
|
q.lock.Lock()
|
||||||
defer q.lock.Unlock()
|
defer q.lock.Unlock()
|
||||||
|
|
||||||
q.stateSchedLock.Lock()
|
|
||||||
defer q.stateSchedLock.Unlock()
|
|
||||||
|
|
||||||
q.closed = false
|
q.closed = false
|
||||||
q.mode = FullSync
|
q.mode = FullSync
|
||||||
q.fastSyncPivot = 0
|
q.fastSyncPivot = 0
|
||||||
|
|
@ -209,13 +204,24 @@ func (q *queue) PendingReceipts() int {
|
||||||
|
|
||||||
// PendingNodeData retrieves the number of node data entries pending for retrieval.
|
// PendingNodeData retrieves the number of node data entries pending for retrieval.
|
||||||
func (q *queue) PendingNodeData() int {
|
func (q *queue) PendingNodeData() int {
|
||||||
q.stateSchedLock.RLock()
|
q.lock.Lock()
|
||||||
defer q.stateSchedLock.RUnlock()
|
defer q.lock.Unlock()
|
||||||
|
|
||||||
if q.stateScheduler != nil {
|
return q.pendingNodeDataLocked()
|
||||||
return q.stateScheduler.Pending()
|
|
||||||
}
|
}
|
||||||
return 0
|
|
||||||
|
// pendingNodeDataLocked retrieves the number of node data entries pending for retrieval.
|
||||||
|
// The caller must hold q.lock.
|
||||||
|
func (q *queue) pendingNodeDataLocked() int {
|
||||||
|
var n int
|
||||||
|
if q.stateScheduler != nil {
|
||||||
|
n = q.stateScheduler.Pending()
|
||||||
|
}
|
||||||
|
// Ensure that PendingNodeData doesn't return 0 until all state is written.
|
||||||
|
if q.stateWriters > 0 {
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// InFlightHeaders retrieves whether there are header fetch requests currently
|
// InFlightHeaders retrieves whether there are header fetch requests currently
|
||||||
|
|
@ -251,7 +257,7 @@ func (q *queue) InFlightNodeData() bool {
|
||||||
q.lock.Lock()
|
q.lock.Lock()
|
||||||
defer q.lock.Unlock()
|
defer q.lock.Unlock()
|
||||||
|
|
||||||
return len(q.statePendPool)+int(atomic.LoadInt32(&q.stateProcessors)) > 0
|
return len(q.statePendPool)+q.stateWriters > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Idle returns if the queue is fully idle or has some data still inside. This
|
// Idle returns if the queue is fully idle or has some data still inside. This
|
||||||
|
|
@ -264,12 +270,9 @@ func (q *queue) Idle() bool {
|
||||||
pending := len(q.blockPendPool) + len(q.receiptPendPool) + len(q.statePendPool)
|
pending := len(q.blockPendPool) + len(q.receiptPendPool) + len(q.statePendPool)
|
||||||
cached := len(q.blockDonePool) + len(q.receiptDonePool)
|
cached := len(q.blockDonePool) + len(q.receiptDonePool)
|
||||||
|
|
||||||
q.stateSchedLock.RLock()
|
|
||||||
if q.stateScheduler != nil {
|
if q.stateScheduler != nil {
|
||||||
queued += q.stateScheduler.Pending()
|
queued += q.stateScheduler.Pending()
|
||||||
}
|
}
|
||||||
q.stateSchedLock.RUnlock()
|
|
||||||
|
|
||||||
return (queued + pending + cached) == 0
|
return (queued + pending + cached) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -398,9 +401,7 @@ func (q *queue) Schedule(headers []*types.Header, from uint64) []*types.Header {
|
||||||
req.Hashes = make(map[common.Hash]int) // Make sure executing requests fail, but don't disappear
|
req.Hashes = make(map[common.Hash]int) // Make sure executing requests fail, but don't disappear
|
||||||
}
|
}
|
||||||
|
|
||||||
q.stateSchedLock.Lock()
|
|
||||||
q.stateScheduler = state.NewStateSync(header.Root, q.stateDatabase)
|
q.stateScheduler = state.NewStateSync(header.Root, q.stateDatabase)
|
||||||
q.stateSchedLock.Unlock()
|
|
||||||
}
|
}
|
||||||
inserts = append(inserts, header)
|
inserts = append(inserts, header)
|
||||||
q.headerHead = hash
|
q.headerHead = hash
|
||||||
|
|
@ -459,7 +460,7 @@ func (q *queue) countProcessableItems() int {
|
||||||
// resultCache has space for fsHeaderForceVerify items. Not
|
// resultCache has space for fsHeaderForceVerify items. Not
|
||||||
// doing this could leave us unable to download the required
|
// doing this could leave us unable to download the required
|
||||||
// amount of headers.
|
// amount of headers.
|
||||||
if i > 0 || len(q.stateTaskPool) > 0 || q.PendingNodeData() > 0 {
|
if i > 0 || len(q.stateTaskPool) > 0 || q.pendingNodeDataLocked() > 0 {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
for j := 0; j < fsHeaderForceVerify; j++ {
|
for j := 0; j < fsHeaderForceVerify; j++ {
|
||||||
|
|
@ -524,9 +525,6 @@ func (q *queue) ReserveHeaders(p *peer, count int) *fetchRequest {
|
||||||
func (q *queue) ReserveNodeData(p *peer, count int) *fetchRequest {
|
func (q *queue) ReserveNodeData(p *peer, count int) *fetchRequest {
|
||||||
// Create a task generator to fetch status-fetch tasks if all schedules ones are done
|
// Create a task generator to fetch status-fetch tasks if all schedules ones are done
|
||||||
generator := func(max int) {
|
generator := func(max int) {
|
||||||
q.stateSchedLock.Lock()
|
|
||||||
defer q.stateSchedLock.Unlock()
|
|
||||||
|
|
||||||
if q.stateScheduler != nil {
|
if q.stateScheduler != nil {
|
||||||
for _, hash := range q.stateScheduler.Missing(max) {
|
for _, hash := range q.stateScheduler.Missing(max) {
|
||||||
q.stateTaskPool[hash] = q.stateTaskIndex
|
q.stateTaskPool[hash] = q.stateTaskIndex
|
||||||
|
|
@ -1068,7 +1066,7 @@ func (q *queue) DeliverNodeData(id string, data [][]byte, callback func(int, boo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Iterate over the downloaded data and verify each of them
|
// Iterate over the downloaded data and verify each of them
|
||||||
accepted, errs := 0, make([]error, 0)
|
errs := make([]error, 0)
|
||||||
process := []trie.SyncResult{}
|
process := []trie.SyncResult{}
|
||||||
for _, blob := range data {
|
for _, blob := range data {
|
||||||
// Skip any state trie entries that were not requested
|
// Skip any state trie entries that were not requested
|
||||||
|
|
@ -1079,69 +1077,52 @@ func (q *queue) DeliverNodeData(id string, data [][]byte, callback func(int, boo
|
||||||
}
|
}
|
||||||
// Inject the next state trie item into the processing queue
|
// Inject the next state trie item into the processing queue
|
||||||
process = append(process, trie.SyncResult{Hash: hash, Data: blob})
|
process = append(process, trie.SyncResult{Hash: hash, Data: blob})
|
||||||
accepted++
|
|
||||||
|
|
||||||
delete(request.Hashes, hash)
|
delete(request.Hashes, hash)
|
||||||
delete(q.stateTaskPool, hash)
|
delete(q.stateTaskPool, hash)
|
||||||
}
|
}
|
||||||
// Start the asynchronous node state data injection
|
|
||||||
atomic.AddInt32(&q.stateProcessors, 1)
|
|
||||||
go func() {
|
|
||||||
defer atomic.AddInt32(&q.stateProcessors, -1)
|
|
||||||
q.deliverNodeData(process, callback)
|
|
||||||
}()
|
|
||||||
// Return all failed or missing fetches to the queue
|
// Return all failed or missing fetches to the queue
|
||||||
for hash, index := range request.Hashes {
|
for hash, index := range request.Hashes {
|
||||||
q.stateTaskQueue.Push(hash, float32(index))
|
q.stateTaskQueue.Push(hash, float32(index))
|
||||||
}
|
}
|
||||||
|
if q.stateScheduler == nil {
|
||||||
|
return 0, errNoFetchesPending
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run valid nodes through the trie download scheduler. It writes completed nodes to a
|
||||||
|
// batch, which is committed asynchronously. This may lead to over-fetches because the
|
||||||
|
// scheduler treats everything as written after Process has returned, but it's
|
||||||
|
// unlikely to be an issue in practice.
|
||||||
|
batch := q.stateDatabase.NewBatch()
|
||||||
|
progressed, nproc, procerr := q.stateScheduler.Process(process, batch)
|
||||||
|
q.stateWriters += 1
|
||||||
|
go func() {
|
||||||
|
if procerr == nil {
|
||||||
|
nproc = len(process)
|
||||||
|
procerr = batch.Write()
|
||||||
|
}
|
||||||
|
// Return processing errors through the callback so the sync gets canceled. The
|
||||||
|
// number of writers is decremented prior to the call so PendingNodeData will
|
||||||
|
// return zero when the callback runs.
|
||||||
|
q.lock.Lock()
|
||||||
|
q.stateWriters -= 1
|
||||||
|
q.lock.Unlock()
|
||||||
|
callback(nproc, progressed, procerr)
|
||||||
|
// Wake up WaitResults after the state has been written because it might be
|
||||||
|
// waiting for completion of the pivot block's state download.
|
||||||
|
q.active.Signal()
|
||||||
|
}()
|
||||||
|
|
||||||
// If none of the data items were good, it's a stale delivery
|
// If none of the data items were good, it's a stale delivery
|
||||||
switch {
|
switch {
|
||||||
case len(errs) == 0:
|
case len(errs) == 0:
|
||||||
return accepted, nil
|
return len(process), nil
|
||||||
case len(errs) == len(request.Hashes):
|
case len(errs) == len(request.Hashes):
|
||||||
return accepted, errStaleDelivery
|
return len(process), errStaleDelivery
|
||||||
default:
|
default:
|
||||||
return accepted, fmt.Errorf("multiple failures: %v", errs)
|
return len(process), fmt.Errorf("multiple failures: %v", errs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// deliverNodeData is the asynchronous node data processor that injects a batch
|
|
||||||
// of sync results into the state scheduler.
|
|
||||||
func (q *queue) deliverNodeData(results []trie.SyncResult, callback func(int, bool, error)) {
|
|
||||||
// Wake up WaitResults after the state has been written because it
|
|
||||||
// might be waiting for the pivot block state to get completed.
|
|
||||||
defer q.active.Signal()
|
|
||||||
|
|
||||||
// Process results one by one to permit task fetches in between
|
|
||||||
progressed := false
|
|
||||||
for i, result := range results {
|
|
||||||
q.stateSchedLock.Lock()
|
|
||||||
|
|
||||||
if q.stateScheduler == nil {
|
|
||||||
// Syncing aborted since this async delivery started, bail out
|
|
||||||
q.stateSchedLock.Unlock()
|
|
||||||
callback(i, progressed, errNoFetchesPending)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
batch := q.stateDatabase.NewBatch()
|
|
||||||
prog, _, err := q.stateScheduler.Process([]trie.SyncResult{result}, batch)
|
|
||||||
if err != nil {
|
|
||||||
q.stateSchedLock.Unlock()
|
|
||||||
callback(i, progressed, err)
|
|
||||||
}
|
|
||||||
if err = batch.Write(); err != nil {
|
|
||||||
q.stateSchedLock.Unlock()
|
|
||||||
callback(i, progressed, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Item processing succeeded, release the lock (temporarily)
|
|
||||||
progressed = progressed || prog
|
|
||||||
q.stateSchedLock.Unlock()
|
|
||||||
}
|
|
||||||
callback(len(results), progressed, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare configures the result cache to allow accepting and caching inbound
|
// Prepare configures the result cache to allow accepting and caching inbound
|
||||||
// fetch results.
|
// fetch results.
|
||||||
func (q *queue) Prepare(offset uint64, mode SyncMode, pivot uint64, head *types.Header) {
|
func (q *queue) Prepare(offset uint64, mode SyncMode, pivot uint64, head *types.Header) {
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ 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/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"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"
|
||||||
|
|
@ -469,7 +470,7 @@ func testDAOChallenge(t *testing.T, localForked, remoteForked bool, timeout bool
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db, _ = ethdb.NewMemDatabase()
|
||||||
genesis = core.WriteGenesisBlockForTesting(db)
|
genesis = core.WriteGenesisBlockForTesting(db)
|
||||||
config = ¶ms.ChainConfig{DAOForkBlock: big.NewInt(1), DAOForkSupport: localForked}
|
config = ¶ms.ChainConfig{DAOForkBlock: big.NewInt(1), DAOForkSupport: localForked}
|
||||||
blockchain, _ = core.NewBlockChain(db, config, pow, evmux)
|
blockchain, _ = core.NewBlockChain(db, config, pow, evmux, vm.Config{})
|
||||||
)
|
)
|
||||||
pm, err := NewProtocolManager(config, false, NetworkId, 1000, evmux, new(testTxPool), pow, blockchain, db)
|
pm, err := NewProtocolManager(config, false, NetworkId, 1000, evmux, new(testTxPool), pow, blockchain, db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"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/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
|
@ -56,7 +57,7 @@ func newTestProtocolManager(fastSync bool, blocks int, generator func(int, *core
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db, _ = ethdb.NewMemDatabase()
|
||||||
genesis = core.WriteGenesisBlockForTesting(db, testBank)
|
genesis = core.WriteGenesisBlockForTesting(db, testBank)
|
||||||
chainConfig = ¶ms.ChainConfig{HomesteadBlock: big.NewInt(0)} // homestead set to 0 because of chain maker
|
chainConfig = ¶ms.ChainConfig{HomesteadBlock: big.NewInt(0)} // homestead set to 0 because of chain maker
|
||||||
blockchain, _ = core.NewBlockChain(db, chainConfig, pow, evmux)
|
blockchain, _ = core.NewBlockChain(db, chainConfig, pow, evmux, vm.Config{})
|
||||||
)
|
)
|
||||||
chain, _ := core.GenerateChain(chainConfig, genesis, db, blocks, generator)
|
chain, _ := core.GenerateChain(chainConfig, genesis, db, blocks, generator)
|
||||||
if _, err := blockchain.InsertChain(chain); err != nil {
|
if _, err := blockchain.InsertChain(chain); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -559,8 +559,34 @@ func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr r
|
||||||
|
|
||||||
// EstimateGas returns an estimate of the amount of gas needed to execute the given transaction.
|
// EstimateGas returns an estimate of the amount of gas needed to execute the given transaction.
|
||||||
func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (*hexutil.Big, error) {
|
func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (*hexutil.Big, error) {
|
||||||
|
// Binary search the gas requirement, as it may be higher than the amount used
|
||||||
|
var lo, hi uint64
|
||||||
|
if (*big.Int)(&args.Gas).BitLen() > 0 {
|
||||||
|
hi = (*big.Int)(&args.Gas).Uint64()
|
||||||
|
} else {
|
||||||
|
// Retrieve the current pending block to act as the gas ceiling
|
||||||
|
block, err := s.b.BlockByNumber(ctx, rpc.PendingBlockNumber)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hi = block.GasLimit().Uint64()
|
||||||
|
}
|
||||||
|
for lo+1 < hi {
|
||||||
|
// Take a guess at the gas, and check transaction validity
|
||||||
|
mid := (hi + lo) / 2
|
||||||
|
(*big.Int)(&args.Gas).SetUint64(mid)
|
||||||
|
|
||||||
_, gas, err := s.doCall(ctx, args, rpc.PendingBlockNumber)
|
_, gas, err := s.doCall(ctx, args, rpc.PendingBlockNumber)
|
||||||
return (*hexutil.Big)(gas), err
|
|
||||||
|
// If the transaction became invalid or used all the gas (failed), raise the gas limit
|
||||||
|
if err != nil || gas.Cmp((*big.Int)(&args.Gas)) == 0 {
|
||||||
|
lo = mid
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Otherwise assume the transaction succeeded, lower the gas limit
|
||||||
|
hi = mid
|
||||||
|
}
|
||||||
|
return (*hexutil.Big)(new(big.Int).SetUint64(hi)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecutionResult groups all structured logs emitted by the EVM
|
// ExecutionResult groups all structured logs emitted by the EVM
|
||||||
|
|
|
||||||
18
internal/guide/guide.go
Normal file
18
internal/guide/guide.go
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright 2017 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// Package guide is a small test suite to ensure snippets in the dev guide work.
|
||||||
|
package guide
|
||||||
100
internal/guide/guide_test.go
Normal file
100
internal/guide/guide_test.go
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
// Copyright 2017 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// This file contains the code snippets from the developer's guide embedded into
|
||||||
|
// Go tests. This ensures that any code published in out guides will not break
|
||||||
|
// accidentally via some code update. If some API changes nonetheless that needs
|
||||||
|
// modifying this file, please port any modification over into the developer's
|
||||||
|
// guide wiki pages too!
|
||||||
|
|
||||||
|
package guide
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Tests that the account management snippets work correctly.
|
||||||
|
func TestAccountManagement(t *testing.T) {
|
||||||
|
// Create a temporary folder to work with
|
||||||
|
workdir, err := ioutil.TempDir("", "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create temporary work dir: %v", err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(workdir)
|
||||||
|
|
||||||
|
// Create an encrypted keystore manager with standard crypto parameters
|
||||||
|
am := accounts.NewManager(filepath.Join(workdir, "keystore"), accounts.StandardScryptN, accounts.StandardScryptP)
|
||||||
|
|
||||||
|
// Create a new account with the specified encryption passphrase
|
||||||
|
newAcc, err := am.NewAccount("Creation password")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create new account: %v", err)
|
||||||
|
}
|
||||||
|
// Export the newly created account with a different passphrase. The returned
|
||||||
|
// data from this method invocation is a JSON encoded, encrypted key-file
|
||||||
|
jsonAcc, err := am.Export(newAcc, "Creation password", "Export password")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to export account: %v", err)
|
||||||
|
}
|
||||||
|
// Update the passphrase on the account created above inside the local keystore
|
||||||
|
if err := am.Update(newAcc, "Creation password", "Update password"); err != nil {
|
||||||
|
t.Fatalf("Failed to update account: %v", err)
|
||||||
|
}
|
||||||
|
// Delete the account updated above from the local keystore
|
||||||
|
if err := am.Delete(newAcc, "Update password"); err != nil {
|
||||||
|
t.Fatalf("Failed to delete account: %v", err)
|
||||||
|
}
|
||||||
|
// Import back the account we've exported (and then deleted) above with yet
|
||||||
|
// again a fresh passphrase
|
||||||
|
if _, err := am.Import(jsonAcc, "Export password", "Import password"); err != nil {
|
||||||
|
t.Fatalf("Failed to import account: %v", err)
|
||||||
|
}
|
||||||
|
// Create a new account to sign transactions with
|
||||||
|
signer, err := am.NewAccount("Signer password")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create signer account: %v", err)
|
||||||
|
}
|
||||||
|
txHash := common.HexToHash("0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef")
|
||||||
|
|
||||||
|
// Sign a transaction with a single authorization
|
||||||
|
if _, err := am.SignWithPassphrase(signer, "Signer password", txHash.Bytes()); err != nil {
|
||||||
|
t.Fatalf("Failed to sign with passphrase: %v", err)
|
||||||
|
}
|
||||||
|
// Sign a transaction with multiple manually cancelled authorizations
|
||||||
|
if err := am.Unlock(signer, "Signer password"); err != nil {
|
||||||
|
t.Fatalf("Failed to unlock account: %v", err)
|
||||||
|
}
|
||||||
|
if _, err := am.Sign(signer.Address, txHash.Bytes()); err != nil {
|
||||||
|
t.Fatalf("Failed to sign with unlocked account: %v", err)
|
||||||
|
}
|
||||||
|
if err := am.Lock(signer.Address); err != nil {
|
||||||
|
t.Fatalf("Failed to lock account: %v", err)
|
||||||
|
}
|
||||||
|
// Sign a transaction with multiple automatically cancelled authorizations
|
||||||
|
if err := am.TimedUnlock(signer, "Signer password", time.Second); err != nil {
|
||||||
|
t.Fatalf("Failed to time unlock account: %v", err)
|
||||||
|
}
|
||||||
|
if _, err := am.Sign(signer.Address, txHash.Bytes()); err != nil {
|
||||||
|
t.Fatalf("Failed to sign with time unlocked account: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,10 +19,8 @@ package web3ext
|
||||||
|
|
||||||
var Modules = map[string]string{
|
var Modules = map[string]string{
|
||||||
"admin": Admin_JS,
|
"admin": Admin_JS,
|
||||||
"bzz": Bzz_JS,
|
|
||||||
"chequebook": Chequebook_JS,
|
"chequebook": Chequebook_JS,
|
||||||
"debug": Debug_JS,
|
"debug": Debug_JS,
|
||||||
"ens": ENS_JS,
|
|
||||||
"eth": Eth_JS,
|
"eth": Eth_JS,
|
||||||
"miner": Miner_JS,
|
"miner": Miner_JS,
|
||||||
"net": Net_JS,
|
"net": Net_JS,
|
||||||
|
|
@ -32,101 +30,6 @@ var Modules = map[string]string{
|
||||||
"txpool": TxPool_JS,
|
"txpool": TxPool_JS,
|
||||||
}
|
}
|
||||||
|
|
||||||
const Bzz_JS = `
|
|
||||||
web3._extend({
|
|
||||||
property: 'bzz',
|
|
||||||
methods:
|
|
||||||
[
|
|
||||||
new web3._extend.Method({
|
|
||||||
name: 'syncEnabled',
|
|
||||||
call: 'bzz_syncEnabled',
|
|
||||||
params: 1,
|
|
||||||
inputFormatter: [null]
|
|
||||||
}),
|
|
||||||
new web3._extend.Method({
|
|
||||||
name: 'swapEnabled',
|
|
||||||
call: 'bzz_swapEnabled',
|
|
||||||
params: 1,
|
|
||||||
inputFormatter: [null]
|
|
||||||
}),
|
|
||||||
new web3._extend.Method({
|
|
||||||
name: 'download',
|
|
||||||
call: 'bzz_download',
|
|
||||||
params: 2,
|
|
||||||
inputFormatter: [null, null]
|
|
||||||
}),
|
|
||||||
new web3._extend.Method({
|
|
||||||
name: 'upload',
|
|
||||||
call: 'bzz_upload',
|
|
||||||
params: 2,
|
|
||||||
inputFormatter: [null, null]
|
|
||||||
}),
|
|
||||||
new web3._extend.Method({
|
|
||||||
name: 'resolve',
|
|
||||||
call: 'bzz_resolve',
|
|
||||||
params: 1,
|
|
||||||
inputFormatter: [null]
|
|
||||||
}),
|
|
||||||
new web3._extend.Method({
|
|
||||||
name: 'get',
|
|
||||||
call: 'bzz_get',
|
|
||||||
params: 1,
|
|
||||||
inputFormatter: [null]
|
|
||||||
}),
|
|
||||||
new web3._extend.Method({
|
|
||||||
name: 'put',
|
|
||||||
call: 'bzz_put',
|
|
||||||
params: 2,
|
|
||||||
inputFormatter: [null, null]
|
|
||||||
}),
|
|
||||||
new web3._extend.Method({
|
|
||||||
name: 'modify',
|
|
||||||
call: 'bzz_modify',
|
|
||||||
params: 4,
|
|
||||||
inputFormatter: [null, null, null, null]
|
|
||||||
})
|
|
||||||
],
|
|
||||||
properties:
|
|
||||||
[
|
|
||||||
new web3._extend.Property({
|
|
||||||
name: 'hive',
|
|
||||||
getter: 'bzz_hive'
|
|
||||||
}),
|
|
||||||
new web3._extend.Property({
|
|
||||||
name: 'info',
|
|
||||||
getter: 'bzz_info',
|
|
||||||
}),
|
|
||||||
]
|
|
||||||
});
|
|
||||||
`
|
|
||||||
|
|
||||||
const ENS_JS = `
|
|
||||||
web3._extend({
|
|
||||||
property: 'ens',
|
|
||||||
methods:
|
|
||||||
[
|
|
||||||
new web3._extend.Method({
|
|
||||||
name: 'register',
|
|
||||||
call: 'ens_register',
|
|
||||||
params: 1,
|
|
||||||
inputFormatter: [null]
|
|
||||||
}),
|
|
||||||
new web3._extend.Method({
|
|
||||||
name: 'setContentHash',
|
|
||||||
call: 'ens_setContentHash',
|
|
||||||
params: 2,
|
|
||||||
inputFormatter: [null, null]
|
|
||||||
}),
|
|
||||||
new web3._extend.Method({
|
|
||||||
name: 'resolve',
|
|
||||||
call: 'ens_resolve',
|
|
||||||
params: 1,
|
|
||||||
inputFormatter: [null]
|
|
||||||
}),
|
|
||||||
]
|
|
||||||
})
|
|
||||||
`
|
|
||||||
|
|
||||||
const Chequebook_JS = `
|
const Chequebook_JS = `
|
||||||
web3._extend({
|
web3._extend({
|
||||||
property: 'chequebook',
|
property: 'chequebook',
|
||||||
|
|
@ -385,6 +288,12 @@ web3._extend({
|
||||||
call: 'debug_traceTransaction',
|
call: 'debug_traceTransaction',
|
||||||
params: 2,
|
params: 2,
|
||||||
inputFormatter: [null, null]
|
inputFormatter: [null, null]
|
||||||
|
}),
|
||||||
|
new web3._extend.Method({
|
||||||
|
name: 'preimage',
|
||||||
|
call: 'debug_preimage',
|
||||||
|
params: 1,
|
||||||
|
inputFormatter: [null]
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
properties: []
|
properties: []
|
||||||
|
|
@ -408,12 +317,6 @@ web3._extend({
|
||||||
params: 3,
|
params: 3,
|
||||||
inputFormatter: [web3._extend.formatters.inputTransactionFormatter, web3._extend.utils.fromDecimal, web3._extend.utils.fromDecimal]
|
inputFormatter: [web3._extend.formatters.inputTransactionFormatter, web3._extend.utils.fromDecimal, web3._extend.utils.fromDecimal]
|
||||||
}),
|
}),
|
||||||
new web3._extend.Method({
|
|
||||||
name: 'getNatSpec',
|
|
||||||
call: 'eth_getNatSpec',
|
|
||||||
params: 1,
|
|
||||||
inputFormatter: [web3._extend.formatters.inputTransactionFormatter]
|
|
||||||
}),
|
|
||||||
new web3._extend.Method({
|
new web3._extend.Method({
|
||||||
name: 'signTransaction',
|
name: 'signTransaction',
|
||||||
call: 'eth_signTransaction',
|
call: 'eth_signTransaction',
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,6 @@ type LightEthereum struct {
|
||||||
solcPath string
|
solcPath string
|
||||||
solc *compiler.Solidity
|
solc *compiler.Solidity
|
||||||
|
|
||||||
NatSpec bool
|
|
||||||
netVersionId int
|
netVersionId int
|
||||||
netRPCService *ethapi.PublicNetAPI
|
netRPCService *ethapi.PublicNetAPI
|
||||||
}
|
}
|
||||||
|
|
@ -95,7 +94,6 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
|
||||||
pow: pow,
|
pow: pow,
|
||||||
shutdownChan: make(chan bool),
|
shutdownChan: make(chan bool),
|
||||||
netVersionId: config.NetworkId,
|
netVersionId: config.NetworkId,
|
||||||
NatSpec: config.NatSpec,
|
|
||||||
solcPath: config.SolcPath,
|
solcPath: config.SolcPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"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/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
|
@ -143,7 +144,7 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor
|
||||||
odr = NewLesOdr(db)
|
odr = NewLesOdr(db)
|
||||||
chain, _ = light.NewLightChain(odr, chainConfig, pow, evmux)
|
chain, _ = light.NewLightChain(odr, chainConfig, pow, evmux)
|
||||||
} else {
|
} else {
|
||||||
blockchain, _ := core.NewBlockChain(db, chainConfig, pow, evmux)
|
blockchain, _ := core.NewBlockChain(db, chainConfig, pow, evmux, vm.Config{})
|
||||||
gchain, _ := core.GenerateChain(chainConfig, genesis, db, blocks, generator)
|
gchain, _ := core.GenerateChain(chainConfig, genesis, db, blocks, generator)
|
||||||
if _, err := blockchain.InsertChain(gchain); err != nil {
|
if _, err := blockchain.InsertChain(gchain); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,6 @@ func (self *LesTxRelay) send(txs types.Transactions, count int) {
|
||||||
for p, list := range sendTo {
|
for p, list := range sendTo {
|
||||||
cost := p.GetRequestCost(SendTxMsg, len(list))
|
cost := p.GetRequestCost(SendTxMsg, len(list))
|
||||||
go func(p *peer, list types.Transactions, cost uint64) {
|
go func(p *peer, list types.Transactions, cost uint64) {
|
||||||
p.fcServer.SendRequest(0, cost)
|
|
||||||
p.SendTxs(cost, list)
|
p.SendTxs(cost, list)
|
||||||
}(p, list, cost)
|
}(p, list, cost)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -251,7 +251,7 @@ func testChainOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) {
|
||||||
)
|
)
|
||||||
core.WriteGenesisBlockForTesting(ldb, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds})
|
core.WriteGenesisBlockForTesting(ldb, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds})
|
||||||
// Assemble the test environment
|
// Assemble the test environment
|
||||||
blockchain, _ := core.NewBlockChain(sdb, testChainConfig(), pow, evmux)
|
blockchain, _ := core.NewBlockChain(sdb, testChainConfig(), pow, evmux, vm.Config{})
|
||||||
chainConfig := ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}
|
chainConfig := ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}
|
||||||
gchain, _ := core.GenerateChain(chainConfig, genesis, sdb, 4, testChainGen)
|
gchain, _ := core.GenerateChain(chainConfig, genesis, sdb, 4, testChainGen)
|
||||||
if _, err := blockchain.InsertChain(gchain); err != nil {
|
if _, err := blockchain.InsertChain(gchain); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"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/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -88,7 +89,7 @@ func TestTxPool(t *testing.T) {
|
||||||
)
|
)
|
||||||
core.WriteGenesisBlockForTesting(ldb, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds})
|
core.WriteGenesisBlockForTesting(ldb, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds})
|
||||||
// Assemble the test environment
|
// Assemble the test environment
|
||||||
blockchain, _ := core.NewBlockChain(sdb, testChainConfig(), pow, evmux)
|
blockchain, _ := core.NewBlockChain(sdb, testChainConfig(), pow, evmux, vm.Config{})
|
||||||
chainConfig := ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}
|
chainConfig := ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}
|
||||||
gchain, _ := core.GenerateChain(chainConfig, genesis, sdb, poolTestBlocks, txPoolTestChainGen)
|
gchain, _ := core.GenerateChain(chainConfig, genesis, sdb, poolTestBlocks, txPoolTestChainGen)
|
||||||
if _, err := blockchain.InsertChain(gchain); err != nil {
|
if _, err := blockchain.InsertChain(gchain); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,8 @@ func (s *VMState) Error() error {
|
||||||
|
|
||||||
func (s *VMState) AddLog(log *types.Log) {}
|
func (s *VMState) AddLog(log *types.Log) {}
|
||||||
|
|
||||||
|
func (s *VMState) AddPreimage(hash common.Hash, preimage []byte) {}
|
||||||
|
|
||||||
// errHandler handles and stores any state error that happens during execution.
|
// errHandler handles and stores any state error that happens during execution.
|
||||||
func (s *VMState) errHandler(err error) {
|
func (s *VMState) errHandler(err error) {
|
||||||
if err != nil && s.err == nil {
|
if err != nil && s.err == nil {
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ func (am *AccountManager) GetAccounts() *Accounts {
|
||||||
// DeleteAccount deletes the key matched by account if the passphrase is correct.
|
// DeleteAccount deletes the key matched by account if the passphrase is correct.
|
||||||
// If a contains no filename, the address must match a unique key.
|
// If a contains no filename, the address must match a unique key.
|
||||||
func (am *AccountManager) DeleteAccount(account *Account, passphrase string) error {
|
func (am *AccountManager) DeleteAccount(account *Account, passphrase string) error {
|
||||||
return am.manager.DeleteAccount(accounts.Account{
|
return am.manager.Delete(accounts.Account{
|
||||||
Address: account.account.Address,
|
Address: account.account.Address,
|
||||||
File: account.account.File,
|
File: account.account.File,
|
||||||
}, passphrase)
|
}, passphrase)
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import "fmt"
|
||||||
const (
|
const (
|
||||||
VersionMajor = 1 // Major version component of the current release
|
VersionMajor = 1 // Major version component of the current release
|
||||||
VersionMinor = 5 // Minor version component of the current release
|
VersionMinor = 5 // Minor version component of the current release
|
||||||
VersionPatch = 7 // Patch version component of the current release
|
VersionPatch = 8 // Patch version component of the current release
|
||||||
VersionMeta = "unstable" // Version metadata to append to the version string
|
VersionMeta = "unstable" // Version metadata to append to the version string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,9 +44,7 @@ If Host is left empty, localhost is assumed.
|
||||||
|
|
||||||
Using a public gateway, the above few lines gives you the leanest
|
Using a public gateway, the above few lines gives you the leanest
|
||||||
bzz-scheme aware read-only http client. You really only ever need this
|
bzz-scheme aware read-only http client. You really only ever need this
|
||||||
if you need go-native swarm access to bzz addresses, e.g.,
|
if you need go-native swarm access to bzz addresses.
|
||||||
github.com/ethereum/go-ethereum/common/natspec
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type RoundTripper struct {
|
type RoundTripper struct {
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ 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/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
|
@ -172,7 +173,7 @@ func runBlockTest(homesteadBlock, daoForkBlock, gasPriceFork *big.Int, test *Blo
|
||||||
core.WriteHeadBlockHash(db, test.Genesis.Hash())
|
core.WriteHeadBlockHash(db, test.Genesis.Hash())
|
||||||
evmux := new(event.TypeMux)
|
evmux := new(event.TypeMux)
|
||||||
config := ¶ms.ChainConfig{HomesteadBlock: homesteadBlock, DAOForkBlock: daoForkBlock, DAOForkSupport: true, EIP150Block: gasPriceFork}
|
config := ¶ms.ChainConfig{HomesteadBlock: homesteadBlock, DAOForkBlock: daoForkBlock, DAOForkSupport: true, EIP150Block: gasPriceFork}
|
||||||
chain, err := core.NewBlockChain(db, config, ethash.NewShared(), evmux)
|
chain, err := core.NewBlockChain(db, config, ethash.NewShared(), evmux, vm.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue