From b95529138805750dec234ef6aafc45b241f5a5a4 Mon Sep 17 00:00:00 2001 From: MestryOmkar Date: Tue, 6 Nov 2018 18:00:21 +0530 Subject: [PATCH] init double validation layer --- contracts/utils.go | 25 +++++++++------------ core/blockchain.go | 9 ++++---- core/tx_pool.go | 8 +++++++ eth/backend.go | 51 ++++++++++++++++++++++++++++++++++++++++-- eth/fetcher/fetcher.go | 2 +- 5 files changed, 73 insertions(+), 22 deletions(-) diff --git a/contracts/utils.go b/contracts/utils.go index 85e0cb1161..986a9ff81b 100644 --- a/contracts/utils.go +++ b/contracts/utils.go @@ -257,6 +257,7 @@ func ExtractValidatorsFromBytes(byteValidators []byte) []int64 { intNumber, err := strconv.Atoi(string(trimByte)) if err != nil { log.Error("Can not convert string to integer", "error", err) + return []int64{} } validators = append(validators, int64(intNumber)) } @@ -553,26 +554,20 @@ func GetMasternodesFromCheckpointHeader(checkpointHeader *types.Header) []common } // Get m2 list from checkpoint block. -func GetM2FromCheckpointBlock(checkpointBlock types.Block) ([]common.Address, error) { +func GetM1M2FromCheckpointBlock(checkpointBlock *types.Block) (map[common.Address]common.Address, error) { if checkpointBlock.Number().Int64()%common.EpocBlockRandomize != 0 { return nil, errors.New("This block is not checkpoint block epoc.") } - - // Get singers from this block. + m1m2 := map[common.Address]common.Address{} + // Get signers from this block. masternodes := GetMasternodesFromCheckpointHeader(checkpointBlock.Header()) validators := ExtractValidatorsFromBytes(checkpointBlock.Header().Validators) - var m2List []common.Address - lenMasternodes := len(masternodes) - var valAddr common.Address - for validatorIndex := range validators { - if validatorIndex < lenMasternodes { - valAddr = masternodes[validatorIndex] - } else { - valAddr = masternodes[validatorIndex-lenMasternodes] - } - m2List = append(m2List, valAddr) + if len(validators) < len(masternodes) { + return nil, errors.New("Len(m2) is less than len(m1)") } - - return m2List, nil + for i, m1 := range masternodes { + m1m2[m1] = masternodes[validators[i]] + } + return m1m2, nil } \ No newline at end of file diff --git a/core/blockchain.go b/core/blockchain.go index 5b7396dc4a..46e3454bd1 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1633,16 +1633,17 @@ func (bc *BlockChain) UpdateM1() error { ms = append(ms, XDPoS.Masternode{Address: candidate, Stake: v.Uint64()}) } } - log.Info("Ordered list of masternode candidates") - for _, m := range ms { - log.Info("", "address", m.Address.String(), "stake", m.Stake) - } + if len(ms) == 0 { log.Info("No masternode candidates found. Keep the current masternodes set for the next epoch") } else { sort.Slice(ms, func(i, j int) bool { return ms[i].Stake >= ms[j].Stake }) + log.Info("Ordered list of masternode candidates") + for _, m := range ms { + log.Info("", "address", m.Address.String(), "stake", m.Stake) + } // update masternodes log.Info("Updating new set of masternodes") if len(ms) > common.MaxMasternodes { diff --git a/core/tx_pool.go b/core/tx_pool.go index e3f878fa70..a15fb1a606 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -553,6 +553,14 @@ func (pool *TxPool) local() map[common.Address]types.Transactions { return txs } +func (pool *TxPool) GetSender(tx *types.Transaction) (common.Address, error) { + from, err := types.Sender(pool.signer, tx) + if err != nil { + return common.Address{}, ErrInvalidSender + } + return from, nil +} + // validateTx checks whether a transaction is valid according to the consensus // rules and adheres to some heuristic limits of the local node (price and size). func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { diff --git a/eth/backend.go b/eth/backend.go index fcab7c9450..6bab13c56a 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -51,6 +51,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" + "time" ) const NumOfMasternodes = 99 @@ -201,10 +202,37 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { return } if _, authorized := snap.Signers[eth.etherbase]; authorized { - if err := contracts.CreateTransactionSign(chainConfig, eth.txPool, eth.accountManager, block, chainDb); err != nil { - log.Error("Fail to create tx sign for imported block", "error", err) + // double validation + m2, err := getM2(snap, eth, block) + if err != nil { + log.Error("Fail to validate M2 condition for imported block", "error", err) return } + if eth.etherbase != m2 { + //wait until signTx from m2 comes into txPool + txCh := make(chan core.TxPreEvent, txChanSize) + eth.txPool.SubscribeTxPreEvent(txCh) + G: + select { + case event := <-txCh: + from, err := eth.txPool.GetSender(event.Tx) + if (err == nil) && (event.Tx.To().String() == common.BlockSigners) && (from == m2) { + if err := contracts.CreateTransactionSign(chainConfig, eth.txPool, eth.accountManager, block, chainDb); err != nil { + log.Error("Fail to create tx sign for imported block", "error", err) + return + } + } + //timeout 10s + case <-time.After(time.Duration(10) * time.Second): + break G + } + close(txCh) + } else if err := contracts.CreateTransactionSign(chainConfig, eth.txPool, eth.accountManager, block, chainDb); err != nil { + log.Error("Fail to create tx sign for imported block", "error", err) + return + } + // end of double validation + } } eth.protocolManager.fetcher.SetImportedHook(importedHook) @@ -292,6 +320,25 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { return eth, nil } +func getM2(snap *XDPoS.Snapshot, eth *Ethereum, block *types.Block) (common.Address, error) { + epoch := eth.chainConfig.XDPoS.Epoch + no := block.NumberU64() + cpNo := no + if no%epoch != 0 { + cpNo = no - (no % epoch) + } + cpBlk := eth.blockchain.GetBlockByNumber(cpNo) + m, err := contracts.GetM1M2FromCheckpointBlock(cpBlk) + if err != nil { + return common.Address{}, err + } + m1, err := XDPoS.WhoIsCreator(snap, block.Header()) + if err != nil { + return common.Address{}, err + } + return m[m1], nil +} + func makeExtraData(extra []byte) []byte { if len(extra) == 0 { // create default extradata diff --git a/eth/fetcher/fetcher.go b/eth/fetcher/fetcher.go index a8659865bb..7043a256e3 100644 --- a/eth/fetcher/fetcher.go +++ b/eth/fetcher/fetcher.go @@ -674,7 +674,7 @@ func (f *Fetcher) insert(peer string, block *types.Block) { propAnnounceOutTimer.UpdateSince(block.ReceivedAt) go f.broadcastBlock(block, false) - // Invoke the testing hook if needed + // Invoke the imported hook if needed if f.importedHook != nil { f.importedHook(block) }