/
evm.go
144 lines (126 loc) · 4.14 KB
/
evm.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package cmd
import (
"context"
"fmt"
"math/big"
"path/filepath"
"github.com/alphabill-org/alphabill/logger"
"github.com/alphabill-org/alphabill/network/protocol/genesis"
"github.com/alphabill-org/alphabill/observability"
"github.com/alphabill-org/alphabill/partition"
"github.com/alphabill-org/alphabill/rpc"
"github.com/alphabill-org/alphabill/txsystem/evm"
"github.com/alphabill-org/alphabill/txsystem/evm/api"
"github.com/fxamacker/cbor/v2"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/spf13/cobra"
)
type (
evmConfiguration struct {
baseNodeConfiguration
Node *startNodeConfiguration
GRPCServer *grpcServerConfiguration
RPCServer *rpc.ServerConfiguration
}
)
func newEvmNodeCmd(baseConfig *baseConfiguration) *cobra.Command {
config := &evmConfiguration{
baseNodeConfiguration: baseNodeConfiguration{
Base: baseConfig,
},
Node: &startNodeConfiguration{},
GRPCServer: &grpcServerConfiguration{},
RPCServer: &rpc.ServerConfiguration{},
}
var nodeCmd = &cobra.Command{
Use: "evm",
Short: "Starts an evm partition node",
Long: `Starts an evm partition node, binding to the network address provided by configuration.`,
RunE: func(cmd *cobra.Command, args []string) error {
return runEvmNode(cmd.Context(), config)
},
}
addCommonNodeConfigurationFlags(nodeCmd, config.Node, "evm")
config.GRPCServer.addConfigurationFlags(nodeCmd)
addRPCServerConfigurationFlags(nodeCmd, config.RPCServer)
// mark the --tb-tx flag as mandatory for EVM nodes
if err := nodeCmd.MarkFlagRequired("tx-db"); err != nil {
panic(err)
}
return nodeCmd
}
func runEvmNode(ctx context.Context, cfg *evmConfiguration) error {
pg, err := loadPartitionGenesis(cfg.Node.Genesis)
if err != nil {
return err
}
params := &genesis.EvmPartitionParams{}
if err = cbor.Unmarshal(pg.Params, params); err != nil {
return fmt.Errorf("failed to unmarshal evm partition params: %w", err)
}
stateFilePath := cfg.Node.StateFile
if stateFilePath == "" {
stateFilePath = filepath.Join(cfg.Base.HomeDir, evmDir, evmGenesisStateFileName)
}
state, err := loadStateFile(stateFilePath, evm.NewUnitData)
if err != nil {
return fmt.Errorf("loading state (file %s): %w", cfg.Node.StateFile, err)
}
// Only genesis state can be uncommitted, try to commit
if !state.IsCommitted() {
if err := state.Commit(pg.Certificate); err != nil {
return fmt.Errorf("invalid genesis state: %w", err)
}
}
blockStore, err := initStore(cfg.Node.DbFile)
if err != nil {
return fmt.Errorf("unable to initialize block DB: %w", err)
}
proofStore, err := initStore(cfg.Node.TxIndexerDBFile)
if err != nil {
return fmt.Errorf("unable to initialize proof DB: %w", err)
}
trustBase, err := genesis.NewValidatorTrustBase(pg.RootValidators)
if err != nil {
return fmt.Errorf("failed to create trust base validator: %w", err)
}
keys, err := LoadKeys(cfg.Node.KeyFile, false, false)
if err != nil {
return fmt.Errorf("failed to load node keys: %w", err)
}
nodeID, err := peer.IDFromPublicKey(keys.EncryptionPrivateKey.GetPublic())
if err != nil {
return fmt.Errorf("failed to calculate nodeID: %w", err)
}
log := cfg.Base.observe.Logger().With(logger.NodeID(nodeID))
obs := observability.WithLogger(cfg.Base.observe, log)
systemIdentifier := pg.SystemDescriptionRecord.GetSystemIdentifier()
txs, err := evm.NewEVMTxSystem(
systemIdentifier,
log,
evm.WithBlockGasLimit(params.BlockGasLimit),
evm.WithGasPrice(params.GasUnitPrice),
evm.WithBlockDB(blockStore),
evm.WithTrustBase(trustBase),
evm.WithState(state),
)
if err != nil {
return fmt.Errorf("evm transaction system init failed: %w", err)
}
var ownerIndexer *partition.OwnerIndexer
if cfg.Node.WithOwnerIndex {
ownerIndexer = partition.NewOwnerIndexer(log)
}
node, err := createNode(ctx, txs, cfg.Node, keys, blockStore, proofStore, ownerIndexer, obs)
if err != nil {
return fmt.Errorf("failed to create node evm node: %w", err)
}
cfg.RPCServer.Router = api.NewAPI(
state,
systemIdentifier,
big.NewInt(0).SetUint64(params.BlockGasLimit),
params.GasUnitPrice,
log,
)
return run(ctx, "evm node", node, cfg.GRPCServer, cfg.RPCServer, proofStore, ownerIndexer, obs)
}