2020-08-03 20:01:38 +00:00
|
|
|
package node
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"crypto/rand"
|
2020-08-19 19:26:48 +00:00
|
|
|
"flag"
|
2020-08-03 20:01:38 +00:00
|
|
|
"fmt"
|
2020-11-15 10:11:07 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
2020-10-21 19:54:40 +00:00
|
|
|
"time"
|
2020-08-03 20:01:38 +00:00
|
|
|
|
2021-06-04 21:18:06 +00:00
|
|
|
"github.com/Secured-Finance/dione/blockchain"
|
|
|
|
|
2021-06-02 19:48:56 +00:00
|
|
|
types2 "github.com/Secured-Finance/dione/blockchain/types"
|
|
|
|
|
2021-05-26 21:06:46 +00:00
|
|
|
gorpc "github.com/libp2p/go-libp2p-gorpc"
|
2020-12-07 15:22:47 +00:00
|
|
|
|
2021-05-26 21:06:46 +00:00
|
|
|
"github.com/Secured-Finance/dione/blockchain/pool"
|
2020-11-27 18:47:58 +00:00
|
|
|
|
2021-05-26 21:06:46 +00:00
|
|
|
"github.com/Secured-Finance/dione/blockchain/sync"
|
2020-11-27 18:47:58 +00:00
|
|
|
|
2021-05-26 21:06:46 +00:00
|
|
|
"github.com/Secured-Finance/dione/consensus"
|
|
|
|
pubsub2 "github.com/Secured-Finance/dione/pubsub"
|
2020-11-27 18:47:58 +00:00
|
|
|
|
|
|
|
"github.com/libp2p/go-libp2p-core/discovery"
|
|
|
|
|
2020-11-23 21:59:27 +00:00
|
|
|
"github.com/Secured-Finance/dione/rpc"
|
|
|
|
rtypes "github.com/Secured-Finance/dione/rpc/types"
|
|
|
|
|
2020-11-18 18:33:03 +00:00
|
|
|
solana2 "github.com/Secured-Finance/dione/rpc/solana"
|
|
|
|
|
|
|
|
"github.com/Secured-Finance/dione/rpc/filecoin"
|
|
|
|
|
2020-11-14 00:32:50 +00:00
|
|
|
"golang.org/x/xerrors"
|
|
|
|
|
|
|
|
"github.com/Secured-Finance/dione/beacon"
|
|
|
|
|
2020-10-21 19:54:40 +00:00
|
|
|
"github.com/Secured-Finance/dione/config"
|
2020-11-13 15:51:23 +00:00
|
|
|
"github.com/Secured-Finance/dione/ethclient"
|
2021-05-26 21:06:46 +00:00
|
|
|
"github.com/libp2p/go-libp2p-core/crypto"
|
2020-08-03 20:01:38 +00:00
|
|
|
"github.com/libp2p/go-libp2p-core/host"
|
2020-10-21 20:36:05 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
2020-08-03 20:01:38 +00:00
|
|
|
)
|
|
|
|
|
2020-11-04 17:46:35 +00:00
|
|
|
const (
|
2020-11-15 10:11:07 +00:00
|
|
|
DefaultPEXUpdateTime = 6 * time.Second
|
2020-11-04 17:46:35 +00:00
|
|
|
)
|
|
|
|
|
2020-08-03 20:01:38 +00:00
|
|
|
type Node struct {
|
2020-10-21 19:54:40 +00:00
|
|
|
Host host.Host
|
2020-11-27 18:47:58 +00:00
|
|
|
PeerDiscovery discovery.Discovery
|
|
|
|
PubSubRouter *pubsub2.PubSubRouter
|
2020-10-21 19:54:40 +00:00
|
|
|
GlobalCtx context.Context
|
|
|
|
GlobalCtxCancel context.CancelFunc
|
|
|
|
Config *config.Config
|
2020-11-12 14:18:30 +00:00
|
|
|
Ethereum *ethclient.EthereumClient
|
2020-10-21 19:54:40 +00:00
|
|
|
ConsensusManager *consensus.PBFTConsensusManager
|
2020-11-14 00:32:50 +00:00
|
|
|
Miner *consensus.Miner
|
|
|
|
Beacon beacon.BeaconNetworks
|
2021-03-17 14:31:27 +00:00
|
|
|
DisputeManager *consensus.DisputeManager
|
2021-06-04 21:18:06 +00:00
|
|
|
BlockPool *blockchain.BlockChain
|
2021-05-26 21:06:46 +00:00
|
|
|
MemPool *pool.Mempool
|
|
|
|
SyncManager sync.SyncManager
|
|
|
|
NetworkService *NetworkService
|
|
|
|
NetworkRPCHost *gorpc.Server
|
2021-06-08 21:30:23 +00:00
|
|
|
//Cache cache.Cache
|
|
|
|
//Wallet *wallet.LocalWallet
|
2020-08-03 20:01:38 +00:00
|
|
|
}
|
|
|
|
|
2020-11-27 18:47:58 +00:00
|
|
|
func NewNode(config *config.Config, prvKey crypto.PrivKey, pexDiscoveryUpdateTime time.Duration) (*Node, error) {
|
|
|
|
n := &Node{
|
|
|
|
Config: config,
|
2020-08-03 20:01:38 +00:00
|
|
|
}
|
|
|
|
|
2020-12-07 15:22:47 +00:00
|
|
|
// initialize libp2p host
|
2021-05-26 21:06:46 +00:00
|
|
|
lhost, err := provideLibp2pHost(n.Config, prvKey)
|
2020-11-27 18:47:58 +00:00
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
n.Host = lhost
|
2021-05-26 21:06:46 +00:00
|
|
|
logrus.Info("Libp2p host has been successfully initialized!")
|
2020-08-03 20:01:38 +00:00
|
|
|
|
2020-12-07 15:22:47 +00:00
|
|
|
// initialize ethereum client
|
2020-11-27 18:47:58 +00:00
|
|
|
ethClient, err := provideEthereumClient(n.Config)
|
2020-11-14 00:32:50 +00:00
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
2020-11-27 18:47:58 +00:00
|
|
|
n.Ethereum = ethClient
|
2021-05-26 21:06:46 +00:00
|
|
|
logrus.Info("Ethereum client has been successfully initialized!")
|
2020-11-23 21:59:27 +00:00
|
|
|
|
2020-12-07 15:22:47 +00:00
|
|
|
// initialize blockchain rpc clients
|
2020-11-23 21:59:27 +00:00
|
|
|
err = n.setupRPCClients()
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
2021-05-26 21:06:46 +00:00
|
|
|
logrus.Info("RPC clients has been successfully configured!")
|
2020-11-23 21:59:27 +00:00
|
|
|
|
2020-12-07 15:22:47 +00:00
|
|
|
// initialize pubsub subsystem
|
2020-11-27 18:47:58 +00:00
|
|
|
psb := providePubsubRouter(lhost, n.Config)
|
|
|
|
n.PubSubRouter = psb
|
2021-05-26 21:06:46 +00:00
|
|
|
logrus.Info("PubSub subsystem has been initialized!")
|
|
|
|
|
|
|
|
// get list of bootstrap multiaddresses
|
|
|
|
baddrs, err := provideBootstrapAddrs(n.Config)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
2020-11-27 18:47:58 +00:00
|
|
|
|
2020-12-07 15:22:47 +00:00
|
|
|
// initialize peer discovery
|
2021-05-26 21:06:46 +00:00
|
|
|
peerDiscovery, err := providePeerDiscovery(baddrs, lhost, pexDiscoveryUpdateTime)
|
2020-12-07 15:22:47 +00:00
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
n.PeerDiscovery = peerDiscovery
|
2021-05-26 21:06:46 +00:00
|
|
|
logrus.Info("Peer discovery subsystem has been initialized!")
|
2020-12-07 15:22:47 +00:00
|
|
|
|
2021-05-26 21:06:46 +00:00
|
|
|
// initialize event log cache subsystem
|
2021-06-08 21:30:23 +00:00
|
|
|
//c := provideCache(config)
|
|
|
|
//n.Cache = c
|
|
|
|
//logrus.Info("Event cache subsystem has initialized!")
|
2021-05-26 21:06:46 +00:00
|
|
|
|
|
|
|
// == initialize blockchain modules
|
|
|
|
|
|
|
|
// initialize blockpool database
|
2021-06-04 21:18:06 +00:00
|
|
|
bp, err := provideBlockChain(n.Config)
|
2021-05-26 21:06:46 +00:00
|
|
|
if err != nil {
|
|
|
|
logrus.Fatalf("Failed to initialize blockpool: %s", err.Error())
|
|
|
|
}
|
|
|
|
n.BlockPool = bp
|
|
|
|
logrus.Info("Block pool database has been successfully initialized!")
|
|
|
|
|
|
|
|
// initialize mempool
|
2021-06-02 19:48:56 +00:00
|
|
|
mp, err := provideMemPool()
|
2021-05-26 21:06:46 +00:00
|
|
|
if err != nil {
|
|
|
|
logrus.Fatalf("Failed to initialize mempool: %s", err.Error())
|
|
|
|
}
|
|
|
|
n.MemPool = mp
|
|
|
|
logrus.Info("Mempool has been successfully initialized!")
|
|
|
|
|
|
|
|
ns := provideNetworkService(bp)
|
|
|
|
n.NetworkService = ns
|
|
|
|
rpcHost := provideNetworkRPCHost(lhost)
|
|
|
|
err = rpcHost.Register(ns)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
logrus.Info("Node p2p RPC network service has been successfully initialized!")
|
|
|
|
|
|
|
|
// initialize libp2p-gorpc client
|
|
|
|
r := provideP2PRPCClient(lhost)
|
|
|
|
|
|
|
|
// initialize sync manager
|
2021-06-02 21:19:52 +00:00
|
|
|
sm, err := provideSyncManager(bp, mp, r, baddrs[0], psb) // FIXME here we just pick up first bootstrap in list
|
2021-05-26 21:06:46 +00:00
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
n.SyncManager = sm
|
|
|
|
logrus.Info("Blockchain synchronization subsystem has been successfully initialized!")
|
2020-11-27 18:47:58 +00:00
|
|
|
|
2020-12-07 15:22:47 +00:00
|
|
|
// initialize mining subsystem
|
2021-06-08 21:30:23 +00:00
|
|
|
miner := provideMiner(n.Host.ID(), *n.Ethereum.GetEthAddress(), n.Beacon, n.Ethereum, prvKey, mp)
|
2020-11-27 18:47:58 +00:00
|
|
|
n.Miner = miner
|
2021-04-19 19:35:40 +00:00
|
|
|
logrus.Info("Mining subsystem has initialized!")
|
2020-11-27 18:47:58 +00:00
|
|
|
|
2020-12-07 15:22:47 +00:00
|
|
|
// initialize consensus subsystem
|
2021-06-08 21:30:23 +00:00
|
|
|
consensusManager := provideConsensusManager(psb, miner, ethClient, prvKey, n.Config.ConsensusMinApprovals)
|
|
|
|
n.ConsensusManager = consensusManager
|
2021-04-19 19:35:40 +00:00
|
|
|
logrus.Info("Consensus subsystem has initialized!")
|
2020-11-27 18:47:58 +00:00
|
|
|
|
2021-06-08 21:30:23 +00:00
|
|
|
// initialize random beacon network subsystem
|
|
|
|
randomBeaconNetwork, err := provideBeacon(psb.Pubsub, consensusManager)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
n.Beacon = randomBeaconNetwork
|
|
|
|
logrus.Info("Random beacon subsystem has been initialized!")
|
|
|
|
|
2021-03-17 14:31:27 +00:00
|
|
|
// initialize dispute subsystem
|
2021-06-08 21:30:23 +00:00
|
|
|
disputeManager, err := provideDisputeManager(context.TODO(), ethClient, consensusManager, config)
|
2021-03-17 14:31:27 +00:00
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
n.DisputeManager = disputeManager
|
2021-04-19 19:35:40 +00:00
|
|
|
logrus.Info("Dispute subsystem has initialized!")
|
2021-03-17 14:31:27 +00:00
|
|
|
|
2020-12-07 15:22:47 +00:00
|
|
|
// initialize internal eth wallet
|
2021-06-08 21:30:23 +00:00
|
|
|
//w, err := provideWallet(n.Host.ID(), rawPrivKey)
|
|
|
|
//if err != nil {
|
|
|
|
// logrus.Fatal(err)
|
|
|
|
//}
|
|
|
|
//n.Wallet = w
|
2020-11-27 18:47:58 +00:00
|
|
|
|
|
|
|
return n, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *Node) Run(ctx context.Context) error {
|
2021-05-26 21:06:46 +00:00
|
|
|
err := n.runLibp2pAsync(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-11-27 18:47:58 +00:00
|
|
|
n.subscribeOnEthContractsAsync(ctx)
|
|
|
|
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *Node) runLibp2pAsync(ctx context.Context) error {
|
|
|
|
logrus.Info(fmt.Sprintf("[*] Your Multiaddress Is: /ip4/%s/tcp/%d/p2p/%s", n.Config.ListenAddr, n.Config.ListenPort, n.Host.ID().Pretty()))
|
|
|
|
|
|
|
|
logrus.Info("Announcing ourselves...")
|
|
|
|
_, err := n.PeerDiscovery.Advertise(context.TODO(), n.Config.Rendezvous)
|
2020-11-27 16:16:08 +00:00
|
|
|
if err != nil {
|
2020-11-27 18:47:58 +00:00
|
|
|
return xerrors.Errorf("failed to announce this node to the network: %v", err)
|
2020-11-27 16:16:08 +00:00
|
|
|
}
|
2020-11-27 18:47:58 +00:00
|
|
|
logrus.Info("Successfully announced!")
|
|
|
|
|
|
|
|
// Discover unbounded count of peers
|
|
|
|
logrus.Info("Searching for other peers...")
|
|
|
|
peerChan, err := n.PeerDiscovery.FindPeers(context.TODO(), n.Config.Rendezvous)
|
2020-11-14 00:32:50 +00:00
|
|
|
if err != nil {
|
2020-11-27 18:47:58 +00:00
|
|
|
return xerrors.Errorf("failed to find new peers: %v", err)
|
2020-11-14 00:32:50 +00:00
|
|
|
}
|
2020-11-27 18:47:58 +00:00
|
|
|
go func() {
|
|
|
|
MainLoop:
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
break MainLoop
|
|
|
|
case newPeer := <-peerChan:
|
|
|
|
{
|
|
|
|
if len(newPeer.Addrs) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if newPeer.ID.String() == n.Host.ID().String() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
logrus.Infof("Found peer: %s", newPeer)
|
|
|
|
// Connect to the peer
|
|
|
|
if err := n.Host.Connect(ctx, newPeer); err != nil {
|
|
|
|
logrus.Warn("Connection failed: ", err)
|
|
|
|
}
|
|
|
|
logrus.Info("Connected to newly discovered peer: ", newPeer)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
return nil
|
2020-10-20 18:18:36 +00:00
|
|
|
}
|
|
|
|
|
2020-11-27 18:47:58 +00:00
|
|
|
func (n *Node) subscribeOnEthContractsAsync(ctx context.Context) {
|
|
|
|
eventChan, subscription, err := n.Ethereum.SubscribeOnOracleEvents(ctx)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal("Couldn't subscribe on ethereum contracts, exiting... ", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
EventLoop:
|
|
|
|
for {
|
|
|
|
select {
|
2021-06-08 21:30:23 +00:00
|
|
|
case <-eventChan:
|
2020-11-27 18:47:58 +00:00
|
|
|
{
|
2021-06-02 19:48:56 +00:00
|
|
|
logrus.Info("Let's wait a little so that all nodes have time to receive the request")
|
2020-12-02 13:42:02 +00:00
|
|
|
time.Sleep(5 * time.Second)
|
|
|
|
|
2021-06-08 21:30:23 +00:00
|
|
|
// TODO make the rpc request and save response as tx payload
|
|
|
|
tx := types2.CreateTransaction([]byte{})
|
2021-06-02 19:48:56 +00:00
|
|
|
err = n.MemPool.StoreTx(tx)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("Failed to store tx in mempool: %s", err.Error())
|
|
|
|
continue
|
2020-11-27 18:47:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
case <-ctx.Done():
|
|
|
|
break EventLoop
|
|
|
|
case <-subscription.Err():
|
|
|
|
logrus.Fatal("Error with ethereum subscription, exiting... ", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
2020-11-23 21:59:27 +00:00
|
|
|
func (n *Node) setupRPCClients() error {
|
|
|
|
fc := filecoin.NewLotusClient()
|
2020-12-02 14:03:39 +00:00
|
|
|
rpc.RegisterRPC(rtypes.RPCTypeFilecoin, map[string]func(string) ([]byte, error){
|
2020-11-23 21:59:27 +00:00
|
|
|
"getTransaction": fc.GetTransaction,
|
2021-04-15 21:01:27 +00:00
|
|
|
"getBlock": fc.GetBlock,
|
2020-11-23 21:59:27 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
sl := solana2.NewSolanaClient()
|
2020-12-02 14:03:39 +00:00
|
|
|
rpc.RegisterRPC(rtypes.RPCTypeSolana, map[string]func(string) ([]byte, error){
|
2020-11-23 21:59:27 +00:00
|
|
|
"getTransaction": sl.GetTransaction,
|
|
|
|
})
|
2020-10-20 18:18:36 +00:00
|
|
|
|
2020-11-23 21:59:27 +00:00
|
|
|
return nil
|
2020-11-14 11:25:14 +00:00
|
|
|
}
|
|
|
|
|
2020-11-27 18:47:58 +00:00
|
|
|
func Start() {
|
2020-08-19 19:26:48 +00:00
|
|
|
configPath := flag.String("config", "", "Path to config")
|
|
|
|
verbose := flag.Bool("verbose", false, "Verbose logging")
|
|
|
|
flag.Parse()
|
2020-08-03 20:01:38 +00:00
|
|
|
|
2020-08-19 19:26:48 +00:00
|
|
|
if *configPath == "" {
|
2020-11-27 18:47:58 +00:00
|
|
|
logrus.Fatal("no config path provided")
|
2020-08-19 19:26:48 +00:00
|
|
|
}
|
2020-11-27 18:47:58 +00:00
|
|
|
cfg, err := config.NewConfig(*configPath)
|
2020-08-19 19:26:48 +00:00
|
|
|
if err != nil {
|
2020-11-27 18:47:58 +00:00
|
|
|
logrus.Fatalf("failed to load config: %v", err)
|
2020-08-19 19:26:48 +00:00
|
|
|
}
|
2020-08-03 20:01:38 +00:00
|
|
|
|
2020-11-15 10:11:07 +00:00
|
|
|
var privateKey crypto.PrivKey
|
|
|
|
|
2020-11-27 18:47:58 +00:00
|
|
|
if cfg.IsBootstrap {
|
2021-05-26 21:06:46 +00:00
|
|
|
// FIXME just a little hack
|
2020-11-15 10:11:07 +00:00
|
|
|
if _, err := os.Stat(".bootstrap_privkey"); os.IsNotExist(err) {
|
|
|
|
privateKey, err = generatePrivateKey()
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
f, _ := os.Create(".bootstrap_privkey")
|
|
|
|
r, _ := privateKey.Raw()
|
2021-05-26 21:06:46 +00:00
|
|
|
_, err = f.Write(r)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
2020-11-15 10:11:07 +00:00
|
|
|
} else {
|
|
|
|
pkey, _ := ioutil.ReadFile(".bootstrap_privkey")
|
|
|
|
privateKey, _ = crypto.UnmarshalEd25519PrivateKey(pkey)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
privateKey, err = generatePrivateKey()
|
2020-11-27 18:47:58 +00:00
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
2020-08-03 20:01:38 +00:00
|
|
|
}
|
|
|
|
|
2020-11-27 18:47:58 +00:00
|
|
|
node, err := NewNode(cfg, privateKey, DefaultPEXUpdateTime)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
2020-08-03 20:01:38 +00:00
|
|
|
|
2020-11-27 18:47:58 +00:00
|
|
|
// log
|
|
|
|
if *verbose {
|
|
|
|
logrus.SetLevel(logrus.DebugLevel)
|
|
|
|
} else {
|
|
|
|
logrus.SetLevel(logrus.DebugLevel)
|
|
|
|
}
|
|
|
|
|
2020-12-07 15:22:47 +00:00
|
|
|
//log.SetDebugLogging()
|
|
|
|
|
2020-11-27 18:47:58 +00:00
|
|
|
//ctx, ctxCancel := context.WithCancel(context.Background())
|
|
|
|
//node.GlobalCtx = ctx
|
|
|
|
//node.GlobalCtxCancel = ctxCancel
|
|
|
|
|
|
|
|
err = node.Run(context.TODO())
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
2020-10-21 19:54:40 +00:00
|
|
|
}
|
2020-08-03 20:01:38 +00:00
|
|
|
}
|
2020-10-20 18:18:36 +00:00
|
|
|
|
|
|
|
func generatePrivateKey() (crypto.PrivKey, error) {
|
|
|
|
r := rand.Reader
|
|
|
|
// Creates a new RSA key pair for this host.
|
2020-11-14 00:32:50 +00:00
|
|
|
prvKey, _, err := crypto.GenerateKeyPairWithReader(crypto.Ed25519, 2048, r)
|
2020-10-20 18:18:36 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return prvKey, nil
|
|
|
|
}
|