Skip to content

Commit 4a598b6

Browse files
authored
Add deploy command to bee (#1314)
1 parent d1920d8 commit 4a598b6

File tree

5 files changed

+424
-83
lines changed

5 files changed

+424
-83
lines changed

cmd/bee/cmd/cmd.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ func newCommand(opts ...option) (c *command, err error) {
100100
return nil, err
101101
}
102102

103+
if err := c.initDeployCmd(); err != nil {
104+
return nil, err
105+
}
106+
103107
c.initVersionCmd()
104108

105109
if err := c.initConfigurateOptionsCmd(); err != nil {

cmd/bee/cmd/deploy.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Copyright 2021 The Swarm Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package cmd
6+
7+
import (
8+
"fmt"
9+
"io/ioutil"
10+
"strings"
11+
12+
"github.com/ethersphere/bee/pkg/logging"
13+
"github.com/ethersphere/bee/pkg/node"
14+
"github.com/sirupsen/logrus"
15+
"github.com/spf13/cobra"
16+
)
17+
18+
func (c *command) initDeployCmd() error {
19+
cmd := &cobra.Command{
20+
Use: "deploy",
21+
Short: "Deploy and fund the chequebook contract",
22+
RunE: func(cmd *cobra.Command, args []string) (err error) {
23+
if (len(args)) > 0 {
24+
return cmd.Help()
25+
}
26+
27+
var logger logging.Logger
28+
switch v := strings.ToLower(c.config.GetString(optionNameVerbosity)); v {
29+
case "0", "silent":
30+
logger = logging.New(ioutil.Discard, 0)
31+
case "1", "error":
32+
logger = logging.New(cmd.OutOrStdout(), logrus.ErrorLevel)
33+
case "2", "warn":
34+
logger = logging.New(cmd.OutOrStdout(), logrus.WarnLevel)
35+
case "3", "info":
36+
logger = logging.New(cmd.OutOrStdout(), logrus.InfoLevel)
37+
case "4", "debug":
38+
logger = logging.New(cmd.OutOrStdout(), logrus.DebugLevel)
39+
case "5", "trace":
40+
logger = logging.New(cmd.OutOrStdout(), logrus.TraceLevel)
41+
default:
42+
return fmt.Errorf("unknown verbosity level %q", v)
43+
}
44+
45+
dataDir := c.config.GetString(optionNameDataDir)
46+
factoryAddress := c.config.GetString(optionNameSwapFactoryAddress)
47+
swapInitialDeposit := c.config.GetString(optionNameSwapInitialDeposit)
48+
swapEndpoint := c.config.GetString(optionNameSwapEndpoint)
49+
50+
stateStore, err := node.InitStateStore(logger, dataDir)
51+
if err != nil {
52+
return
53+
}
54+
55+
defer stateStore.Close()
56+
57+
signerConfig, err := c.configureSigner(cmd, logger)
58+
if err != nil {
59+
return
60+
}
61+
signer := signerConfig.signer
62+
63+
ctx := cmd.Context()
64+
65+
swapBackend, overlayEthAddress, chainID, transactionService, err := node.InitChain(
66+
ctx,
67+
logger,
68+
stateStore,
69+
swapEndpoint,
70+
signer,
71+
)
72+
if err != nil {
73+
return
74+
}
75+
defer swapBackend.Close()
76+
77+
chequebookFactory, err := node.InitChequebookFactory(
78+
logger,
79+
swapBackend,
80+
chainID,
81+
transactionService,
82+
factoryAddress,
83+
)
84+
if err != nil {
85+
return
86+
}
87+
88+
_, err = node.InitChequebookService(
89+
ctx,
90+
logger,
91+
stateStore,
92+
signer,
93+
chainID,
94+
swapBackend,
95+
overlayEthAddress,
96+
transactionService,
97+
chequebookFactory,
98+
swapInitialDeposit,
99+
)
100+
101+
return
102+
},
103+
PreRunE: func(cmd *cobra.Command, args []string) error {
104+
return c.config.BindPFlags(cmd.Flags())
105+
},
106+
}
107+
108+
c.setAllFlags(cmd)
109+
c.root.AddCommand(cmd)
110+
111+
return nil
112+
}

pkg/node/chain.go

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
// Copyright 2021 The Swarm Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package node
6+
7+
import (
8+
"context"
9+
"errors"
10+
"fmt"
11+
"math/big"
12+
"time"
13+
14+
"github.com/ethereum/go-ethereum/common"
15+
"github.com/ethereum/go-ethereum/ethclient"
16+
"github.com/ethersphere/bee/pkg/crypto"
17+
"github.com/ethersphere/bee/pkg/logging"
18+
"github.com/ethersphere/bee/pkg/p2p/libp2p"
19+
"github.com/ethersphere/bee/pkg/settlement/swap"
20+
"github.com/ethersphere/bee/pkg/settlement/swap/chequebook"
21+
"github.com/ethersphere/bee/pkg/settlement/swap/swapprotocol"
22+
"github.com/ethersphere/bee/pkg/settlement/swap/transaction"
23+
"github.com/ethersphere/bee/pkg/storage"
24+
"gopkg.in/src-d/go-log.v1"
25+
)
26+
27+
const (
28+
maxDelay = 1 * time.Minute
29+
)
30+
31+
// InitChain will initialize the Ethereum backend at the given endpoint and
32+
// set up the Transacton Service to interact with it using the provided signer.
33+
func InitChain(
34+
ctx context.Context,
35+
logger logging.Logger,
36+
stateStore storage.StateStorer,
37+
endpoint string,
38+
signer crypto.Signer,
39+
) (*ethclient.Client, common.Address, int64, transaction.Service, error) {
40+
backend, err := ethclient.Dial(endpoint)
41+
if err != nil {
42+
return nil, common.Address{}, 0, nil, fmt.Errorf("dial eth client: %w", err)
43+
}
44+
45+
chainID, err := backend.ChainID(ctx)
46+
if err != nil {
47+
logger.Infof("could not connect to backend at %v. In a swap-enabled network a working blockchain node (for goerli network in production) is required. Check your node or specify another node using --swap-endpoint.", endpoint)
48+
return nil, common.Address{}, 0, nil, fmt.Errorf("get chain id: %w", err)
49+
}
50+
51+
transactionService, err := transaction.NewService(logger, backend, signer, stateStore, chainID)
52+
if err != nil {
53+
return nil, common.Address{}, 0, nil, fmt.Errorf("new transaction service: %w", err)
54+
}
55+
overlayEthAddress, err := signer.EthereumAddress()
56+
if err != nil {
57+
return nil, common.Address{}, 0, nil, fmt.Errorf("eth address: %w", err)
58+
}
59+
60+
// Sync the with the given Ethereum backend:
61+
isSynced, err := transaction.IsSynced(ctx, backend, maxDelay)
62+
if err != nil {
63+
return nil, common.Address{}, 0, nil, fmt.Errorf("is synced: %w", err)
64+
}
65+
if !isSynced {
66+
log.Infof("waiting to sync with the Ethereum backend")
67+
err := transaction.WaitSynced(ctx, backend, maxDelay)
68+
if err != nil {
69+
return nil, common.Address{}, 0, nil, fmt.Errorf("waiting backend sync: %w", err)
70+
}
71+
}
72+
return backend, overlayEthAddress, chainID.Int64(), transactionService, nil
73+
}
74+
75+
// InitChequebookFactory will initialize the chequebook factory with the given
76+
// chain backend.
77+
func InitChequebookFactory(
78+
logger logging.Logger,
79+
backend *ethclient.Client,
80+
chainID int64,
81+
transactionService transaction.Service,
82+
factoryAddress string,
83+
) (chequebook.Factory, error) {
84+
var addr common.Address
85+
if factoryAddress == "" {
86+
var found bool
87+
addr, found = chequebook.DiscoverFactoryAddress(chainID)
88+
if !found {
89+
return nil, errors.New("no known factory address for this network")
90+
}
91+
log.Infof("using default factory address for chain id %d: %x", chainID, addr)
92+
} else if !common.IsHexAddress(factoryAddress) {
93+
return nil, errors.New("malformed factory address")
94+
} else {
95+
addr = common.HexToAddress(factoryAddress)
96+
log.Infof("using custom factory address: %x", factoryAddress)
97+
}
98+
99+
chequebookFactory, err := chequebook.NewFactory(
100+
backend,
101+
transactionService,
102+
addr,
103+
chequebook.NewSimpleSwapFactoryBindingFunc,
104+
)
105+
if err != nil {
106+
return nil, fmt.Errorf("new factory: %w", err)
107+
}
108+
109+
return chequebookFactory, nil
110+
}
111+
112+
// InitChequebookService will initialize the chequebook service with the given
113+
// chequebook factory and chain backend.
114+
func InitChequebookService(
115+
ctx context.Context,
116+
logger logging.Logger,
117+
stateStore storage.StateStorer,
118+
signer crypto.Signer,
119+
chainID int64,
120+
backend *ethclient.Client,
121+
overlayEthAddress common.Address,
122+
transactionService transaction.Service,
123+
chequebookFactory chequebook.Factory,
124+
initialDeposit string,
125+
) (chequebook.Service, error) {
126+
chequeSigner := chequebook.NewChequeSigner(signer, chainID)
127+
128+
deposit, ok := new(big.Int).SetString(initialDeposit, 10)
129+
if !ok {
130+
return nil, fmt.Errorf("initial swap deposit \"%s\" cannot be parsed", initialDeposit)
131+
}
132+
133+
chequebookService, err := chequebook.Init(
134+
ctx,
135+
chequebookFactory,
136+
stateStore,
137+
logger,
138+
deposit,
139+
transactionService,
140+
backend,
141+
chainID,
142+
overlayEthAddress,
143+
chequeSigner,
144+
chequebook.NewSimpleSwapBindings,
145+
chequebook.NewERC20Bindings,
146+
)
147+
if err != nil {
148+
return nil, fmt.Errorf("chequebook init: %w", err)
149+
}
150+
151+
return chequebookService, nil
152+
}
153+
154+
func initChequeStoreCashout(
155+
stateStore storage.StateStorer,
156+
swapBackend transaction.Backend,
157+
chequebookFactory chequebook.Factory,
158+
chainID int64,
159+
overlayEthAddress common.Address,
160+
transactionService transaction.Service,
161+
) (chequebook.ChequeStore, chequebook.CashoutService, error) {
162+
chequeStore := chequebook.NewChequeStore(
163+
stateStore,
164+
swapBackend,
165+
chequebookFactory,
166+
chainID,
167+
overlayEthAddress,
168+
chequebook.NewSimpleSwapBindings,
169+
chequebook.RecoverCheque,
170+
)
171+
172+
cashout, err := chequebook.NewCashoutService(
173+
stateStore,
174+
chequebook.NewSimpleSwapBindings,
175+
swapBackend,
176+
transactionService,
177+
chequeStore,
178+
)
179+
if err != nil {
180+
return nil, nil, err
181+
}
182+
183+
return chequeStore, cashout, nil
184+
}
185+
186+
// InitSwap will initialize and register the swap service.
187+
func InitSwap(
188+
p2ps *libp2p.Service,
189+
logger logging.Logger,
190+
stateStore storage.StateStorer,
191+
networkID uint64,
192+
overlayEthAddress common.Address,
193+
chequebookService chequebook.Service,
194+
chequeStore chequebook.ChequeStore,
195+
cashoutService chequebook.CashoutService,
196+
) (*swap.Service, error) {
197+
swapProtocol := swapprotocol.New(p2ps, logger, overlayEthAddress)
198+
swapAddressBook := swap.NewAddressbook(stateStore)
199+
200+
swapService := swap.New(
201+
swapProtocol,
202+
logger,
203+
stateStore,
204+
chequebookService,
205+
chequeStore,
206+
swapAddressBook,
207+
networkID,
208+
cashoutService,
209+
p2ps,
210+
)
211+
212+
swapProtocol.SetSwap(swapService)
213+
214+
err := p2ps.AddProtocol(swapProtocol.Protocol())
215+
if err != nil {
216+
return nil, err
217+
}
218+
219+
return swapService, nil
220+
}

0 commit comments

Comments
 (0)