Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 36 additions & 4 deletions accounts/abi/bind/backends/simulated.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ import (
// This nil assignment ensures compile time that SimulatedBackend implements bind.ContractBackend.
var _ bind.ContractBackend = (*SimulatedBackend)(nil)

var errBlockNumberUnsupported = errors.New("SimulatedBackend cannot access blocks other than the latest block")
var errGasEstimationFailed = errors.New("gas required exceeds allowance or always failing transaction")
var (
errBlockNumberUnsupported = errors.New("simulatedBackend cannot access blocks other than the latest block")
errGasEstimationFailed = errors.New("gas required exceeds allowance or always failing transaction")
)

// SimulatedBackend implements bind.ContractBackend, simulating a blockchain in
// the background. Its main purpose is to allow easily testing contract bindings.
Expand All @@ -65,8 +67,11 @@ type SimulatedBackend struct {

// NewSimulatedBackend creates a new binding backend using a simulated blockchain
// for testing purposes.
func NewSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
database := rawdb.NewMemoryDatabase()
func NewSimulatedBackend(database ethdb.Database, alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
// Don't panic for the lazy user.
if database == nil {
database = rawdb.NewMemoryDatabase()
}
genesis := core.Genesis{Config: params.AllEthashProtocolChanges, GasLimit: gasLimit, Alloc: alloc}
genesis.MustCommit(database)
blockchain, _ := core.NewBlockChain(database, nil, genesis.Config, ethash.NewFaker(), vm.Config{}, nil)
Expand Down Expand Up @@ -424,6 +429,33 @@ func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error {
return nil
}

// InsertEmptyBlocks inserts a batch of empty blocks to blockchain.
func (b *SimulatedBackend) InsertEmptyBlocks(number int) error {
b.mu.Lock()
defer b.mu.Unlock()
// Insert a batch of empty blocks and commit to the database
blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, number, func(i int, block *core.BlockGen) {})
if _, err := b.blockchain.InsertChain(blocks); err != nil {
panic(err) // This cannot happen unless the simulator is wrong, fail in that case
}
// Apply all pending transactions to new pending blocks.
blocks, _ = core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) {
for _, tx := range b.pendingBlock.Transactions() {
block.AddTx(tx)
}
})

statedb, _ := b.blockchain.State()
b.pendingBlock = blocks[0]
b.pendingState, _ = state.New(b.pendingBlock.Root(), statedb.Database())
return nil
}

// Blockchain returns the underlying blockchain.
func (b *SimulatedBackend) Blockchain() *core.BlockChain {
return b.blockchain
}

