Skip to content

Commit 0b16a1c

Browse files
committed
[GH-846] Added bootstrap-url parameter for simple initialization of archive node.
1 parent 2b928ca commit 0b16a1c

27 files changed

+352
-58
lines changed

nil/cmd/nild/main.go

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ package main
22

33
import (
44
"context"
5+
"encoding/json"
56
"errors"
67
"os"
8+
"time"
79

10+
rpc_client "github.com/NilFoundation/nil/nil/client/rpc"
811
"github.com/NilFoundation/nil/nil/cmd/nild/nildconfig"
912
"github.com/NilFoundation/nil/nil/common/check"
1013
"github.com/NilFoundation/nil/nil/common/concurrent"
@@ -19,6 +22,7 @@ import (
1922
"github.com/NilFoundation/nil/nil/services/indexer"
2023
"github.com/NilFoundation/nil/nil/services/nilservice"
2124
"github.com/NilFoundation/nil/nil/services/rpc/transport"
25+
rpctypes "github.com/NilFoundation/nil/nil/services/rpc/types"
2226
"github.com/spf13/cobra"
2327
"github.com/spf13/pflag"
2428
)
@@ -32,7 +36,7 @@ var logFilter string
3236
func main() {
3337
logger := logging.NewLogger("nild")
3438

35-
cfg := parseArgs()
39+
cfg := parseArgs(logger)
3640

3741
logging.ApplyComponentsFilter(logFilter)
3842

@@ -100,7 +104,49 @@ func addBasicFlags(fset *pflag.FlagSet, cfg *nildconfig.Config) {
100104
&cfg.CollatorTickPeriodMs, "collator-tick-ms", cfg.CollatorTickPeriodMs, "collator tick period in milliseconds")
101105
}
102106

103-
func parseArgs() *nildconfig.Config {
107+
func doBootstrapRequestAndPatchConfig(bootstrapUrl string, cfg *nildconfig.Config, logger logging.Logger) error {
108+
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
109+
defer cancel()
110+
111+
client := rpc_client.NewRawClient(bootstrapUrl, logger)
112+
response, err := client.RawCall(ctx, "debug_getBootstrapConfig")
113+
if err != nil {
114+
logger.Error().Err(err).Msg("failed to fetch bootstrap config")
115+
return err
116+
}
117+
118+
var bootstrapConfig rpctypes.BootstrapConfig
119+
err = json.Unmarshal(response, &bootstrapConfig)
120+
if err != nil {
121+
return err
122+
}
123+
124+
// Patch config
125+
//
126+
// Since we override a limited set of settings rather than arbitrary ones,
127+
// we can choose a reasonable merging strategy that mostly avoids unexpected results.
128+
cfg.NShards = bootstrapConfig.NShards
129+
130+
if cfg.ZeroState != nil {
131+
logger.Warn().Msg("overriding zero state config")
132+
}
133+
cfg.ZeroState = bootstrapConfig.ZeroStateConfig
134+
135+
if cfg.Network.TcpPort == 0 {
136+
tcpPort := 3000 // Some port to work through libp2p
137+
logger.Info().Msgf("setting TCP port to %d", tcpPort)
138+
cfg.Network.TcpPort = tcpPort
139+
}
140+
141+
cfg.BootstrapPeers = append(cfg.BootstrapPeers, bootstrapConfig.BootstrapPeers...)
142+
143+
cfg.Network.DHTBootstrapPeers = append(cfg.Network.DHTBootstrapPeers, bootstrapConfig.DhtBootstrapPeers...)
144+
cfg.Network.DHTEnabled = true
145+
146+
return nil
147+
}
148+
149+
func parseArgs(logger logging.Logger) *nildconfig.Config {
104150
cfg, err := loadConfig()
105151
check.PanicIfErr(err)
106152

@@ -179,17 +225,30 @@ func parseArgs() *nildconfig.Config {
179225
replayCmd.Flags().Var(&cfg.Replay.BlockIdLast, "last-block", "last block id to replay")
180226
replayCmd.Flags().Var(&cfg.Replay.ShardId, "shard-id", "shard id to replay block from")
181227

228+
var bootstrapUrl string
182229
archiveCmd := &cobra.Command{
183230
Use: "archive",
184231
Short: "Run nil archive node",
185-
Run: func(cmd *cobra.Command, args []string) {
232+
RunE: func(cmd *cobra.Command, args []string) error {
186233
cfg.RunMode = nilservice.ArchiveRunMode
234+
235+
if bootstrapUrl != "" {
236+
return doBootstrapRequestAndPatchConfig(bootstrapUrl, cfg, logger)
237+
}
238+
239+
return nil
187240
},
188241
}
189242

190243
addBasicFlags(archiveCmd.Flags(), cfg)
191244
cmdflags.AddNetwork(archiveCmd.Flags(), cfg.Network)
192245
cmdflags.AddTelemetry(archiveCmd.Flags(), cfg.Telemetry)
246+
// N.B. Despite the fact that we override the config with the loaded configuration, we handle this flag as usual,
247+
// and not through a hack like GetConfigNameFromArgs. There are two reasons for this:
248+
// - We patch a limited number of settings and are confident that other processing should not depend on them
249+
// - We believe that the loaded settings should take precedence over all others, so we apply them last.
250+
archiveCmd.Flags().StringVar(
251+
&bootstrapUrl, "bootstrap-url", "", "url to fetch initial configuration from (genesis config etc.")
193252

194253
rpcCmd := &cobra.Command{
195254
Use: "rpc",

nil/internal/cobrax/cmdflags/network.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ func AddNetwork(fset *pflag.FlagSet, cfg *network.Config) {
1515

1616
fset.BoolVar(&cfg.ServeRelay, "serve-relay", cfg.ServeRelay, "enable relay")
1717
fset.Var(&cfg.Relays, "relays", "relay peers")
18+
fset.Var(&cfg.RelayPublicAddress, "relay-public-address", "public address of relay")
1819

1920
fset.BoolVar(&cfg.DHTEnabled, "with-discovery", cfg.DHTEnabled, "enable discovery (with Kademlia DHT)")
2021
fset.Var(&cfg.DHTBootstrapPeers, "discovery-bootstrap-peers", "bootstrap peers for discovery")

nil/internal/execution/zerostate.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ import (
1616
)
1717

1818
type ContractDescr struct {
19-
Name string `yaml:"name"`
20-
Address types.Address `yaml:"address,omitempty"`
21-
Value types.Value `yaml:"value"`
22-
Shard types.ShardId `yaml:"shard,omitempty"`
23-
Contract string `yaml:"contract"`
24-
CtorArgs []any `yaml:"ctorArgs,omitempty"`
19+
Name string `yaml:"name" json:"name"`
20+
Address types.Address `yaml:"address,omitempty" json:"address,omitempty"`
21+
Value types.Value `yaml:"value" json:"value"`
22+
Shard types.ShardId `yaml:"shard,omitempty" json:"shard,omitempty"`
23+
Contract string `yaml:"contract" json:"contract"`
24+
CtorArgs []any `yaml:"ctorArgs,omitempty" json:"ctorArgs,omitempty"`
2525
}
2626

2727
type MainKeys struct {
@@ -30,13 +30,13 @@ type MainKeys struct {
3030
}
3131

3232
type ConfigParams struct {
33-
Validators config.ParamValidators `yaml:"validators,omitempty"`
34-
GasPrice config.ParamGasPrice `yaml:"gasPrice"`
33+
Validators config.ParamValidators `yaml:"validators,omitempty" json:"validators,omitempty"`
34+
GasPrice config.ParamGasPrice `yaml:"gasPrice" json:"gasPrice"`
3535
}
3636

3737
type ZeroStateConfig struct {
38-
ConfigParams ConfigParams `yaml:"config,omitempty"`
39-
Contracts []*ContractDescr `yaml:"contracts"`
38+
ConfigParams ConfigParams `yaml:"config,omitempty" json:"config,omitempty"`
39+
Contracts []*ContractDescr `yaml:"contracts" json:"contracts"`
4040
}
4141

4242
func CreateDefaultZeroStateConfig(mainPublicKey []byte) (*ZeroStateConfig, error) {

nil/internal/network/addr_info.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
package network
22

33
import (
4+
"errors"
5+
46
"github.com/NilFoundation/nil/nil/common"
57
"github.com/libp2p/go-libp2p/core/peer"
8+
"gopkg.in/yaml.v3"
69
)
710

811
type AddrInfo peer.AddrInfo
912

13+
func (a AddrInfo) Empty() bool {
14+
return errors.Is(a.ID.Validate(), peer.ErrEmptyPeerID)
15+
}
16+
1017
func (a *AddrInfo) Set(value string) error {
1118
addr, err := peer.AddrInfoFromString(value)
1219
if err != nil {
@@ -44,6 +51,18 @@ func (a *AddrInfo) UnmarshalText(text []byte) error {
4451
return a.Set(string(text))
4552
}
4653

54+
func (a AddrInfo) MarshalYAML() (any, error) {
55+
return a.String(), nil
56+
}
57+
58+
func (a *AddrInfo) UnmarshalYAML(value *yaml.Node) error {
59+
var str string
60+
if err := value.Decode(&str); err != nil {
61+
return err
62+
}
63+
return a.Set(str)
64+
}
65+
4766
type AddrInfoSlice = common.PValueSlice[*AddrInfo, AddrInfo]
4867

4968
func ToLibP2pAddrInfoSlice(s AddrInfoSlice) []peer.AddrInfo {

nil/internal/network/addr_info_test.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,17 @@ func TestConfigYamlSerialization(t *testing.T) {
2525
addrInfo1,
2626
addrInfo2,
2727
},
28+
RelayPublicAddress: addrInfo1,
2829
}
2930

3031
data, err := yaml.Marshal(config)
3132
require.NoError(t, err)
3233

33-
expectedYaml := `dhtBootstrapPeers:
34-
- /ip4/127.0.0.1/tcp/1500/p2p/16Uiu2HAmQctkUi9y7WfUtYa9rPon1m5TRBtXSvUwi2VtpbWZj4yf
35-
- /ip4/192.168.1.1/tcp/4002/p2p/16Uiu2HAmQctkUi9y7WfUtYa9rPon1m5TRBtXSvUwi2VtpbWZj4yg
34+
expectedYaml := `---
35+
dhtBootstrapPeers:
36+
- /ip4/127.0.0.1/tcp/1500/p2p/16Uiu2HAmQctkUi9y7WfUtYa9rPon1m5TRBtXSvUwi2VtpbWZj4yf
37+
- /ip4/192.168.1.1/tcp/4002/p2p/16Uiu2HAmQctkUi9y7WfUtYa9rPon1m5TRBtXSvUwi2VtpbWZj4yg
38+
relayPublicAddress: /ip4/127.0.0.1/tcp/1500/p2p/16Uiu2HAmQctkUi9y7WfUtYa9rPon1m5TRBtXSvUwi2VtpbWZj4yf
3639
`
3740
require.YAMLEq(t, expectedYaml, string(data))
3841

@@ -53,15 +56,14 @@ func TestAddrInfoStringRepresentation(t *testing.T) {
5356
"/ip4/192.168.0.10/tcp/4002/p2p/16Uiu2HAmQctkUi9y7WfUtYa9rPon1m5TRBtXSvUwi2VtpbWZj4yf")
5457
require.NoError(t, err)
5558

56-
_, id := peer.SplitAddr(addr1)
59+
transport1, id := peer.SplitAddr(addr1)
60+
transport2, _ := peer.SplitAddr(addr2)
5761
addrInfo := AddrInfo{
5862
ID: id,
59-
Addrs: []ma.Multiaddr{addr1, addr2},
63+
Addrs: []ma.Multiaddr{transport1, transport2},
6064
}
6165

62-
expectedString := "/ip4/127.0.0.1/tcp/1500/p2p/16Uiu2HAmQctkUi9y7WfUtYa9rPon1m5TRBtXSvUwi2VtpbWZj4yf" +
63-
"/p2p/16Uiu2HAmQctkUi9y7WfUtYa9rPon1m5TRBtXSvUwi2VtpbWZj4yf," +
64-
"/ip4/192.168.0.10/tcp/4002/p2p/16Uiu2HAmQctkUi9y7WfUtYa9rPon1m5TRBtXSvUwi2VtpbWZj4yf" +
65-
"/p2p/16Uiu2HAmQctkUi9y7WfUtYa9rPon1m5TRBtXSvUwi2VtpbWZj4yf"
66+
expectedString := "/ip4/127.0.0.1/tcp/1500/p2p/16Uiu2HAmQctkUi9y7WfUtYa9rPon1m5TRBtXSvUwi2VtpbWZj4yf," +
67+
"/ip4/192.168.0.10/tcp/4002/p2p/16Uiu2HAmQctkUi9y7WfUtYa9rPon1m5TRBtXSvUwi2VtpbWZj4yf"
6668
require.Equal(t, expectedString, addrInfo.String())
6769
}

nil/internal/network/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ type Config struct {
2323

2424
ServeRelay bool `yaml:"serveRelay,omitempty"`
2525
Relays AddrInfoSlice `yaml:"relays,omitempty"`
26+
// RelayPublicAddress is the public relay address used to wrap the node's own address in BootstrapConfig if set.
27+
RelayPublicAddress AddrInfo `yaml:"relayPublicAddress,omitempty"`
2628

2729
DHTEnabled bool `yaml:"dhtEnabled,omitempty"`
2830
DHTBootstrapPeers AddrInfoSlice `yaml:"dhtBootstrapPeers,omitempty"`

nil/internal/network/host.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/libp2p/go-libp2p/core/network"
1515
"github.com/libp2p/go-libp2p/core/peer"
1616
"github.com/libp2p/go-libp2p/p2p/net/connmgr"
17+
"github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay"
1718
"github.com/libp2p/go-libp2p/p2p/security/noise"
1819
quic "github.com/libp2p/go-libp2p/p2p/transport/quic"
1920
"github.com/libp2p/go-libp2p/p2p/transport/tcp"
@@ -88,7 +89,7 @@ func newHost(ctx context.Context, conf *Config) (Host, logging.Logger, error) {
8889
}
8990

9091
if conf.ServeRelay {
91-
options = append(options, libp2p.EnableRelayService())
92+
options = append(options, libp2p.EnableRelayService(relay.WithInfiniteLimits()))
9293

9394
// todo: remove it after relay is tested
9495
// this is to make sure that the relay is not disabled

nil/internal/network/relay_test.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package network
22

33
import (
4+
"context"
45
"testing"
56

67
"github.com/libp2p/go-libp2p/core/network"
7-
"github.com/libp2p/go-libp2p/core/peer"
88
"github.com/stretchr/testify/suite"
99
)
1010

@@ -29,6 +29,9 @@ func (s *RelayTestSuite) TestRelay() {
2929
Relays: []AddrInfo{CalcAddress(relay)},
3030
Reachability: network.ReachabilityPrivate,
3131
})
32+
private.SetRequestHandler(s.context, "/hello", func(context.Context, []byte) ([]byte, error) {
33+
return []byte("world"), nil
34+
})
3235
defer private.Close()
3336

3437
// Connect the private node to the relay (avoiding discovery)
@@ -38,12 +41,15 @@ func (s *RelayTestSuite) TestRelay() {
3841
client := s.newManager()
3942
defer client.Close()
4043

41-
relayedAddr, err := peer.AddrInfoFromString(hostAddress(relay) + "/p2p-circuit/p2p/" + private.host.ID().String())
44+
relayedAddr := RelayedAddress(private.host.ID(), CalcAddress(relay))
45+
id, err := client.Connect(s.context, relayedAddr)
4246
s.Require().NoError(err)
47+
s.Require().Equal(private.host.ID(), id)
4348

44-
id, err := client.Connect(s.context, AddrInfo(*relayedAddr))
49+
resp, err := client.SendRequestAndGetResponse(
50+
network.WithAllowLimitedConn(s.context, "relay"), id, "/hello", []byte("hello"))
4551
s.Require().NoError(err)
46-
s.Require().Equal(private.host.ID(), id)
52+
s.Require().Equal("world", string(resp))
4753
}
4854

4955
func TestRelay(t *testing.T) {

nil/internal/network/testaide.go

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,14 @@ import (
1111
"time"
1212

1313
"github.com/NilFoundation/nil/nil/common"
14-
"github.com/NilFoundation/nil/nil/common/check"
1514
"github.com/libp2p/go-libp2p/core/peer"
1615
"github.com/stretchr/testify/require"
1716
)
1817

19-
func CalcAddress(m Manager) AddrInfo {
20-
addr, err := peer.AddrInfoFromString(hostAddress(m))
21-
check.PanicIfErr(err)
22-
return AddrInfo(*addr)
23-
}
24-
25-
func hostAddress(m Manager) string {
26-
return m.getHost().Addrs()[0].String() + "/p2p/" + m.getHost().ID().String()
27-
}
28-
2918
func NewTestManagerWithBaseConfig(ctx context.Context, t *testing.T, conf *Config) *BasicManager {
3019
t.Helper()
3120

3221
conf = common.CopyPtr(conf)
33-
if conf.IPV4Address == "" {
34-
conf.IPV4Address = "127.0.0.1"
35-
}
3622
if conf.PrivateKey == nil {
3723
privateKey, err := GeneratePrivateKey()
3824
require.NoError(t, err)

nil/internal/network/utils.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package network
2+
3+
import (
4+
"github.com/NilFoundation/nil/nil/common/check"
5+
ma "github.com/multiformats/go-multiaddr"
6+
)
7+
8+
func CalcAddress(m Manager) AddrInfo {
9+
return AddrInfo{m.getHost().ID(), m.getHost().Addrs()}
10+
}
11+
12+
func RelayedAddress(p PeerID, relayAddrInfo AddrInfo) AddrInfo {
13+
addrInfo := AddrInfo{
14+
ID: p,
15+
Addrs: make([]ma.Multiaddr, len(relayAddrInfo.Addrs)),
16+
}
17+
for i, relayAddr := range relayAddrInfo.Addrs {
18+
var addr ma.Multiaddr
19+
relay, err := ma.NewComponent("p2p", relayAddrInfo.ID.String())
20+
check.PanicIfErr(err)
21+
addr = addr.AppendComponent(relay)
22+
circuit, err := ma.NewComponent("p2p-circuit", "")
23+
check.PanicIfErr(err)
24+
addr = addr.AppendComponent(circuit)
25+
addrInfo.Addrs[i] = relayAddr.Encapsulate(addr)
26+
}
27+
return addrInfo
28+
}

0 commit comments

Comments
 (0)