diff --git a/common/constant/blockchainSync.go b/common/constant/blockchainSync.go index 34e400af2..e7cf03383 100644 --- a/common/constant/blockchainSync.go +++ b/common/constant/blockchainSync.go @@ -11,6 +11,7 @@ const ( PeerGetBlocksLimit uint32 = 1440 CommonMilestoneBlockIdsLimit int32 = 10 SafeBlockGap uint32 = 1440 - MinRollbackBlocks uint32 = 720 - MaxCommonMilestoneRequestTrial uint32 = MinRollbackBlocks/uint32(CommonMilestoneBlockIdsLimit) + 1 + // @iltoga change this to 2 for testing snapshots + MinRollbackBlocks uint32 = 720 // production 720 + MaxCommonMilestoneRequestTrial uint32 = MinRollbackBlocks/uint32(CommonMilestoneBlockIdsLimit) + 1 ) diff --git a/common/constant/genesis.go b/common/constant/genesis.go index 853a86245..2004baa16 100644 --- a/common/constant/genesis.go +++ b/common/constant/genesis.go @@ -3,7 +3,7 @@ package constant const ( - MainchainGenesisBlockID int64 = 3638197708165910115 + MainchainGenesisBlockID int64 = 1070983609761144356 ) type ( diff --git a/common/constant/snapshot.go b/common/constant/snapshot.go index 48ac2bf00..8154c5d98 100644 --- a/common/constant/snapshot.go +++ b/common/constant/snapshot.go @@ -12,5 +12,5 @@ const ( // @iltoga reduce to 1 for testing locally SnapshotChunkSize int = int(100 * 1024) // 10 KB // DownloadSnapshotNumberOfRetries number of times to retry downloading failed snapshot file chunks from other peers - DownloadSnapshotNumberOfRetries uint32 = 3 + DownloadSnapshotNumberOfRetries uint32 = 5 ) diff --git a/common/monitoring/metricsMonitoring.go b/common/monitoring/metricsMonitoring.go index ebf1578c6..46f84957e 100644 --- a/common/monitoring/metricsMonitoring.go +++ b/common/monitoring/metricsMonitoring.go @@ -48,7 +48,7 @@ const ( P2pGetCommonMilestoneBlockIDsServer = "P2pGetCommonMilestoneBlockIDsServer" P2pGetNextBlockIDsServer = "P2pGetNextBlockIDsServer" P2pGetNextBlocksServer = "P2pGetNextBlocksServer" - P2pRequestFileDownloadServer = "P2pRequestFileDownloadServer" + P2pRequestFileDownloadServer = "P2pRequestFileDownloadServer" P2pGetPeerInfoClient = "P2pGetPeerInfoClient" P2pGetMorePeersClient = "P2pGetMorePeersClient" @@ -60,7 +60,7 @@ const ( P2pGetCommonMilestoneBlockIDsClient = "P2pGetCommonMilestoneBlockIDsClient" P2pGetNextBlockIDsClient = "P2pGetNextBlockIDsClient" P2pGetNextBlocksClient = "P2pGetNextBlocksClient" - P2pRequestFileDownloadClient = "P2pRequestFileDownloadClient" + P2pRequestFileDownloadClient = "P2pRequestFileDownloadClient" ) func SetMonitoringActive(isActive bool) { diff --git a/common/query/blockQuery.go b/common/query/blockQuery.go index 44e9dec28..4280d132f 100644 --- a/common/query/blockQuery.go +++ b/common/query/blockQuery.go @@ -15,9 +15,10 @@ type ( GetBlocks(height, size uint32) string GetLastBlock() string GetGenesisBlock() string - GetBlockByID(int64) string - GetBlockByHeight(uint32) string - GetBlockFromHeight(uint32, uint32) string + GetBlockByID(id int64) string + GetBlockByHeight(height uint32) string + GetBlockFromHeight(startHeight, limit uint32) string + GetBlockFromTimestamp(startTimestamp int64, limit uint32) string InsertBlock(block *model.Block) (str string, args []interface{}) ExtractModel(block *model.Block) []interface{} BuildModel(blocks []*model.Block, rows *sql.Rows) ([]*model.Block, error) @@ -93,10 +94,16 @@ func (bq *BlockQuery) GetBlockByHeight(height uint32) string { // GetBlockFromHeight returns query string to get blocks from a certain height func (bq *BlockQuery) GetBlockFromHeight(startHeight, limit uint32) string { - return fmt.Sprintf("SELECT %s FROM %s WHERE HEIGHT >= %d ORDER BY HEIGHT LIMIT %d", + return fmt.Sprintf("SELECT %s FROM %s WHERE height >= %d ORDER BY height LIMIT %d", strings.Join(bq.Fields, ", "), bq.getTableName(), startHeight, limit) } +// GetBlockFromTimestamp returns query string to get blocks from a certain block timestamp +func (bq *BlockQuery) GetBlockFromTimestamp(startTimestamp int64, limit uint32) string { + return fmt.Sprintf("SELECT %s FROM %s WHERE timestamp >= %d ORDER BY timestamp LIMIT %d", + strings.Join(bq.Fields, ", "), bq.getTableName(), startTimestamp, limit) +} + // ExtractModel extract the model struct fields to the order of BlockQuery.Fields func (*BlockQuery) ExtractModel(block *model.Block) []interface{} { return []interface{}{ diff --git a/common/query/blockQuery_test.go b/common/query/blockQuery_test.go index 23645d2da..246d8af40 100644 --- a/common/query/blockQuery_test.go +++ b/common/query/blockQuery_test.go @@ -5,10 +5,8 @@ import ( "testing" "github.com/DATA-DOG/go-sqlmock" - - "github.com/zoobc/zoobc-core/common/model" - "github.com/zoobc/zoobc-core/common/chaintype" + "github.com/zoobc/zoobc-core/common/model" ) var ( @@ -249,3 +247,87 @@ func TestBlockQuery_Rollback(t *testing.T) { }) } } + +func TestBlockQuery_GetBlockFromHeight(t *testing.T) { + type fields struct { + Fields []string + TableName string + ChainType chaintype.ChainType + } + type args struct { + startHeight uint32 + limit uint32 + } + tests := []struct { + name string + fields fields + args args + want string + }{ + { + name: "GetBlockFromHeight:success", + fields: fields(*mockBlockQuery), + args: args{ + limit: 1, + startHeight: 1, + }, + want: "SELECT id, block_hash, previous_block_hash, height, timestamp, block_seed, block_signature, " + + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, " + + "total_coinbase, version FROM main_block WHERE height >= 1 ORDER BY height LIMIT 1", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + bq := &BlockQuery{ + Fields: tt.fields.Fields, + TableName: tt.fields.TableName, + ChainType: tt.fields.ChainType, + } + if got := bq.GetBlockFromHeight(tt.args.startHeight, tt.args.limit); got != tt.want { + t.Errorf("BlockQuery.GetBlockFromHeight() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestBlockQuery_GetBlockFromTimestamp(t *testing.T) { + type fields struct { + Fields []string + TableName string + ChainType chaintype.ChainType + } + type args struct { + startTimestamp int64 + limit uint32 + } + tests := []struct { + name string + fields fields + args args + want string + }{ + { + name: "GetBlockFromTimestamp:success", + fields: fields(*mockBlockQuery), + args: args{ + limit: 1, + startTimestamp: 15875392, + }, + want: "SELECT id, block_hash, previous_block_hash, height, timestamp, block_seed, block_signature, " + + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, " + + "total_coinbase, version FROM main_block WHERE timestamp >= 15875392 ORDER BY timestamp LIMIT 1", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + bq := &BlockQuery{ + Fields: tt.fields.Fields, + TableName: tt.fields.TableName, + ChainType: tt.fields.ChainType, + } + if got := bq.GetBlockFromTimestamp(tt.args.startTimestamp, tt.args.limit); got != tt.want { + t.Errorf("BlockQuery.GetBlockFromTimestamp() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/common/schema b/common/schema index bb1388bf8..6558d9252 160000 --- a/common/schema +++ b/common/schema @@ -1 +1 @@ -Subproject commit bb1388bf800324a3132839cac42dce0c82c7239d +Subproject commit 6558d9252a95e48bb3188139ce091f1bc1ce5e22 diff --git a/core/service/blockCoreService.go b/core/service/blockCoreService.go index afeb9bcbe..71b719e2a 100644 --- a/core/service/blockCoreService.go +++ b/core/service/blockCoreService.go @@ -22,6 +22,8 @@ type ( timestamp int64, ) (*model.Block, error) ValidateBlock(block, previousLastBlock *model.Block, curTime int64) error + ValidatePayloadHash(block *model.Block) error + GetPayloadHashAndLength(block *model.Block) (payloadHash []byte, payloadLength uint32, err error) PushBlock(previousBlock, block *model.Block, broadcast, persist bool) error GetBlockByID(id int64, withAttachedData bool) (*model.Block, error) GetBlockByHeight(uint32) (*model.Block, error) diff --git a/core/service/blockMainService.go b/core/service/blockMainService.go index 0a47849ed..4a7af32d6 100644 --- a/core/service/blockMainService.go +++ b/core/service/blockMainService.go @@ -33,6 +33,7 @@ import ( ) type ( + // BlockServiceMainInterface interface that contains methods specific of BlockService BlockServiceMainInterface interface { NewMainBlock( version uint32, @@ -163,10 +164,12 @@ func (bs *BlockService) NewMainBlock( totalCoinBase int64, transactions []*model.Transaction, publishedReceipts []*model.PublishedReceipt, - payloadHash []byte, - payloadLength uint32, secretPhrase string, ) (*model.Block, error) { + var ( + err error + ) + block := &model.Block{ Version: version, PreviousBlockHash: previousBlockHash, @@ -179,9 +182,13 @@ func (bs *BlockService) NewMainBlock( TotalCoinBase: totalCoinBase, Transactions: transactions, PublishedReceipts: publishedReceipts, - PayloadHash: payloadHash, - PayloadLength: payloadLength, } + + // compute block's payload hash and length and add it to block struct + if block.PayloadHash, block.PayloadLength, err = bs.GetPayloadHashAndLength(block); err != nil { + return nil, err + } + blockUnsignedByte, err := util.GetBlockByte(block, false, bs.Chaintype) if err != nil { bs.Logger.Error(err.Error()) @@ -258,7 +265,19 @@ func (bs *BlockService) NewGenesisBlock( return block, nil } -// PreValidateBlock valdiate block without it's transactions +// ValidatePayloadHash validate (computed) block's payload data hash against block's payload hash +func (bs *BlockService) ValidatePayloadHash(block *model.Block) error { + hash, length, err := bs.GetPayloadHashAndLength(block) + if err != nil { + return err + } + if length != block.GetPayloadLength() || !bytes.Equal(hash, block.GetPayloadHash()) { + return blocker.NewBlocker(blocker.ValidationErr, "InvalidBlockPayload") + } + return nil +} + +// PreValidateBlock validate block without it's transactions func (bs *BlockService) PreValidateBlock(block, previousLastBlock *model.Block) error { // check if blocksmith can smith at the time blocksmithsMap := bs.BlocksmithStrategy.GetSortedBlocksmithsMap(previousLastBlock) @@ -276,6 +295,10 @@ func (bs *BlockService) PreValidateBlock(block, previousLastBlock *model.Block) // ValidateBlock validate block to be pushed into the blockchain func (bs *BlockService) ValidateBlock(block, previousLastBlock *model.Block, curTime int64) error { + if err := bs.ValidatePayloadHash(block); err != nil { + return err + } + // check block timestamp if block.GetTimestamp() > curTime+constant.GenerateBlockTimeoutSec { return blocker.NewBlocker(blocker.BlockErr, "InvalidTimestamp") @@ -896,6 +919,33 @@ func (bs *BlockService) RemoveMempoolTransactions(transactions []*model.Transact return nil } +func (bs *BlockService) GetPayloadHashAndLength(block *model.Block) (payloadHash []byte, payloadLength uint32, err error) { + var ( + digest = sha3.New256() + ) + for _, tx := range block.GetTransactions() { + if _, err := digest.Write(tx.GetTransactionHash()); err != nil { + return nil, 0, err + } + txType, err := bs.ActionTypeSwitcher.GetTransactionType(tx) + if err != nil { + return nil, 0, err + } + payloadLength += txType.GetSize() + } + // filter only good receipt + for _, br := range block.GetPublishedReceipts() { + brBytes := bs.ReceiptUtil.GetSignedBatchReceiptBytes(br.BatchReceipt) + _, err = digest.Write(brBytes) + if err != nil { + return nil, 0, err + } + payloadLength += uint32(len(brBytes)) + } + payloadHash = digest.Sum([]byte{}) + return +} + // GenerateBlock generate block from transactions in mempool func (bs *BlockService) GenerateBlock( previousBlock *model.Block, @@ -904,11 +954,9 @@ func (bs *BlockService) GenerateBlock( ) (*model.Block, error) { var ( totalAmount, totalFee, totalCoinbase int64 - payloadLength uint32 // only for mainchain sortedTransactions []*model.Transaction publishedReceipts []*model.PublishedReceipt - payloadHash []byte err error digest = sha3.New256() blockSmithPublicKey = crypto.NewEd25519Signature().GetPublicKeyFromSeed(secretPhrase) @@ -922,16 +970,12 @@ func (bs *BlockService) GenerateBlock( } // select transactions from mempool to be added to the block for _, tx := range sortedTransactions { - if _, err = digest.Write(tx.TransactionHash); err != nil { - return nil, err - } txType, errType := bs.ActionTypeSwitcher.GetTransactionType(tx) if errType != nil { return nil, err } totalAmount += txType.GetAmount() totalFee += tx.Fee - payloadLength += txType.GetSize() } // select published receipts to be added to the block publishedReceipts, err = bs.ReceiptService.SelectReceipts( @@ -939,27 +983,16 @@ func (bs *BlockService) GenerateBlock( len(bs.BlocksmithStrategy.GetSortedBlocksmiths(previousBlock))), previousBlock.Height, ) - // FIXME: add published receipts to block payload length - if err != nil { return nil, err } - // filter only good receipt - for _, br := range publishedReceipts { - _, err = digest.Write(bs.ReceiptUtil.GetSignedBatchReceiptBytes(br.BatchReceipt)) - if err != nil { - return nil, err - } - } - payloadHash = digest.Sum([]byte{}) // loop through transaction to build block hash - digest.Reset() // reset the digest if _, err = digest.Write(previousBlock.GetBlockSeed()); err != nil { return nil, err } - previousSeedHash := digest.Sum([]byte{}) + blockSeed := bs.Signature.SignByNode(previousSeedHash, secretPhrase) digest.Reset() // reset the digest // compute the previous block hash @@ -979,8 +1012,6 @@ func (bs *BlockService) GenerateBlock( totalCoinbase, sortedTransactions, publishedReceipts, - payloadHash, - payloadLength, secretPhrase, ) if err != nil { diff --git a/core/service/blockMainService_test.go b/core/service/blockMainService_test.go index b23a724e3..234c6b9bc 100644 --- a/core/service/blockMainService_test.go +++ b/core/service/blockMainService_test.go @@ -632,9 +632,10 @@ func TestBlockService_NewBlock(t *testing.T) { TotalCoinBase: 0, Transactions: []*model.Transaction{}, PublishedReceipts: []*model.PublishedReceipt{}, - PayloadHash: []byte{}, - PayloadLength: 0, - BlockSignature: []byte{}, + PayloadHash: []byte{167, 255, 198, 248, 191, 30, 215, 102, 81, 193, 71, 86, 160, 97, 214, 98, 245, 128, + 255, 77, 228, 59, 73, 250, 130, 216, 10, 75, 128, 248, 67, 74}, + PayloadLength: 0, + BlockSignature: []byte{}, } mockBlockHash, _ = util.GetBlockHash(mockBlock, &chaintype.MainChain{}) ) @@ -661,8 +662,6 @@ func TestBlockService_NewBlock(t *testing.T) { totalCoinBase int64 transactions []*model.Transaction publishedReceipts []*model.PublishedReceipt - payloadHash []byte - payloadLength uint32 secretPhrase string } tests := []struct { @@ -690,8 +689,6 @@ func TestBlockService_NewBlock(t *testing.T) { totalCoinBase: 0, transactions: []*model.Transaction{}, publishedReceipts: []*model.PublishedReceipt{}, - payloadHash: []byte{}, - payloadLength: 0, secretPhrase: "secretphrase", }, want: mockBlock, @@ -720,8 +717,6 @@ func TestBlockService_NewBlock(t *testing.T) { tt.args.totalCoinBase, tt.args.transactions, tt.args.publishedReceipts, - tt.args.payloadHash, - tt.args.payloadLength, tt.args.secretPhrase, ) if (err != nil) != tt.wantErr { @@ -3592,8 +3587,9 @@ var ( 45, 118, 97, 219, 80, 242, 244, 100, 134, 144, 246, 37, 144, 213, 135}, BlockSignature: []byte{144, 246, 37, 144, 213, 135}, CumulativeDifficulty: "1000", - PayloadLength: 1, - PayloadHash: []byte{}, + PayloadLength: 0, + PayloadHash: []byte{167, 255, 198, 248, 191, 30, 215, 102, 81, 193, 71, 86, 160, + 97, 214, 98, 245, 128, 255, 77, 228, 59, 73, 250, 130, 216, 10, 75, 128, 248, 67, 74}, BlocksmithPublicKey: []byte{1, 2, 3, 200, 7, 61, 108, 229, 204, 48, 199, 145, 21, 99, 125, 75, 49, 45, 118, 97, 219, 80, 242, 244, 100, 134, 144, 246, 37, 144, 213, 135}, TotalAmount: 1000, @@ -5024,3 +5020,148 @@ func TestBlockService_canPersistBlock(t *testing.T) { }) } } + +type ( + mockReceiptUtil struct { + coreUtil.ReceiptUtil + resSignetBytes []byte + } +) + +func (mRu *mockReceiptUtil) GetSignedBatchReceiptBytes(receipt *model.BatchReceipt) []byte { + if mRu.resSignetBytes != nil { + return mRu.resSignetBytes + } + return []byte{} +} + +func TestBlockService_ValidatePayloadHash(t *testing.T) { + mockBlock := &model.Block{ + PayloadHash: []byte{102, 253, 86, 32, 28, 24, 212, 55, 129, 77, 244, 149, 6, 198, 243, 4, 86, 251, 61, 45, 48, 99, 191, + 108, 13, 232, 254, 123, 170, 190, 3, 141}, + PayloadLength: uint32(13), + Transactions: []*model.Transaction{ + mockTransaction, + }, + PublishedReceipts: mockPublishedReceipt, + } + mockInvalidBlock := &model.Block{ + PayloadHash: []byte{102, 253, 86, 32, 28, 24, 212, 55, 129, 77, 244, 149, 6, 198, 243, 4, 86, 251, 61, 45, 48, 99, 191, + 108, 13, 232, 254, 123, 170, 190, 3, 0}, + PayloadLength: uint32(13), + Transactions: []*model.Transaction{ + mockTransaction, + }, + PublishedReceipts: mockPublishedReceipt, + } + type fields struct { + RWMutex sync.RWMutex + Chaintype chaintype.ChainType + KVExecutor kvdb.KVExecutorInterface + QueryExecutor query.ExecutorInterface + BlockQuery query.BlockQueryInterface + MempoolQuery query.MempoolQueryInterface + TransactionQuery query.TransactionQueryInterface + PublishedReceiptQuery query.PublishedReceiptQueryInterface + SkippedBlocksmithQuery query.SkippedBlocksmithQueryInterface + Signature crypto.SignatureInterface + MempoolService MempoolServiceInterface + ReceiptService ReceiptServiceInterface + NodeRegistrationService NodeRegistrationServiceInterface + BlocksmithService BlocksmithServiceInterface + ActionTypeSwitcher transaction.TypeActionSwitcher + AccountBalanceQuery query.AccountBalanceQueryInterface + ParticipationScoreQuery query.ParticipationScoreQueryInterface + NodeRegistrationQuery query.NodeRegistrationQueryInterface + AccountLedgerQuery query.AccountLedgerQueryInterface + BlocksmithStrategy strategy.BlocksmithStrategyInterface + BlockIncompleteQueueService BlockIncompleteQueueServiceInterface + BlockPoolService BlockPoolServiceInterface + Observer *observer.Observer + Logger *log.Logger + TransactionUtil transaction.UtilInterface + ReceiptUtil coreUtil.ReceiptUtilInterface + PublishedReceiptUtil coreUtil.PublishedReceiptUtilInterface + TransactionCoreService TransactionCoreServiceInterface + CoinbaseService CoinbaseServiceInterface + ParticipationScoreService ParticipationScoreServiceInterface + PublishedReceiptService PublishedReceiptServiceInterface + } + type args struct { + block *model.Block + } + tests := []struct { + name string + fields fields + args args + wantErr bool + }{ + { + name: "ValidatePayloadHash:success", + fields: fields{ + BlockQuery: query.NewBlockQuery(&chaintype.MainChain{}), + ActionTypeSwitcher: &mockTypeActionSuccess{}, + ReceiptUtil: &mockReceiptUtil{ + resSignetBytes: []byte{1, 1, 1, 1, 1}, + }, + }, + args: args{ + block: mockBlock, + }, + }, + { + name: "ValidatePayloadHash:fail", + fields: fields{ + BlockQuery: query.NewBlockQuery(&chaintype.MainChain{}), + ActionTypeSwitcher: &mockTypeActionSuccess{}, + ReceiptUtil: &mockReceiptUtil{ + resSignetBytes: []byte{1, 1, 1, 1, 1}, + }, + }, + args: args{ + block: mockInvalidBlock, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + bs := &BlockService{ + RWMutex: tt.fields.RWMutex, + Chaintype: tt.fields.Chaintype, + KVExecutor: tt.fields.KVExecutor, + QueryExecutor: tt.fields.QueryExecutor, + BlockQuery: tt.fields.BlockQuery, + MempoolQuery: tt.fields.MempoolQuery, + TransactionQuery: tt.fields.TransactionQuery, + PublishedReceiptQuery: tt.fields.PublishedReceiptQuery, + SkippedBlocksmithQuery: tt.fields.SkippedBlocksmithQuery, + Signature: tt.fields.Signature, + MempoolService: tt.fields.MempoolService, + ReceiptService: tt.fields.ReceiptService, + NodeRegistrationService: tt.fields.NodeRegistrationService, + BlocksmithService: tt.fields.BlocksmithService, + ActionTypeSwitcher: tt.fields.ActionTypeSwitcher, + AccountBalanceQuery: tt.fields.AccountBalanceQuery, + ParticipationScoreQuery: tt.fields.ParticipationScoreQuery, + NodeRegistrationQuery: tt.fields.NodeRegistrationQuery, + AccountLedgerQuery: tt.fields.AccountLedgerQuery, + BlocksmithStrategy: tt.fields.BlocksmithStrategy, + BlockIncompleteQueueService: tt.fields.BlockIncompleteQueueService, + BlockPoolService: tt.fields.BlockPoolService, + Observer: tt.fields.Observer, + Logger: tt.fields.Logger, + TransactionUtil: tt.fields.TransactionUtil, + ReceiptUtil: tt.fields.ReceiptUtil, + PublishedReceiptUtil: tt.fields.PublishedReceiptUtil, + TransactionCoreService: tt.fields.TransactionCoreService, + CoinbaseService: tt.fields.CoinbaseService, + ParticipationScoreService: tt.fields.ParticipationScoreService, + PublishedReceiptService: tt.fields.PublishedReceiptService, + } + if err := bs.ValidatePayloadHash(tt.args.block); (err != nil) != tt.wantErr { + t.Errorf("BlockService.ValidatePayloadHash() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/core/service/blockSpineService.go b/core/service/blockSpineService.go index c16134d9f..a7aa926d6 100644 --- a/core/service/blockSpineService.go +++ b/core/service/blockSpineService.go @@ -27,6 +27,11 @@ import ( ) type ( + // BlockServiceSpineInterface interface that contains methods specific of BlockSpineService + BlockServiceSpineInterface interface { + ValidateSpineBlockManifest(spineBlockManifest *model.SpineBlockManifest) error + } + BlockSpineService struct { sync.RWMutex Chaintype chaintype.ChainType @@ -84,12 +89,14 @@ func (bs *BlockSpineService) NewSpineBlock( blockSeed, blockSmithPublicKey []byte, previousBlockHeight uint32, timestamp int64, - payloadHash []byte, - payloadLength uint32, secretPhrase string, spinePublicKeys []*model.SpinePublicKey, spineBlockManifests []*model.SpineBlockManifest, ) (*model.Block, error) { + var ( + payloadLength uint32 + err error + ) block := &model.Block{ Version: version, PreviousBlockHash: previousBlockHash, @@ -97,11 +104,16 @@ func (bs *BlockSpineService) NewSpineBlock( BlocksmithPublicKey: blockSmithPublicKey, Height: previousBlockHeight, Timestamp: timestamp, - PayloadHash: payloadHash, PayloadLength: payloadLength, SpinePublicKeys: spinePublicKeys, SpineBlockManifests: spineBlockManifests, } + + // compute block's payload hash and length and add it to block struct + if block.PayloadHash, block.PayloadLength, err = bs.GetPayloadHashAndLength(block); err != nil { + return nil, err + } + blockUnsignedByte, err := util.GetBlockByte(block, false, bs.Chaintype) if err != nil { bs.Logger.Error(err.Error()) @@ -178,10 +190,24 @@ func (bs *BlockSpineService) NewGenesisBlock( return block, nil } +// ValidatePayloadHash validate (computed) block's payload data hash against block's payload hash +func (bs *BlockSpineService) ValidatePayloadHash(block *model.Block) error { + hash, length, err := bs.GetPayloadHashAndLength(block) + if err != nil { + return err + } + if length != block.GetPayloadLength() || !bytes.Equal(hash, block.GetPayloadHash()) { + return blocker.NewBlocker(blocker.ValidationErr, "InvalidBlockPayload") + } + return nil +} + // ValidateBlock validate block to be pushed into the blockchain func (bs *BlockSpineService) ValidateBlock(block, previousLastBlock *model.Block, curTime int64) error { - // TODO: validate spine block manifest if part of block data - // - re-calculate block payload hash using data from 'block' func argument and compare it with block.PayloadHash + // validate block's payload data + if err := bs.ValidatePayloadHash(block); err != nil { + return err + } // todo: validate previous time if block.GetTimestamp() > curTime+constant.GenerateBlockTimeoutSec { @@ -475,6 +501,31 @@ func (bs *BlockSpineService) PopulateBlockData(block *model.Block) error { return nil } +// GetPayloadBytes compute and return the block's payload hash +func (bs *BlockSpineService) GetPayloadHashAndLength(block *model.Block) (payloadHash []byte, payloadLength uint32, err error) { + var ( + digest = sha3.New256() + ) + for _, spinePubKey := range block.GetSpinePublicKeys() { + spinePubKeyBytes := commonUtils.GetSpinePublicKeyBytes(spinePubKey) + if _, err := digest.Write(spinePubKeyBytes); err != nil { + return nil, 0, err + } + payloadLength += uint32(len(spinePubKeyBytes)) + + } + // compute the block payload length and hash by parsing all file chunks db entities into their bytes representation + for _, spineBlockManifest := range block.GetSpineBlockManifests() { + spineBlockManifestBytes := bs.SpineBlockManifestService.GetSpineBlockManifestBytes(spineBlockManifest) + if _, err := digest.Write(spineBlockManifestBytes); err != nil { + return nil, 0, err + } + payloadLength += uint32(len(spineBlockManifestBytes)) + } + payloadHash = digest.Sum([]byte{}) + return +} + // GenerateBlock generate block from transactions in mempool func (bs *BlockSpineService) GenerateBlock( previousBlock *model.Block, @@ -482,26 +533,21 @@ func (bs *BlockSpineService) GenerateBlock( timestamp int64, ) (*model.Block, error) { var ( - payloadLength uint32 - spinePublicKeys []*model.SpinePublicKey - payloadBytes, payloadHash []byte - err error - digest = sha3.New256() - blockSmithPublicKey = crypto.NewEd25519Signature().GetPublicKeyFromSeed(secretPhrase) - fromTimestamp = previousBlock.Timestamp - spineBlockManifests []*model.SpineBlockManifest + spinePublicKeys []*model.SpinePublicKey + err error + digest = sha3.New256() + blockSmithPublicKey = crypto.NewEd25519Signature().GetPublicKeyFromSeed(secretPhrase) + fromTimestamp = previousBlock.Timestamp + spineBlockManifests []*model.SpineBlockManifest ) newBlockHeight := previousBlock.Height + 1 // compute spine pub keys from mainchain node registrations // Note: since spine blocks are not in sync with main blocks and they are unaware of the height (on mainchain) where to retrieve - // node registration's public keys, we use timestamps for now + // node registration's public keys, we use timestamps instead of block heights if fromTimestamp == bs.GetChainType().GetGenesisBlockTimestamp() { fromTimestamp++ } spinePublicKeys, err = bs.SpinePublicKeyService.BuildSpinePublicKeysFromNodeRegistry(fromTimestamp, timestamp, newBlockHeight) - for _, spinePubKey := range spinePublicKeys { - payloadBytes = append(payloadBytes, commonUtils.GetSpinePublicKeyBytes(spinePubKey)...) - } if err != nil { return nil, err } @@ -511,19 +557,7 @@ func (bs *BlockSpineService) GenerateBlock( if err != nil { return nil, err } - // compute the block payload length and hash by parsing all file chunks db entities into their bytes representation - if len(spineBlockManifests) > 0 { - for _, spineBlockManifest := range spineBlockManifests { - megablockBytes := bs.SpineBlockManifestService.GetSpineBlockManifestBytes(spineBlockManifest) - payloadBytes = append(payloadBytes, megablockBytes...) - } - } - if _, err := digest.Write(payloadBytes); err != nil { - return nil, err - } - payloadHash = digest.Sum([]byte{}) - payloadLength = uint32(len(payloadBytes)) // loop through transaction to build block hash digest.Reset() // reset the digest if _, err := digest.Write(previousBlock.GetBlockSeed()); err != nil { @@ -545,8 +579,6 @@ func (bs *BlockSpineService) GenerateBlock( blockSmithPublicKey, newBlockHeight, timestamp, - payloadHash, - payloadLength, secretPhrase, spinePublicKeys, spineBlockManifests, @@ -879,3 +911,47 @@ func (bs *BlockSpineService) WillSmith( } return blockchainProcessorLastBlockID, nil } + +func (bs *BlockSpineService) ValidateSpineBlockManifest(spineBlockManifest *model.SpineBlockManifest) error { + var ( + block model.Block + found bool + ) + qry := bs.BlockQuery.GetBlockFromTimestamp(spineBlockManifest.GetExpirationTimestamp(), 1) + row, _ := bs.QueryExecutor.ExecuteSelectRow(qry, false) + if err := bs.BlockQuery.Scan(&block, row); err != nil { + if err != sql.ErrNoRows { + return blocker.NewBlocker(blocker.DBErr, err.Error()) + } + return blocker.NewBlocker(blocker.ValidationErr, "InvalidSpineBlockManifestTimestamp") + } + if err := bs.PopulateBlockData(&block); err != nil { + return err + } + + // first check if spineBlockManifest is included in block data + spineBlockManifestBytes := bs.SpineBlockManifestService.GetSpineBlockManifestBytes(spineBlockManifest) + for _, blSpineBlockManifest := range block.GetSpineBlockManifests() { + blSpineBlockManifestBytes := bs.SpineBlockManifestService.GetSpineBlockManifestBytes(blSpineBlockManifest) + if bytes.Equal(spineBlockManifestBytes, blSpineBlockManifestBytes) { + found = true + break + } + } + if !found { + return blocker.NewBlocker(blocker.ValidationErr, "InvalidSpineBlockManifestData") + } + + // now validate against block payload hash + computedHash, computedLength, err := bs.GetPayloadHashAndLength(&block) + if err != nil { + return err + } + if !bytes.Equal(computedHash, block.GetPayloadHash()) || computedLength != block.PayloadLength { + // in this case it could be that one or more spine block manifest entries have been manually added to db after the block + // has been pushed to db + return blocker.NewBlocker(blocker.ValidationErr, "InvalidComputedSpineBlockPayloadHash") + } + + return nil +} diff --git a/core/service/blockSpineService_test.go b/core/service/blockSpineService_test.go index 30e1a5bea..94d240ecd 100644 --- a/core/service/blockSpineService_test.go +++ b/core/service/blockSpineService_test.go @@ -106,8 +106,16 @@ type ( mockSpineNodeRegistrationServiceFail struct { NodeRegistrationService } + + mockBlockSpinePublicKeyService struct { + BlockSpinePublicKeyService + } ) +func (*mockBlockSpinePublicKeyService) GetSpinePublicKeysByBlockHeight(height uint32) (spinePublicKeys []*model.SpinePublicKey, err error) { + return nil, nil +} + func (*mockSpineNodeRegistrationServiceSuccess) AddParticipationScore( nodeID, scoreDelta int64, height uint32, @@ -556,9 +564,10 @@ func TestBlockSpineService_NewSpineBlock(t *testing.T) { BlocksmithPublicKey: bcsNodePubKey1, Timestamp: 15875392, SpinePublicKeys: []*model.SpinePublicKey{}, - PayloadHash: []byte{}, - PayloadLength: 0, - BlockSignature: []byte{}, + PayloadHash: []byte{167, 255, 198, 248, 191, 30, 215, 102, 81, 193, 71, 86, 160, 97, 214, 98, 245, 128, + 255, 77, 228, 59, 73, 250, 130, 216, 10, 75, 128, 248, 67, 74}, + PayloadLength: 0, + BlockSignature: []byte{}, } mockSpineBlockHash, _ = util.GetBlockHash(mockSpineBlock, &chaintype.SpineChain{}) ) @@ -581,8 +590,6 @@ func TestBlockSpineService_NewSpineBlock(t *testing.T) { previousBlockHeight uint32 timestamp int64 spinePublicKeys []*model.SpinePublicKey - payloadHash []byte - payloadLength uint32 secretPhrase string spineBlockManifests []*model.SpineBlockManifest } @@ -607,8 +614,6 @@ func TestBlockSpineService_NewSpineBlock(t *testing.T) { previousBlockHeight: 0, timestamp: 15875392, spinePublicKeys: []*model.SpinePublicKey{}, - payloadHash: []byte{}, - payloadLength: 0, secretPhrase: "secretphrase", }, want: mockSpineBlock, @@ -629,8 +634,6 @@ func TestBlockSpineService_NewSpineBlock(t *testing.T) { tt.args.blockSmithPublicKey, tt.args.previousBlockHeight, tt.args.timestamp, - tt.args.payloadHash, - tt.args.payloadLength, tt.args.secretPhrase, tt.args.spinePublicKeys, tt.args.spineBlockManifests, @@ -1287,8 +1290,9 @@ type ( } mockSpineBlockManifestService struct { SpineBlockManifestService - ResSpineBlockManifests []*model.SpineBlockManifest - ResError error + ResSpineBlockManifests []*model.SpineBlockManifest + ResError error + ResSpineBlockManifestBytes []byte } ) @@ -2240,6 +2244,9 @@ func TestBlockSpineService_ReceiveBlock(t *testing.T) { SpinePublicKeys: []*model.SpinePublicKey{ mockSpinePublicKey, }, + PayloadLength: 44, + PayloadHash: []byte{55, 140, 121, 255, 150, 51, 177, 63, 86, 185, 40, 206, 151, 168, 77, 67, 61, 43, 54, 73, 162, 230, + 10, 202, 83, 1, 185, 208, 203, 232, 73, 215}, } mockSpineBlockData.BlockHash = mockSpineGoodLastBlockHash @@ -2809,8 +2816,9 @@ var ( 45, 118, 97, 219, 80, 242, 244, 100, 134, 144, 246, 37, 144, 213, 135}, BlockSignature: []byte{144, 246, 37, 144, 213, 135}, CumulativeDifficulty: "1000", - PayloadLength: 1, - PayloadHash: []byte{}, + PayloadLength: 0, + PayloadHash: []byte{167, 255, 198, 248, 191, 30, 215, 102, 81, 193, 71, 86, 160, 97, 214, 98, 245, 128, 255, 77, + 228, 59, 73, 250, 130, 216, 10, 75, 128, 248, 67, 74}, BlocksmithPublicKey: []byte{1, 2, 3, 200, 7, 61, 108, 229, 204, 48, 199, 145, 21, 99, 125, 75, 49, 45, 118, 97, 219, 80, 242, 244, 100, 134, 144, 246, 37, 144, 213, 135}, TotalAmount: 1000, @@ -3586,7 +3594,7 @@ type ( ) func (*mockSpineExecutorPopulateBlockDataFail) ExecuteSelect(qStr string, tx bool, args ...interface{}) (*sql.Rows, error) { - return nil, errors.New("Mock Error") + return nil, errors.New("MockError") } func (*mockSpineExecutorPopulateBlockDataSuccess) ExecuteSelect(qStr string, tx bool, args ...interface{}) (*sql.Rows, error) { @@ -3708,3 +3716,216 @@ func TestBlockSpineService_PopulateBlockData(t *testing.T) { }) } } + +type ( + mockSpineExecutorValidateSpineBlockManifest struct { + query.Executor + success bool + noRows bool + } +) + +func (msExQ *mockSpineExecutorValidateSpineBlockManifest) ExecuteSelectRow(qStr string, tx bool, args ...interface{}) (*sql.Row, error) { + db, mock, _ := sqlmock.New() + defer db.Close() + + if !msExQ.success { + return nil, errors.New("ExecuteSelectRowFailed") + } + if msExQ.noRows { + mock.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows(sqlmock.NewRows(query.NewBlockQuery(&chaintype.SpineChain{}).Fields)) + } + switch qStr { + case "SELECT id, block_hash, previous_block_hash, height, timestamp, block_seed, block_signature, cumulative_difficulty, " + + "payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, total_coinbase, " + + "version FROM spine_block WHERE timestamp >= 15875392 ORDER BY timestamp LIMIT 1": + mock.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows(sqlmock.NewRows(query.NewBlockQuery(&chaintype.SpineChain{}).Fields). + AddRow( + mockSpineBlockData.GetID(), + mockSpineBlockData.GetBlockHash(), + mockSpineBlockData.GetPreviousBlockHash(), + mockSpineBlockData.GetHeight(), + mockSpineBlockData.GetTimestamp(), + mockSpineBlockData.GetBlockSeed(), + mockSpineBlockData.GetBlockSignature(), + mockSpineBlockData.GetCumulativeDifficulty(), + uint32(8), + []byte{28, 122, 181, 212, 11, 147, 147, 173, 220, 102, 150, 8, 100, 164, 82, 120, 228, 253, 53, 160, 5, 21, + 103, 1, 127, 243, 215, 57, 88, 97, 137, 113}, + mockSpineBlockData.GetBlocksmithPublicKey(), + mockSpineBlockData.GetTotalAmount(), + mockSpineBlockData.GetTotalFee(), + mockSpineBlockData.GetTotalCoinBase(), + mockSpineBlockData.GetVersion(), + )) + default: + return nil, errors.New("UnmockedQuery") + } + row := db.QueryRow(qStr) + return row, nil +} + +func (ss *mockSpineBlockManifestService) GetSpineBlockManifestBytes(spineBlockManifest *model.SpineBlockManifest) []byte { + if spineBlockManifest.ID == 12345678 || ss.ResSpineBlockManifestBytes != nil { + return ss.ResSpineBlockManifestBytes + } + return []byte{} +} + +func TestBlockSpineService_ValidateSpineBlockManifest(t *testing.T) { + type fields struct { + RWMutex sync.RWMutex + Chaintype chaintype.ChainType + QueryExecutor query.ExecutorInterface + BlockQuery query.BlockQueryInterface + Signature crypto.SignatureInterface + BlocksmithStrategy strategy.BlocksmithStrategyInterface + Observer *observer.Observer + Logger *log.Logger + SpinePublicKeyService BlockSpinePublicKeyServiceInterface + SpineBlockManifestService SpineBlockManifestServiceInterface + } + type args struct { + spineBlockManifest *model.SpineBlockManifest + } + tests := []struct { + name string + fields fields + args args + wantErr bool + }{ + { + name: "ValidateSpineBlockManifest:success", + fields: fields{ + QueryExecutor: &mockSpineExecutorValidateSpineBlockManifest{ + success: true, + }, + BlockQuery: query.NewBlockQuery(&chaintype.SpineChain{}), + Logger: logrus.New(), + SpinePublicKeyService: &mockBlockSpinePublicKeyService{}, + SpineBlockManifestService: &mockSpineBlockManifestService{ + ResSpineBlockManifestBytes: []byte{1, 1, 1, 1, 1, 1, 1, 1}, + ResSpineBlockManifests: []*model.SpineBlockManifest{ + { + ID: 12345678, + FullFileHash: make([]byte, 64), + FileChunkHashes: make([]byte, 0), + SpineBlockManifestHeight: 720, + SpineBlockManifestType: model.SpineBlockManifestType_Snapshot, + ExpirationTimestamp: int64(1000), + }, + }, + }, + }, + args: args{ + spineBlockManifest: &model.SpineBlockManifest{ + ID: 12345678, + ExpirationTimestamp: 15875392, + }, + }, + wantErr: false, + }, + { + name: "ValidateSpineBlockManifest:fail-{InvalidSpineBlockManifestTimestamp}", + fields: fields{ + QueryExecutor: &mockSpineExecutorValidateSpineBlockManifest{ + success: true, + noRows: true, + }, + BlockQuery: query.NewBlockQuery(&chaintype.SpineChain{}), + Logger: logrus.New(), + SpinePublicKeyService: &mockBlockSpinePublicKeyService{}, + SpineBlockManifestService: &mockSpineBlockManifestService{ + ResSpineBlockManifestBytes: []byte{1, 1, 1, 1, 1, 1, 1, 1}, + ResSpineBlockManifests: []*model.SpineBlockManifest{ + { + ID: 12345678, + SpineBlockManifestType: model.SpineBlockManifestType_Snapshot, + ExpirationTimestamp: int64(1000), + }, + }, + }, + }, + args: args{ + spineBlockManifest: &model.SpineBlockManifest{ + ID: 12345678, + ExpirationTimestamp: 15875392, + }, + }, + wantErr: true, + }, + { + name: "ValidateSpineBlockManifest:fail-{InvalidSpineBlockManifestData}", + fields: fields{ + QueryExecutor: &mockSpineExecutorValidateSpineBlockManifest{ + success: true, + }, + BlockQuery: query.NewBlockQuery(&chaintype.SpineChain{}), + Logger: logrus.New(), + SpinePublicKeyService: &mockBlockSpinePublicKeyService{}, + SpineBlockManifestService: &mockSpineBlockManifestService{ + ResSpineBlockManifestBytes: []byte{1, 1, 1, 1, 1, 1, 1, 1}, + }, + }, + args: args{ + spineBlockManifest: &model.SpineBlockManifest{ + ID: 11111111, + ExpirationTimestamp: 15875392, + }, + }, + wantErr: true, + }, + { + name: "ValidateSpineBlockManifest:fail-{InvalidComputedSpineBlockPayloadHash}", + fields: fields{ + QueryExecutor: &mockSpineExecutorValidateSpineBlockManifest{ + success: true, + }, + BlockQuery: query.NewBlockQuery(&chaintype.SpineChain{}), + Logger: logrus.New(), + SpinePublicKeyService: &mockBlockSpinePublicKeyService{}, + SpineBlockManifestService: &mockSpineBlockManifestService{ + ResSpineBlockManifestBytes: []byte{1, 1, 1, 1, 1, 1, 1, 1}, + ResSpineBlockManifests: []*model.SpineBlockManifest{ + { + ID: 11111111, + SpineBlockManifestType: model.SpineBlockManifestType_Snapshot, + ExpirationTimestamp: int64(1000), + }, + { + ID: 22222222, + SpineBlockManifestType: model.SpineBlockManifestType_Snapshot, + ExpirationTimestamp: int64(1000), + }, + }, + }, + }, + args: args{ + spineBlockManifest: &model.SpineBlockManifest{ + ID: 11111111, + ExpirationTimestamp: 15875392, + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + bs := &BlockSpineService{ + RWMutex: tt.fields.RWMutex, + Chaintype: tt.fields.Chaintype, + QueryExecutor: tt.fields.QueryExecutor, + BlockQuery: tt.fields.BlockQuery, + Signature: tt.fields.Signature, + BlocksmithStrategy: tt.fields.BlocksmithStrategy, + Observer: tt.fields.Observer, + Logger: tt.fields.Logger, + SpinePublicKeyService: tt.fields.SpinePublicKeyService, + SpineBlockManifestService: tt.fields.SpineBlockManifestService, + } + if err := bs.ValidateSpineBlockManifest(tt.args.spineBlockManifest); (err != nil) != tt.wantErr { + t.Errorf("BlockSpineService.ValidateSpineBlockManifest() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/core/service/snapshotMainBlockService.go b/core/service/snapshotMainBlockService.go index 1a9116714..3d5932641 100644 --- a/core/service/snapshotMainBlockService.go +++ b/core/service/snapshotMainBlockService.go @@ -67,7 +67,6 @@ func (ss *SnapshotMainBlockService) NewSnapshotFile(block *model.Block) (snapsho snapshotExpirationTimestamp = block.Timestamp + int64(ss.chainType.GetSnapshotGenerationTimeout().Seconds()) ) - // @iltoga comment out for testing snapshots locally if block.Height <= constant.MinRollbackBlocks { return nil, blocker.NewBlocker(blocker.ValidationErr, fmt.Sprintf("invalid snapshot height: %d", block.Height)) @@ -150,7 +149,6 @@ func (ss *SnapshotMainBlockService) ImportSnapshotFile(snapshotFileInfo *model.S // IsSnapshotHeight returns true if chain height passed is a snapshot height func (ss *SnapshotMainBlockService) IsSnapshotHeight(height uint32) bool { snapshotInterval := ss.chainType.GetSnapshotInterval() - // @iltoga comment out for testing snapshots locally if snapshotInterval < constant.MinRollbackBlocks { if height < constant.MinRollbackBlocks { return false diff --git a/core/service/transactionCoreService_test.go b/core/service/transactionCoreService_test.go index d7ad2df45..42795eb25 100644 --- a/core/service/transactionCoreService_test.go +++ b/core/service/transactionCoreService_test.go @@ -3,7 +3,6 @@ package service import ( "database/sql" "errors" - "fmt" "reflect" "regexp" "testing" @@ -282,7 +281,6 @@ func (*mockQueryExecutorExpiringEscrowSuccess) ExecuteSelect(qStr string, tx boo return db.Query(qStr) } func (*mockQueryExecutorExpiringEscrowSuccess) ExecuteTransactions(queries [][]interface{}) error { - fmt.Println(queries) return nil } diff --git a/go.mod b/go.mod index 141b93dad..3ab31cfe5 100644 --- a/go.mod +++ b/go.mod @@ -3,15 +3,14 @@ module github.com/zoobc/zoobc-core go 1.14 require ( - github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect - github.com/DATA-DOG/go-sqlmock v1.3.3 - github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect + github.com/DATA-DOG/go-sqlmock v1.4.1 + github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect github.com/btcsuite/btcd v0.20.1-beta github.com/btcsuite/btcutil v1.0.1 github.com/dgraph-io/badger v1.6.0 github.com/go-ole/go-ole v1.2.4 // indirect github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129 - github.com/golang/protobuf v1.3.2 + github.com/golang/protobuf v1.3.3 github.com/google/go-cmp v0.3.1 github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 github.com/grpc-ecosystem/grpc-gateway v1.11.3 @@ -27,17 +26,11 @@ require ( github.com/shirou/gopsutil v2.19.9+incompatible github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect github.com/sirupsen/logrus v1.4.2 - github.com/spf13/afero v1.2.2 // indirect - github.com/spf13/cobra v0.0.5 - github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.4.0 - github.com/tyler-smith/go-bip39 v0.0.0-20190808214741-c55f737395bc + github.com/spf13/cobra v0.0.6 + github.com/spf13/viper v1.6.2 + github.com/tyler-smith/go-bip39 v1.0.2 github.com/ugorji/go/codec v1.1.7 - golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d - golang.org/x/net v0.0.0-20191021144547-ec77196f6094 // indirect - golang.org/x/sys v0.0.0-20191025021431-6c3a3bfe00ae // indirect - golang.org/x/text v0.3.2 // indirect - google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03 - google.golang.org/grpc v1.24.0 + golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 + google.golang.org/genproto v0.0.0-20200306153348-d950eab6f860 + google.golang.org/grpc v1.27.0 ) diff --git a/go.sum b/go.sum index 091dadc35..b17e65a4f 100644 --- a/go.sum +++ b/go.sum @@ -1,20 +1,20 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9 h1:HD8gA2tkByhMAwYaFAX9w2l7vxvBQ5NMoxDrkhqhtn4= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= -github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/DATA-DOG/go-sqlmock v1.3.3 h1:CWUqKXe0s8A2z6qCgkP4Kru7wC11YoAnoupUKFDnH08= -github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/DATA-DOG/go-sqlmock v1.4.1 h1:ThlnYciV1iM/V0OSF/dtkqWb6xo5qITT1TJBG1MRDJM= +github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= +github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -22,17 +22,26 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.1 h1:GKOz8BnRjYrb/JTKgaOk+zh26NWNdSNvdvv0xoAZMSA= github.com/btcsuite/btcutil v1.0.1/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd h1:qdGvebPBDuYDPGi1WCPjy1tGyMpmDK8IEapSsszn7HE= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 h1:ZA/jbKoGcVAnER6pCHPEkGdZOV7U1oLUedErBHCUMs0= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -41,6 +50,7 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -53,6 +63,8 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUn github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -68,19 +80,30 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129 h1:tT8iWCYw4uOem71yYA3htfH+LNopJvcqZQshm56G5L4= github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.1 h1:ocYkMQY5RrXTYgXl7ICpV0IXwlEQGwKIsery4gyXa1U= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 h1:0IKlLyQ3Hs9nDaiK5cSHAGmcQEIC8l2Ts1u6x5Dfrqg= @@ -89,23 +112,30 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.11.3 h1:h8+NsYENhxNTuq+dobk3+ODoJtwY4Fu0WQXsxJfL8aM= github.com/grpc-ecosystem/grpc-gateway v1.11.3/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.14.1 h1:YuM9SXYy583fxvSOkzCDyBPCtY+/IMSHEG1dKFMLZsA= +github.com/grpc-ecosystem/grpc-gateway v1.14.1/go.mod h1:6CwZWGDSPRJidgKAtJVvND6soZe6fT7iteq8wDPdhb0= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89 h1:12K8AlpT0/6QUXSfV0yi4Q0jkbq8NDtIKFtF61AoqV0= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= @@ -118,6 +148,8 @@ github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzR github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q= github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= +github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -140,6 +172,8 @@ github.com/pelletier/go-toml v1.5.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -147,53 +181,67 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_golang v1.5.0 h1:Ctq0iGpCmr3jeP77kbF2UxgvRwzWWz+4Bh9/vJTyg1A= +github.com/prometheus/client_golang v1.5.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8= github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shirou/gopsutil v2.19.9+incompatible h1:IrPVlK4nfwW10DF7pW+7YJKws9NkgNzWozwwWv9FsgY= github.com/shirou/gopsutil v2.19.9+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 h1:udFKJ0aHUL60LboW/A+DfgoHVedieIzIXE8uylPue0U= +github.com/shirou/gopsutil v2.20.2+incompatible h1:ucK79BhBpgqQxPASyS2cu9HX8cfDVljBN1WWFvbNvgY= +github.com/shirou/gopsutil v2.20.2+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v0.0.6 h1:breEStsVwemnKh2/s6gMvSdMEkwW0sK8vGStnlVBMCs= +github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.6.2 h1:7aKfF+e8/k68gda3LOjo5RxiUqddoFxVq4BKBPrxk5E= +github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -201,9 +249,11 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tyler-smith/go-bip39 v0.0.0-20190808214741-c55f737395bc h1:IQziJgvy3j6NMoUGlqtLRuCEk3xQpjhFgATvh3srhz4= -github.com/tyler-smith/go-bip39 v0.0.0-20190808214741-c55f737395bc/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8= +github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= @@ -220,8 +270,9 @@ golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d h1:2+ZP7EfsZV7Vvmx3TIqSlSzATMkTAKqM14YGFPoSKjI= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -236,14 +287,16 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191021144547-ec77196f6094 h1:5O4U9trLjNpuhpynaDsqwCk+Tw6seqJz1EbqbnzHrc8= -golang.org/x/net v0.0.0-20191021144547-ec77196f6094/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191002035440-2ec189313ef0 h1:2mqDk8w/o6UmeUCu5Qiq2y7iMf6anbx+YA8d1JFoFrs= +golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -254,42 +307,57 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191025021431-6c3a3bfe00ae h1:QoJmnb9uyPCrH8GIg9uRLn4Ta45yhcQtpymCd0AavO8= -golang.org/x/sys v0.0.0-20191025021431-6c3a3bfe00ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 h1:ywK/j/KkyTHcdyYSZNXGjMwgmDSfjglYZ3vStQ/gSCU= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03 h1:4HYDjxeNXAOTv3o1N2tjo8UUSlhQgAD52FVkwxnWgM8= google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200306153348-d950eab6f860 h1:QmnwU8dKvY8c/vZikd2jhBNwrrGS5qeyK/2Aeeh9Grk= +google.golang.org/genproto v0.0.0-20200306153348-d950eab6f860/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/main.go b/main.go index bea00363e..a2479436c 100644 --- a/main.go +++ b/main.go @@ -799,7 +799,10 @@ func startBlockchainSyncronizers() { ct.GetName()) break } - if lastSpineBlockManifest != nil { + err = spinechainBlockService.ValidateSpineBlockManifest(lastSpineBlockManifest) + loggerCoreService.Errorf("Invalid spineBlockManifest for chaintype %s Snapshot won't be downloaded. %s", + ct.GetName(), err) + if lastSpineBlockManifest != nil && err == nil { loggerCoreService.Infof("found a Snapshot Spine Block Manifest for chaintype %s, "+ "at height is %d. Start downloading...", ct.GetName(), lastSpineBlockManifest.SpineBlockManifestHeight)