// callmsg implements core.Message to allow passing it as a transaction simulator.
type callmsg struct {
ethereum.CallMsg
Expand Down
2 changes: 1 addition & 1 deletion accounts/abi/bind/backends/simulated_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func TestSimulatedBackend(t *testing.T) {
genAlloc := make(core.GenesisAlloc)
genAlloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(9223372036854775807)}

sim := backends.NewSimulatedBackend(genAlloc, gasLimit)
sim := backends.NewSimulatedBackend(nil, genAlloc, gasLimit)

// should return an error if the tx is not found
txHash := common.HexToHash("2")
Expand Down
23 changes: 12 additions & 11 deletions accounts/abi/bind/bind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ var bindTests = []struct {
// Generate a new random account and a funded simulator
key, _ := crypto.GenerateKey()
auth := bind.NewKeyedTransactor(key)
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
sim := backends.NewSimulatedBackend(nil, core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)

// Deploy an interaction tester contract and call a transaction on it
_, _, interactor, err := DeployInteractor(auth, sim, "Deploy string")
Expand Down Expand Up @@ -307,7 +307,7 @@ var bindTests = []struct {
// Generate a new random account and a funded simulator
key, _ := crypto.GenerateKey()
auth := bind.NewKeyedTransactor(key)
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
sim := backends.NewSimulatedBackend(nil, core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)

// Deploy a tuple tester contract and execute a structured call on it
_, _, getter, err := DeployGetter(auth, sim)
Expand Down Expand Up @@ -347,7 +347,7 @@ var bindTests = []struct {
// Generate a new random account and a funded simulator
key, _ := crypto.GenerateKey()
auth := bind.NewKeyedTransactor(key)
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
sim := backends.NewSimulatedBackend(nil, core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)

// Deploy a tuple tester contract and execute a structured call on it
_, _, tupler, err := DeployTupler(auth, sim)
Expand Down Expand Up @@ -399,7 +399,7 @@ var bindTests = []struct {
// Generate a new random account and a funded simulator
key, _ := crypto.GenerateKey()
auth := bind.NewKeyedTransactor(key)
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
sim := backends.NewSimulatedBackend(nil, core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)

// Deploy a slice tester contract and execute a n array call on it
_, _, slicer, err := DeploySlicer(auth, sim)
Expand Down Expand Up @@ -441,7 +441,7 @@ var bindTests = []struct {
// Generate a new random account and a funded simulator
key, _ := crypto.GenerateKey()
auth := bind.NewKeyedTransactor(key)
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
sim := backends.NewSimulatedBackend(nil, core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)

// Deploy a default method invoker contract and execute its default method
_, _, defaulter, err := DeployDefaulter(auth, sim)
Expand Down Expand Up @@ -475,11 +475,12 @@ var bindTests = []struct {
`
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/common"
`,
`
// Create a simulator and wrap a non-deployed contract
sim := backends.NewSimulatedBackend(nil, uint64(10000000000))
sim := backends.NewSimulatedBackend(nil, core.GenesisAlloc{}, uint64(10000000000))

nonexistent, err := NewNonExistent(common.Address{}, sim)
if err != nil {
Expand Down Expand Up @@ -523,7 +524,7 @@ var bindTests = []struct {
// Generate a new random account and a funded simulator
key, _ := crypto.GenerateKey()
auth := bind.NewKeyedTransactor(key)
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
sim := backends.NewSimulatedBackend(nil, core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)

// Deploy a funky gas pattern contract
_, _, limiter, err := DeployFunkyGasPattern(auth, sim)
Expand Down Expand Up @@ -567,7 +568,7 @@ var bindTests = []struct {
// Generate a new random account and a funded simulator
key, _ := crypto.GenerateKey()
auth := bind.NewKeyedTransactor(key)
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
sim := backends.NewSimulatedBackend(nil, core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)

// Deploy a sender tester contract and execute a structured call on it
_, _, callfrom, err := DeployCallFrom(auth, sim)
Expand Down Expand Up @@ -636,7 +637,7 @@ var bindTests = []struct {
// Generate a new random account and a funded simulator
key, _ := crypto.GenerateKey()
auth := bind.NewKeyedTransactor(key)
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
sim := backends.NewSimulatedBackend(nil, core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)

// Deploy a underscorer tester contract and execute a structured call on it
_, _, underscorer, err := DeployUnderscorer(auth, sim)
Expand Down Expand Up @@ -724,7 +725,7 @@ var bindTests = []struct {
// Generate a new random account and a funded simulator
key, _ := crypto.GenerateKey()
auth := bind.NewKeyedTransactor(key)
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
sim := backends.NewSimulatedBackend(nil, core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)

// Deploy an eventer contract
_, _, eventer, err := DeployEventer(auth, sim)
Expand Down Expand Up @@ -908,7 +909,7 @@ var bindTests = []struct {
// Generate a new random account and a funded simulator
key, _ := crypto.GenerateKey()
auth := bind.NewKeyedTransactor(key)
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
sim := backends.NewSimulatedBackend(nil, core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)

//deploy the test contract
_, _, testContract, err := DeployDeeplyNestedArray(auth, sim)
Expand Down
12 changes: 12 additions & 0 deletions accounts/abi/bind/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,18 @@ var (
}
}), nil
}

// Parse{{.Normalized.Name}} is a log parse operation binding the contract event 0x{{printf "%x" .Original.Id}}.
//
// Solidity: {{.Original.String}}
func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Parse{{.Normalized.Name}}(log types.Log) (*{{$contract.Type}}{{.Normalized.Name}}, error) {
event := new({{$contract.Type}}{{.Normalized.Name}})
if err := _{{$contract.Type}}.contract.UnpackLog(event, "{{.Original.Name}}", log); err != nil {
return nil, err
}
return event, nil
}

{{end}}
{{end}}
`
Expand Down
4 changes: 3 additions & 1 deletion accounts/abi/bind/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,11 @@ var waitDeployedTests = map[string]struct {
func TestWaitDeployed(t *testing.T) {
for name, test := range waitDeployedTests {
backend := backends.NewSimulatedBackend(
nil,
core.GenesisAlloc{
crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000)},
}, 10000000,
},
10000000,
)

// Create the transaction.
Expand Down
35 changes: 27 additions & 8 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/internal/debug"
"github.com/ethereum/go-ethereum/les"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/node"
Expand Down Expand Up @@ -317,14 +318,33 @@ func startNode(ctx *cli.Context, stack *node.Node) {
events := make(chan accounts.WalletEvent, 16)
stack.AccountManager().Subscribe(events)

go func() {
// Create a chain state reader for self-derivation
rpcClient, err := stack.Attach()
if err != nil {
utils.Fatalf("Failed to attach to self: %v", err)
// Create a client to interact with local geth node.
rpcClient, err := stack.Attach()
if err != nil {
utils.Fatalf("Failed to attach to self: %v", err)
}
ethClient := ethclient.NewClient(rpcClient)

// Set contract backend for ethereum service if local node
// is serving LES requests.
if ctx.GlobalInt(utils.LightServFlag.Name) > 0 {
var ethService *eth.Ethereum
if err := stack.Service(&ethService); err != nil {
utils.Fatalf("Failed to retrieve ethereum service: %v", err)
}
ethService.SetContractBackend(ethClient)
}
// Set contract backend for les service if local node is
// running as a light client.
if ctx.GlobalString(utils.SyncModeFlag.Name) == "light" {
var lesService *les.LightEthereum
if err := stack.Service(&lesService); err != nil {
utils.Fatalf("Failed to retrieve light ethereum service: %v", err)
}
stateReader := ethclient.NewClient(rpcClient)
lesService.SetContractBackend(ethClient)
}

go func() {
// Open any wallets already attached
for _, wallet := range stack.AccountManager().Wallets() {
if err := wallet.Open(""); err != nil {
Expand All @@ -348,7 +368,7 @@ func startNode(ctx *cli.Context, stack *node.Node) {
}
derivationPaths = append(derivationPaths, accounts.DefaultBaseDerivationPath)

event.Wallet.SelfDerive(derivationPaths, stateReader)
event.Wallet.SelfDerive(derivationPaths, ethClient)

case accounts.WalletDropped:
log.Info("Old wallet dropped", "url", event.Wallet.URL())
Expand Down Expand Up @@ -377,7 +397,6 @@ func startNode(ctx *cli.Context, stack *node.Node) {
"age", common.PrettyAge(timestamp))
stack.Stop()
}

}
}()
}
Expand Down
65 changes: 65 additions & 0 deletions cmd/puppeth/wizard_genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,17 @@ import (
"net/http"
"os"
"path/filepath"
"strings"
"time"

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/contracts/registrar/contract"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/vm/runtime"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
)
Expand Down Expand Up @@ -132,6 +139,64 @@ func (w *wizard) makeGenesis() {
fmt.Println("Specify your chain/network ID if you want an explicit one (default = random)")
genesis.Config.ChainID = new(big.Int).SetUint64(uint64(w.readDefaultInt(rand.Intn(65536))))

// Query the user for checkpoint contract config
fmt.Println()
fmt.Println("Should checkpoint contract be deployed (default = no)")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@karalabe PTAL, I cannot judge this part, I am not familiar with Puppeth code

if w.readDefaultYesNo(false) {
// Read the address of the trusted signers
fmt.Println("Which accounts should be the trusted signer? (advisable at least one)")
var (
signers []common.Address
threshold *big.Int
)
// Get trusted signer addresses
for {
if address := w.readAddress(); address != nil {
signers = append(signers, *address)
continue
}
break
}
// Get stable checkpoint signature minFraction
for {
fmt.Printf("What is the minimal approval threshold? (advisable at most %d)\n", len(signers))
threshold = w.readDefaultBigInt(big.NewInt(0))
if threshold.Int64() <= 0 || threshold.Int64() > int64(len(signers)) {
fmt.Printf("Invalid minimal approval threshold, please enter in range [1, %d]\n", len(signers))
}
break
}
parsed, err := abi.JSON(strings.NewReader(contract.ContractABI))
if err != nil {
log.Crit("Parse contract ABI failed", "err", err)
}
input, err := parsed.Pack("", signers, big.NewInt(params.CheckpointFrequency), big.NewInt(params.CheckpointProcessConfirmations), threshold)
if err != nil {
log.Crit("Pack contract constructor arguments failed", "err", err)
}
config := &runtime.Config{GasLimit: math.MaxInt64}
config.State, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
code, address, _, err := runtime.Create(append(common.FromHex(contract.ContractBin), input...), config)
if err != nil {
log.Crit("Execute contract constructor failed", "err", err)
}
config.State.Commit(true)
genesis.Alloc[address] = core.GenesisAccount{Code: code, Storage: make(map[common.Hash]common.Hash), Balance: big.NewInt(1)}
err = config.State.ForEachStorage(address, func(key, value common.Hash) bool {
genesis.Alloc[address].Storage[key] = value
return true
})
if err != nil {
log.Crit("Failed to iterate contract storage", "err", err)
}
genesis.Config.CheckpointContract = &params.CheckpointContractConfig{
Name: w.network,
ContractAddr: address,
Signers: signers,
Threshold: threshold.Uint64(),
}
}

// All done, store the genesis and flush to disk
log.Info("Configured new genesis block")

Expand Down
Loading