Skip to content

Commit 3b9134a

Browse files
committed
feat: Consensus initialization
1 parent ac48195 commit 3b9134a

5 files changed

Lines changed: 177 additions & 22 deletions

File tree

.dockerignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,9 @@ CODE_OF_CONDUCT.md
2323
CONTRIBUTING.md
2424

2525
# Scripts
26-
scripts/
26+
scripts/
27+
28+
.devbox/
29+
.plugins/
30+
tmp/
31+
snapshots/

blockchain/blockchain.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ type Reader interface {
5252

5353
var (
5454
ErrParentDoesNotMatchHead = errors.New("block's parent hash does not match head block hash")
55-
SupportedStarknetVersion = semver.MustParse("0.13.3")
55+
SupportedStarknetVersion = semver.MustParse("0.14.0")
5656
)
5757

5858
func CheckBlockVersion(protocolVersion string) error {

cmd/juno/juno.go

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ const (
6060
p2pPeersF = "p2p-peers"
6161
p2pFeederNodeF = "p2p-feeder-node"
6262
p2pPrivateKey = "p2p-private-key"
63+
consensusF = "consensus"
64+
consensusAddrF = "consensus-addr"
65+
consensusPeersF = "consensus-peers"
66+
consensusDBPathF = "consensus-db-path"
67+
consensusMockIndexF = "consensus-mock-index" // TODO: remove this
68+
consensusMockCountF = "consensus-mock-count" // TODO: remove this
6369
metricsF = "metrics"
6470
metricsHostF = "metrics-host"
6571
metricsPortF = "metrics-port"
@@ -112,6 +118,12 @@ const (
112118
defaultP2pPeers = ""
113119
defaultP2pFeederNode = false
114120
defaultP2pPrivateKey = ""
121+
defaultConsensus = false
122+
defaultConsensusAddr = ""
123+
defaultConsensusPeers = ""
124+
defaultConsensusDBPath = ""
125+
defaultConsensusMockIndex = 0 // TODO: remove this
126+
defaultConsensusMockCount = 1 // TODO: remove this
115127
defaultMetrics = false
116128
defaultMetricsPort = 9090
117129
defaultGRPC = false
@@ -172,21 +184,27 @@ const (
172184
"These peers can be either Feeder or regular nodes."
173185
p2pFeederNodeUsage = "EXPERIMENTAL: Run juno as a feeder node which will only sync from feeder gateway and gossip the new" +
174186
" blocks to the network."
175-
p2pPrivateKeyUsage = "EXPERIMENTAL: Hexadecimal representation of a private key on the Ed25519 elliptic curve."
176-
metricsUsage = "Enables the Prometheus metrics endpoint on the default port."
177-
metricsHostUsage = "The interface on which the Prometheus endpoint will listen for requests."
178-
metricsPortUsage = "The port on which the Prometheus endpoint will listen for requests."
179-
grpcUsage = "Enable the HTTP gRPC server on the default port."
180-
grpcHostUsage = "The interface on which the gRPC server will listen for requests."
181-
grpcPortUsage = "The port on which the gRPC server will listen for requests."
182-
maxVMsUsage = "Maximum number for VM instances to be used for RPC calls concurrently"
183-
maxVMQueueUsage = "Maximum number for requests to queue after reaching max-vms before starting to reject incoming requests"
184-
remoteDBUsage = "gRPC URL of a remote Juno node"
185-
rpcMaxBlockScanUsage = "Maximum number of blocks scanned in single starknet_getEvents call"
186-
dbCacheSizeUsage = "Determines the amount of memory (in megabytes) allocated for caching data in the database."
187-
dbMaxHandlesUsage = "A soft limit on the number of open files that can be used by the DB"
188-
gwAPIKeyUsage = "API key for gateway endpoints to avoid throttling" //nolint: gosec
189-
gwTimeoutsUsage = "Timeouts for requests made to the gateway. Can be specified in three ways:\n" +
187+
p2pPrivateKeyUsage = "EXPERIMENTAL: Hexadecimal representation of a private key on the Ed25519 elliptic curve."
188+
consensusUsage = "EXPERIMENTAL: Enables the consensus server."
189+
consensusAddrUsage = "EXPERIMENTAL: Specify the address of the consensus server."
190+
consensusPeersUsage = "EXPERIMENTAL: Specify list of consensus peers split by a comma."
191+
consensusDBPathUsage = "EXPERIMENTAL: Specify the path to the consensus database."
192+
consensusMockIndexUsage = "EXPERIMENTAL: Specify the index of the mock consensus server to use." // TODO: remove this
193+
consensusMockCountUsage = "EXPERIMENTAL: Specify the number of mock consensus servers to use." // TODO: remove this
194+
metricsUsage = "Enables the Prometheus metrics endpoint on the default port."
195+
metricsHostUsage = "The interface on which the Prometheus endpoint will listen for requests."
196+
metricsPortUsage = "The port on which the Prometheus endpoint will listen for requests."
197+
grpcUsage = "Enable the HTTP gRPC server on the default port."
198+
grpcHostUsage = "The interface on which the gRPC server will listen for requests."
199+
grpcPortUsage = "The port on which the gRPC server will listen for requests."
200+
maxVMsUsage = "Maximum number for VM instances to be used for RPC calls concurrently"
201+
maxVMQueueUsage = "Maximum number for requests to queue after reaching max-vms before starting to reject incoming requests"
202+
remoteDBUsage = "gRPC URL of a remote Juno node"
203+
rpcMaxBlockScanUsage = "Maximum number of blocks scanned in single starknet_getEvents call"
204+
dbCacheSizeUsage = "Determines the amount of memory (in megabytes) allocated for caching data in the database."
205+
dbMaxHandlesUsage = "A soft limit on the number of open files that can be used by the DB"
206+
gwAPIKeyUsage = "API key for gateway endpoints to avoid throttling" //nolint: gosec
207+
gwTimeoutsUsage = "Timeouts for requests made to the gateway. Can be specified in three ways:\n" +
190208
"- Single value (e.g. '5s'): After each failure, the timeout will increase dynamically.\n" +
191209
"- Comma-separated list (e.g. '5s,10s,20s'): Each value will be used in sequence after failures.\n" +
192210
"- Single value with trailing comma (e.g. '5s,'): Uses a fixed timeout without dynamic adjustment."
@@ -374,6 +392,12 @@ func NewCmd(config *node.Config, run func(*cobra.Command, []string) error) *cobr
374392
junoCmd.Flags().String(p2pPeersF, defaultP2pPeers, p2pPeersUsage)
375393
junoCmd.Flags().Bool(p2pFeederNodeF, defaultP2pFeederNode, p2pFeederNodeUsage)
376394
junoCmd.Flags().String(p2pPrivateKey, defaultP2pPrivateKey, p2pPrivateKeyUsage)
395+
junoCmd.Flags().Bool(consensusF, defaultConsensus, consensusUsage)
396+
junoCmd.Flags().String(consensusAddrF, defaultConsensusAddr, consensusAddrUsage)
397+
junoCmd.Flags().String(consensusPeersF, defaultConsensusPeers, consensusPeersUsage)
398+
junoCmd.Flags().String(consensusDBPathF, defaultConsensusDBPath, consensusDBPathUsage)
399+
junoCmd.Flags().Int(consensusMockIndexF, defaultConsensusMockIndex, consensusMockIndexUsage) // TODO: remove this
400+
junoCmd.Flags().Int(consensusMockCountF, defaultConsensusMockCount, consensusMockCountUsage) // TODO: remove this
377401
junoCmd.Flags().Bool(metricsF, defaultMetrics, metricsUsage)
378402
junoCmd.Flags().String(metricsHostF, defaultHost, metricsHostUsage)
379403
junoCmd.Flags().Uint16(metricsPortF, defaultMetricsPort, metricsPortUsage)

docker-compose.consensus.yaml

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
services:
2+
node0:
3+
image: nethermind/juno:consensus
4+
ports:
5+
- "6060:6060"
6+
command: [
7+
"--http",
8+
"--http-host", "0.0.0.0",
9+
"--network", "mainnet",
10+
"--log-level", "debug",
11+
"--disable-l1-verification",
12+
"--db-path", "/db/main",
13+
"--consensus",
14+
"--consensus-db-path", "/db/consensus",
15+
"--consensus-addr", "/ip4/0.0.0.0/tcp/7070",
16+
"--consensus-peers", "",
17+
"--consensus-mock-index", "0",
18+
"--consensus-mock-count", "4",
19+
]
20+
21+
node1:
22+
image: nethermind/juno:consensus
23+
ports:
24+
- "6061:6060"
25+
depends_on:
26+
- node0
27+
command: [
28+
"--http",
29+
"--http-host", "0.0.0.0",
30+
"--network", "mainnet",
31+
"--log-level", "debug",
32+
"--disable-l1-verification",
33+
"--db-path", "/db/main",
34+
"--consensus",
35+
"--consensus-db-path", "/db/consensus",
36+
"--consensus-addr", "/ip4/0.0.0.0/tcp/7070",
37+
"--consensus-peers", "/dns4/node0/tcp/7070/p2p/12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN",
38+
"--consensus-mock-index", "1",
39+
"--consensus-mock-count", "4",
40+
]
41+
42+
node2:
43+
image: nethermind/juno:consensus
44+
ports:
45+
- "6062:6060"
46+
depends_on:
47+
- node1
48+
command: [
49+
"--http",
50+
"--http-host", "0.0.0.0",
51+
"--network", "mainnet",
52+
"--log-level", "debug",
53+
"--disable-l1-verification",
54+
"--db-path", "/db/main",
55+
"--consensus",
56+
"--consensus-db-path", "/db/consensus",
57+
"--consensus-addr", "/ip4/0.0.0.0/tcp/7070",
58+
"--consensus-peers", "/dns4/node1/tcp/7070/p2p/12D3KooWPjceQrSwdWXPyLLeABRXmuqt69Rg3sBYbU1Nft9HyQ6X",
59+
"--consensus-mock-index", "2",
60+
"--consensus-mock-count", "4",
61+
]
62+
63+
node3:
64+
image: nethermind/juno:consensus
65+
ports:
66+
- "6063:6060"
67+
depends_on:
68+
- node2
69+
command: [
70+
"--http",
71+
"--http-host", "0.0.0.0",
72+
"--network", "mainnet",
73+
"--log-level", "debug",
74+
"--disable-l1-verification",
75+
"--db-path", "/db/main",
76+
"--consensus",
77+
"--consensus-db-path", "/db/consensus",
78+
"--consensus-addr", "/ip4/0.0.0.0/tcp/7070",
79+
"--consensus-peers", "/dns4/node2/tcp/7070/p2p/12D3KooWH3uVF6wv47WnArKHk5p6cvgCJEb74UTmxztmQDc298L3",
80+
"--consensus-mock-index", "3",
81+
"--consensus-mock-count", "4",
82+
]

node/node.go

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import (
1616
"github.com/NethermindEth/juno/builder"
1717
"github.com/NethermindEth/juno/clients/feeder"
1818
"github.com/NethermindEth/juno/clients/gateway"
19+
"github.com/NethermindEth/juno/consensus"
20+
"github.com/NethermindEth/juno/consensus/datasource"
1921
"github.com/NethermindEth/juno/core"
2022
"github.com/NethermindEth/juno/core/felt"
2123
"github.com/NethermindEth/juno/db"
@@ -94,6 +96,13 @@ type Config struct {
9496
P2PFeederNode bool `mapstructure:"p2p-feeder-node"`
9597
P2PPrivateKey string `mapstructure:"p2p-private-key"`
9698

99+
Consensus bool `mapstructure:"consensus"`
100+
ConsensusAddr string `mapstructure:"consensus-addr"`
101+
ConsensusPeers string `mapstructure:"consensus-peers"`
102+
ConsensusDBPath string `mapstructure:"consensus-db-path"`
103+
ConsensusMockIndex int `mapstructure:"consensus-mock-index"` // TODO: remove this
104+
ConsensusMockCount int `mapstructure:"consensus-mock-count"` // TODO: remove this
105+
97106
MaxVMs uint `mapstructure:"max-vms"`
98107
MaxVMQueue uint `mapstructure:"max-vm-queue"`
99108
RPCMaxBlockScan uint `mapstructure:"rpc-max-block-scan"`
@@ -223,12 +232,9 @@ func New(cfg *Config, version string, logLevel *utils.LogLevel) (*Node, error) {
223232
WithLogger(log).
224233
WithTimeouts(timeouts, fixed).
225234
WithAPIKey(cfg.GatewayAPIKey)
226-
feederGatewayDataSource := sync.NewFeederGatewayDataSource(chain, adaptfeeder.New(client))
227-
synchronizer = sync.New(chain, feederGatewayDataSource, log, cfg.PendingPollInterval, dbIsRemote, database)
228-
synchronizer.WithPlugin(junoPlugin)
229-
chain.WithPendingBlockFn(synchronizer.PendingBlock)
230235
gatewayClient = gateway.NewClient(cfg.Network.GatewayURL, log).WithUserAgent(ua).WithAPIKey(cfg.GatewayAPIKey)
231236

237+
syncDataSource := sync.NewFeederGatewayDataSource(chain, adaptfeeder.New(client))
232238
if cfg.P2P {
233239
if cfg.Network == utils.Mainnet {
234240
return nil, fmt.Errorf("P2P cannot be used on %v network", utils.Mainnet)
@@ -246,8 +252,46 @@ func New(cfg *Config, version string, logLevel *utils.LogLevel) (*Node, error) {
246252
}
247253

248254
services = append(services, p2pService)
255+
} else if cfg.Consensus {
256+
// TODO: Replace these mock components with the actual ones
257+
mockConsensusServices := consensus.InitMockServices(0, 0, cfg.ConsensusMockIndex, cfg.ConsensusMockCount)
258+
259+
consensusDB, err := pebble.NewWithOptions(cfg.ConsensusDBPath, cfg.DBCacheSize, cfg.DBMaxHandles, cfg.Colour)
260+
if err != nil {
261+
return nil, fmt.Errorf("open consensus DB: %w", err)
262+
}
263+
264+
consensusServices, err := consensus.Init(
265+
log,
266+
consensusDB,
267+
chain,
268+
nodeVM,
269+
mockConsensusServices.NodeAddress,
270+
mockConsensusServices.Validators,
271+
mockConsensusServices.TimeoutFn,
272+
cfg.ConsensusAddr,
273+
mockConsensusServices.PrivateKey,
274+
)
275+
if err != nil {
276+
return nil, fmt.Errorf("init consensus services: %w", err)
277+
}
278+
279+
if err := consensus.Connect(context.Background(), consensusServices.Host, cfg.ConsensusPeers); err != nil {
280+
return nil, fmt.Errorf("connect to consensus peers: %w", err)
281+
}
282+
283+
dataSource := datasource.New(consensusServices.CommitListener, consensusServices.Proposer, consensusServices.P2P)
284+
syncDataSource = dataSource
285+
286+
services = append(services, consensusServices.Proposer, consensusServices.P2P, consensusServices.Driver, dataSource)
249287
}
250288

289+
if !cfg.P2P || cfg.P2PFeederNode {
290+
synchronizer = sync.New(chain, syncDataSource, log, cfg.PendingPollInterval, dbIsRemote, database)
291+
synchronizer.WithPlugin(junoPlugin)
292+
}
293+
chain.WithPendingBlockFn(synchronizer.PendingBlock)
294+
251295
var syncReader sync.Reader = &sync.NoopSynchronizer{}
252296
if synchronizer != nil {
253297
syncReader = synchronizer
@@ -460,7 +504,7 @@ func (n *Node) Run(ctx context.Context) {
460504
return
461505
}
462506

463-
if n.cfg.Sequencer {
507+
if n.cfg.Sequencer || n.cfg.Consensus {
464508
if err = buildGenesis(n.cfg.SeqGenesisFile, n.blockchain,
465509
vm.New(false, n.log), uint64(n.cfg.RPCCallMaxSteps)); err != nil {
466510
n.log.Errorw("Error building genesis state", "err", err)

0 commit comments

Comments
 (0)