diff --git a/blockchain/pool/mempool.go b/blockchain/pool/mempool.go index 4d7697e..22fec10 100644 --- a/blockchain/pool/mempool.go +++ b/blockchain/pool/mempool.go @@ -2,6 +2,7 @@ package pool import ( "encoding/hex" + "errors" "sort" "time" @@ -17,6 +18,10 @@ const ( DefaultTxPrefix = "tx_" ) +var ( + ErrTxNotFound = errors.New("tx isn't found in mempool") +) + type Mempool struct { cache cache.Cache } @@ -35,9 +40,9 @@ func (mp *Mempool) StoreTx(tx *types2.Transaction) error { return err } -func (mp *Mempool) GetTxsForNewBlock() []*types2.Transaction { +func (mp *Mempool) GetTransactionsForNewBlock() []*types2.Transaction { var txForBlock []*types2.Transaction - allTxs := mp.GetAllTxs() + allTxs := mp.GetAllTransactions() sort.Slice(allTxs, func(i, j int) bool { return allTxs[i].Timestamp.Before(allTxs[j].Timestamp) }) @@ -54,7 +59,7 @@ func (mp *Mempool) GetTxsForNewBlock() []*types2.Transaction { return txForBlock } -func (mp *Mempool) GetAllTxs() []*types2.Transaction { +func (mp *Mempool) GetAllTransactions() []*types2.Transaction { var allTxs []*types2.Transaction for _, v := range mp.cache.Items() { @@ -64,7 +69,18 @@ func (mp *Mempool) GetAllTxs() []*types2.Transaction { return allTxs } -func removeItemFromStringSlice(s []string, i int) []string { - s[len(s)-1], s[i] = s[i], s[len(s)-1] - return s[:len(s)-1] +func (mp *Mempool) GetTransaction(hash []byte) (*types2.Transaction, error) { + hashStr := hex.EncodeToString(hash) + var tx types2.Transaction + err := mp.cache.Get(DefaultTxPrefix+hashStr, &tx) + + if err != nil { + if errors.Is(err, cache.ErrNotFound) { + return nil, ErrTxNotFound + } else { + return nil, err + } + } + + return &tx, nil } diff --git a/blockchain/sync/sync_mgr.go b/blockchain/sync/sync_mgr.go index 2a6cbef..7063415 100644 --- a/blockchain/sync/sync_mgr.go +++ b/blockchain/sync/sync_mgr.go @@ -3,18 +3,19 @@ package sync import ( "bytes" "context" + "errors" "fmt" "strings" "sync" + "github.com/Secured-Finance/dione/consensus/policy" + "github.com/wealdtech/go-merkletree/keccak256" "github.com/wealdtech/go-merkletree" "github.com/sirupsen/logrus" - "github.com/Secured-Finance/dione/node" - "github.com/Secured-Finance/dione/node/wire" "github.com/libp2p/go-libp2p-core/peer" @@ -32,7 +33,8 @@ type SyncManager interface { } type syncManager struct { - blockPool *pool.BlockPool + blockpool *pool.BlockPool + mempool *pool.Mempool wg sync.WaitGroup ctx context.Context ctxCancelFunc context.CancelFunc @@ -44,7 +46,7 @@ type syncManager struct { func NewSyncManager(bp *pool.BlockPool, p2pRPCClient *gorpc.Client, bootstrapPeer peer.ID) SyncManager { ctx, cancelFunc := context.WithCancel(context.Background()) return &syncManager{ - blockPool: bp, + blockpool: bp, ctx: ctx, ctxCancelFunc: cancelFunc, initialSyncCompleted: false, @@ -56,7 +58,16 @@ func NewSyncManager(bp *pool.BlockPool, p2pRPCClient *gorpc.Client, bootstrapPee func (sm *syncManager) Start() { sm.wg.Add(1) - sm.doInitialSync() + err := sm.doInitialBlockPoolSync() + if err != nil { + logrus.Error(err) + } + + err = sm.doInitialMempoolSync() + if err != nil { + logrus.Error(err) + } + go sm.syncLoop() } @@ -65,15 +76,15 @@ func (sm *syncManager) Stop() { sm.wg.Wait() } -func (sm *syncManager) doInitialSync() error { +func (sm *syncManager) doInitialBlockPoolSync() error { if sm.initialSyncCompleted { return nil } - ourLastHeight, err := sm.blockPool.GetLatestBlockHeight() + ourLastHeight, err := sm.blockpool.GetLatestBlockHeight() if err == pool.ErrLatestHeightNil { gBlock := types2.GenesisBlock() - err = sm.blockPool.StoreBlock(gBlock) // commit genesis block + err = sm.blockpool.StoreBlock(gBlock) // commit genesis block if err != nil { return err } @@ -96,16 +107,16 @@ func (sm *syncManager) doInitialSync() error { for heightCount > 0 { from = to + 1 var addedVal uint64 - if heightCount < node.MaxBlockCountForRetrieving { + if heightCount < policy.MaxBlockCountForRetrieving { addedVal = heightCount } else { - addedVal = node.MaxBlockCountForRetrieving + addedVal = policy.MaxBlockCountForRetrieving } heightCount -= addedVal to += addedVal - var getBlocksReply wire.GetBlocksReply - arg := wire.GetBlocksArg{From: from, To: to} - err = sm.rpcClient.Call(sm.bootstrapPeer, "NetworkService", "GetBlocks", arg, &getBlocksReply) + var getBlocksReply wire.GetRangeOfBlocksReply + arg := wire.GetRangeOfBlocksArg{From: from, To: to} + err = sm.rpcClient.Call(sm.bootstrapPeer, "NetworkService", "GetRangeOfBlocks", arg, &getBlocksReply) if err != nil { return err } @@ -129,9 +140,59 @@ func (sm *syncManager) doInitialSync() error { return nil } +func (sm *syncManager) doInitialMempoolSync() error { + var reply wire.InvMessage + err := sm.rpcClient.Call(sm.bootstrapPeer, "NetworkService", "Mempool", nil, &reply) + if err != nil { + return err + } + + var txsToRetrieve [][]byte + + for _, v := range reply.Inventory { + _, err = sm.mempool.GetTransaction(v.Hash) + if errors.Is(err, pool.ErrTxNotFound) { + txsToRetrieve = append(txsToRetrieve, v.Hash) + } + } + + for { + var txHashes [][]byte + + if len(txsToRetrieve) == 0 { + break + } + + if len(txsToRetrieve) > policy.MaxTransactionCountForRetrieving { + txHashes = txsToRetrieve[:policy.MaxTransactionCountForRetrieving] + txsToRetrieve = txsToRetrieve[policy.MaxTransactionCountForRetrieving:] + } else { + txHashes = txsToRetrieve + } + + getMempoolTxArg := wire.GetMempoolTxsArg{ + Items: txHashes, + } + var getMempoolTxReply wire.GetMempoolTxsReply + err := sm.rpcClient.Call(sm.bootstrapPeer, "NetworkService", "GetMempoolTxs", getMempoolTxArg, &getMempoolTxReply) + if err != nil { + return err + } + for _, v := range getMempoolTxReply.Transactions { + err := sm.mempool.StoreTx(&v) + if err != nil { + logrus.Warnf(err.Error()) + } + } + // FIXME handle not found transactions + } + + return nil +} + func (sm *syncManager) processReceivedBlock(block types2.Block) error { // validate block - previousBlockHeader, err := sm.blockPool.FetchBlockHeaderByHeight(block.Header.Height - 1) + previousBlockHeader, err := sm.blockpool.FetchBlockHeaderByHeight(block.Header.Height - 1) if err != nil { return fmt.Errorf("failed to retrieve previous block %d", block.Header.Height-1) } @@ -163,7 +224,7 @@ func (sm *syncManager) processReceivedBlock(block types2.Block) error { } } - err = sm.blockPool.StoreBlock(&block) + err = sm.blockpool.StoreBlock(&block) if err != nil { return fmt.Errorf("failed to store block in blockpool: %s", err.Error()) } @@ -172,5 +233,4 @@ func (sm *syncManager) processReceivedBlock(block types2.Block) error { } func (sm *syncManager) syncLoop() { - } diff --git a/consensus/policy/policy.go b/consensus/policy/policy.go index 28e96f9..f5b5cf2 100644 --- a/consensus/policy/policy.go +++ b/consensus/policy/policy.go @@ -1,5 +1,7 @@ package policy const ( - BlockMaxTransactionCount = 100 + BlockMaxTransactionCount = 100 + MaxBlockCountForRetrieving = 500 // we do it just like in Bitcoin + MaxTransactionCountForRetrieving = 50000 ) diff --git a/go.mod b/go.mod index f84eebd..025a0d6 100644 --- a/go.mod +++ b/go.mod @@ -29,20 +29,21 @@ require ( github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/huin/goupnp v1.0.1-0.20200620063722-49508fba0031 // indirect github.com/ipfs/go-log v1.0.4 + github.com/ipfs/go-log/v2 v2.1.3 // indirect github.com/jmoiron/sqlx v1.2.0 github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9 // indirect github.com/klauspost/cpuid/v2 v2.0.6 // indirect github.com/ledgerwatch/lmdb-go v1.17.8 github.com/libp2p/go-libp2p v0.13.0 - github.com/libp2p/go-libp2p-core v0.8.0 - github.com/libp2p/go-libp2p-gorpc v0.1.2 + github.com/libp2p/go-libp2p-core v0.8.5 + github.com/libp2p/go-libp2p-gorpc v0.1.3 github.com/libp2p/go-libp2p-pubsub v0.4.2-0.20210212194758-6c1addf493eb github.com/mattn/go-sqlite3 v1.11.0 github.com/miguelmota/go-ethereum-hdwallet v0.0.0-20210314074952-8dd49aa599b9 github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 github.com/mitchellh/hashstructure/v2 v2.0.1 github.com/mitchellh/mapstructure v1.3.3 // indirect - github.com/multiformats/go-multiaddr v0.3.1 + github.com/multiformats/go-multiaddr v0.3.2 github.com/multiformats/go-multihash v0.0.15 // indirect github.com/olekukonko/tablewriter v0.0.4 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible @@ -56,15 +57,17 @@ require ( github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 // indirect github.com/stretchr/testify v1.7.0 github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go v1.2.6 // indirect github.com/valyala/fasthttp v1.17.0 github.com/wealdtech/go-merkletree v1.0.1-0.20190605192610-2bb163c2ea2a github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2 github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 - go.uber.org/zap v1.16.0 - golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b + go.uber.org/multierr v1.7.0 // indirect + go.uber.org/zap v1.17.0 + golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 // indirect - golang.org/x/sys v0.0.0-20210426230700-d19ff857e887 // indirect + golang.org/x/sys v0.0.0-20210601080250-7ecdf8ef093b // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 honnef.co/go/tools v0.0.1-2020.1.3 // indirect nhooyr.io/websocket v1.8.6 // indirect diff --git a/go.sum b/go.sum index 1530895..57efd7a 100644 --- a/go.sum +++ b/go.sum @@ -760,6 +760,8 @@ github.com/ipfs/go-log/v2 v2.0.8/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscw github.com/ipfs/go-log/v2 v2.1.1/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= github.com/ipfs/go-log/v2 v2.1.2-0.20200626104915-0016c0b4b3e4 h1:3bijxqzQ1O9yg7gd7Aqk80oaEvsJ+uXw0zSvi2qR3Jw= github.com/ipfs/go-log/v2 v2.1.2-0.20200626104915-0016c0b4b3e4/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= +github.com/ipfs/go-log/v2 v2.1.3 h1:1iS3IU7aXRlbgUpN8yTTpJ53NXYjAe37vcI5+5nYrzk= +github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g= github.com/ipfs/go-merkledag v0.0.3/go.mod h1:Oc5kIXLHokkE1hWGMBHw+oxehkAaTOqtEb7Zbh6BhLA= github.com/ipfs/go-merkledag v0.0.6/go.mod h1:QYPdnlvkOg7GnQRofu9XZimC5ZW5Wi3bKys/4GQQfto= github.com/ipfs/go-merkledag v0.2.3/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= @@ -1017,6 +1019,8 @@ github.com/libp2p/go-libp2p-core v0.6.1/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJB github.com/libp2p/go-libp2p-core v0.7.0/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= github.com/libp2p/go-libp2p-core v0.8.0 h1:5K3mT+64qDTKbV3yTdbMCzJ7O6wbNsavAEb8iqBvBcI= github.com/libp2p/go-libp2p-core v0.8.0/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= +github.com/libp2p/go-libp2p-core v0.8.5 h1:aEgbIcPGsKy6zYcC+5AJivYFedhYa4sW7mIpWpUaLKw= +github.com/libp2p/go-libp2p-core v0.8.5/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= github.com/libp2p/go-libp2p-crypto v0.0.1/go.mod h1:yJkNyDmO341d5wwXxDUGO0LykUVT72ImHNUqh5D/dBE= github.com/libp2p/go-libp2p-crypto v0.0.2/go.mod h1:eETI5OUfBnvARGOHrJz2eWNyTUxEGZnBxMcbUjfIj4I= github.com/libp2p/go-libp2p-crypto v0.1.0 h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ= @@ -1032,6 +1036,8 @@ github.com/libp2p/go-libp2p-discovery v0.5.0 h1:Qfl+e5+lfDgwdrXdu4YNCWyEo3fWuP+W github.com/libp2p/go-libp2p-discovery v0.5.0/go.mod h1:+srtPIU9gDaBNu//UHvcdliKBIcr4SfDcm0/PfPJLug= github.com/libp2p/go-libp2p-gorpc v0.1.2 h1:jHL0F79uDVPNsflS9byf8Wk23MQ0G+r5nUnLChoUn8A= github.com/libp2p/go-libp2p-gorpc v0.1.2/go.mod h1:ulZShaJCp3JHlBMHiA20efUmiqDECza+JvGFNXJyKdI= +github.com/libp2p/go-libp2p-gorpc v0.1.3 h1:b0bRXD4PEfqIvXbivDhNnaSQ8ERoaYd0vM7mDIDLQCQ= +github.com/libp2p/go-libp2p-gorpc v0.1.3/go.mod h1:ulZShaJCp3JHlBMHiA20efUmiqDECza+JvGFNXJyKdI= github.com/libp2p/go-libp2p-host v0.0.1/go.mod h1:qWd+H1yuU0m5CwzAkvbSjqKairayEHdR5MMl7Cwa7Go= github.com/libp2p/go-libp2p-host v0.0.3/go.mod h1:Y/qPyA6C8j2coYyos1dfRm0I8+nvd4TGrDGt4tA7JR8= github.com/libp2p/go-libp2p-interface-connmgr v0.0.1/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= @@ -1350,6 +1356,8 @@ github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4fJxp6ggJGteB8HQTI= github.com/multiformats/go-multiaddr v0.3.1 h1:1bxa+W7j9wZKTZREySx1vPMs2TqrYWjVZ7zE6/XLG1I= github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc= +github.com/multiformats/go-multiaddr v0.3.2 h1:vapLUGlFpvvkaemMvKGGxjruOzaIzQbn41J6R9vxeyU= +github.com/multiformats/go-multiaddr v0.3.2/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.3/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= @@ -1703,10 +1711,14 @@ github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6 github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go v1.1.13 h1:nB3O5kBSQGjEQAcfe1aLUYuxmXdFKmYgBZhY32rQb6Q= github.com/ugorji/go v1.1.13/go.mod h1:jxau1n+/wyTGLQoCkjok9r5zFa/FxT6eI5HiHKQszjc= +github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E= +github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.1.13 h1:013LbFhocBoIqgHeIHKlV4JWYhqogATYWZhIcH0WHn4= github.com/ugorji/go/codec v1.1.13/go.mod h1:oNVt3Dq+FO91WNQ/9JnHKQP2QJxTzoN7wCBFCq1OeuU= +github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= +github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= @@ -1847,6 +1859,8 @@ go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+ go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= +go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= @@ -1854,6 +1868,8 @@ go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= go4.org v0.0.0-20200411211856-f5505b9728dd h1:BNJlw5kRTzdmyfh5U8F93HA2OwkP7ZGwA51eJ/0wKOU= go4.org v0.0.0-20200411211856-f5505b9728dd/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZMZXMSBGhxRdsvzbkg= @@ -1901,6 +1917,8 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -2099,6 +2117,8 @@ golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887 h1:dXfMednGJh/SUUFjTLsWJz3P+TQt9qnR11GgeI3vWKs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210601080250-7ecdf8ef093b h1:qh4f65QIVFjq9eBURLEYWqaEXmOyqdUyiBSgaXWccWk= +golang.org/x/sys v0.0.0-20210601080250-7ecdf8ef093b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/node/network_service.go b/node/network_service.go index 5e65b22..deb93d8 100644 --- a/node/network_service.go +++ b/node/network_service.go @@ -2,20 +2,23 @@ package node import ( "context" + "errors" + "fmt" + + gorpc "github.com/libp2p/go-libp2p-gorpc" "github.com/sirupsen/logrus" + "github.com/Secured-Finance/dione/consensus/policy" "github.com/Secured-Finance/dione/node/wire" "github.com/Secured-Finance/dione/blockchain/pool" ) -const ( - MaxBlockCountForRetrieving = 500 // we do it just like in Bitcoin -) - type NetworkService struct { blockpool *pool.BlockPool + mempool *pool.Mempool + rpcClient *gorpc.Client } func NewNetworkService(bp *pool.BlockPool) *NetworkService { @@ -24,7 +27,7 @@ func NewNetworkService(bp *pool.BlockPool) *NetworkService { } } -func (s *NetworkService) LastBlockHeight(ctx context.Context, arg interface{}, reply *wire.LastBlockHeightReply) { +func (s *NetworkService) LastBlockHeight(ctx context.Context, arg struct{}, reply *wire.LastBlockHeightReply) { height, err := s.blockpool.GetLatestBlockHeight() if err != nil { reply.Error = err @@ -33,13 +36,13 @@ func (s *NetworkService) LastBlockHeight(ctx context.Context, arg interface{}, r reply.Height = height } -func (s *NetworkService) GetBlocks(ctx context.Context, arg wire.GetBlocksArg, reply *wire.GetBlocksReply) { +func (s *NetworkService) GetRangeOfBlocks(ctx context.Context, arg wire.GetRangeOfBlocksArg, reply *wire.GetRangeOfBlocksReply) { if arg.From > arg.To { errText := "incorrect arguments: from > to" reply.Error = &errText return } - if arg.To-arg.From > MaxBlockCountForRetrieving { + if arg.To-arg.From > policy.MaxBlockCountForRetrieving { errText := "incorrect arguments: count of block for retrieving is exceeded the limit" reply.Error = &errText return @@ -54,3 +57,37 @@ func (s *NetworkService) GetBlocks(ctx context.Context, arg wire.GetBlocksArg, r reply.Blocks = append(reply.Blocks, *block) } } + +func (s *NetworkService) Mempool(ctx context.Context, arg struct{}, reply *wire.InvMessage) { + txs := s.mempool.GetAllTransactions() + + // extract hashes of txs + for _, v := range txs { + reply.Inventory = append(reply.Inventory, wire.InvItem{ + Type: wire.TxInvType, + Hash: v.Hash, + }) + } +} + +func (s *NetworkService) GetMempoolTxs(ctx context.Context, arg wire.GetMempoolTxsArg, reply *wire.GetMempoolTxsReply) { + if len(arg.Items) > MaxTransactionCountForRetrieving { + pid, _ := gorpc.GetRequestSender(ctx) + logrus.Warnf("Max tx count limit exceeded for GetMempoolTxs request of node %s", pid) + reply.Error = fmt.Errorf("max tx count limit exceeded") + return + } + + for _, v := range arg.Items { + tx, err := s.mempool.GetTransaction(v) + if err != nil { + if errors.Is(err, pool.ErrTxNotFound) { + reply.NotFoundTxs = append(reply.NotFoundTxs, v) + } else { + reply.Error = err + return + } + } + reply.Transactions = append(reply.Transactions, *tx) + } +} diff --git a/node/wire/get_mempool_tx.go b/node/wire/get_mempool_tx.go new file mode 100644 index 0000000..da364e5 --- /dev/null +++ b/node/wire/get_mempool_tx.go @@ -0,0 +1,13 @@ +package wire + +import "github.com/Secured-Finance/dione/blockchain/types" + +type GetMempoolTxsArg struct { + Items [][]byte +} + +type GetMempoolTxsReply struct { + Transactions []types.Transaction + NotFoundTxs [][]byte + Error error +} diff --git a/node/wire/get_blocks.go b/node/wire/get_range_of_blocks.go similarity index 78% rename from node/wire/get_blocks.go rename to node/wire/get_range_of_blocks.go index dda8cfe..5ecc770 100644 --- a/node/wire/get_blocks.go +++ b/node/wire/get_range_of_blocks.go @@ -2,12 +2,12 @@ package wire import "github.com/Secured-Finance/dione/blockchain/types" -type GetBlocksArg struct { +type GetRangeOfBlocksArg struct { From uint64 To uint64 } -type GetBlocksReply struct { +type GetRangeOfBlocksReply struct { Blocks []types.Block FailedBlockHeights []uint64 // list of block heights the node was unable to retrieve Error *string diff --git a/node/wire/inv.go b/node/wire/inv.go new file mode 100644 index 0000000..b903ec5 --- /dev/null +++ b/node/wire/inv.go @@ -0,0 +1,17 @@ +package wire + +type InvType int + +const ( + InvalidInvType = iota + TxInvType +) + +type InvMessage struct { + Inventory []InvItem +} + +type InvItem struct { + Type InvType + Hash []byte +}