From fc03a1af7bc59530681ed7d9b1daf12c1fca902c Mon Sep 17 00:00:00 2001 From: bojie Date: Wed, 5 Dec 2018 00:29:53 +0800 Subject: app: misc fixes (#76) Use sync map to prevent concurrent read write. Use last pending state to prepare/verify transactions. --- dex/app.go | 80 +++++++++++++++++++++++--------------------------------------- 1 file changed, 30 insertions(+), 50 deletions(-) diff --git a/dex/app.go b/dex/app.go index eae9ba0b3..8723420c5 100644 --- a/dex/app.go +++ b/dex/app.go @@ -47,9 +47,7 @@ type DexconApp struct { chainDB ethdb.Database config *Config - chainLocksInitMu sync.Mutex - chainLocks map[uint32]*sync.RWMutex - + chainLocks sync.Map chainLatestRoot sync.Map } @@ -67,7 +65,6 @@ func NewDexconApp(txPool *core.TxPool, blockchain *core.BlockChain, gov *DexconG gov: gov, chainDB: chainDB, config: config, - chainLocks: make(map[uint32]*sync.RWMutex), } } @@ -75,32 +72,38 @@ func (d *DexconApp) addrBelongsToChain(address common.Address, chainSize, chainI return new(big.Int).Mod(address.Big(), chainSize).Cmp(chainID) == 0 } -func (d *DexconApp) chainLockInit(chainID uint32) { - d.chainLocksInitMu.Lock() - defer d.chainLocksInitMu.Unlock() - - _, exist := d.chainLocks[chainID] - if !exist { - d.chainLocks[chainID] = &sync.RWMutex{} - } -} - func (d *DexconApp) chainLock(chainID uint32) { - d.chainLockInit(chainID) - d.chainLocks[chainID].Lock() + v, ok := d.chainLocks.Load(chainID) + if !ok { + v = &sync.RWMutex{} + d.chainLocks.Store(chainID, v) + } + v.(*sync.RWMutex).Lock() } func (d *DexconApp) chainUnlock(chainID uint32) { - d.chainLocks[chainID].Unlock() + v, ok := d.chainLocks.Load(chainID) + if !ok { + panic(fmt.Errorf("chain %v is not init yet", chainID)) + } + v.(*sync.RWMutex).Unlock() } func (d *DexconApp) chainRLock(chainID uint32) { - d.chainLockInit(chainID) - d.chainLocks[chainID].RLock() + v, ok := d.chainLocks.Load(chainID) + if !ok { + v = &sync.RWMutex{} + d.chainLocks.Store(chainID, v) + } + v.(*sync.RWMutex).RLock() } func (d *DexconApp) chainRUnlock(chainID uint32) { - d.chainLocks[chainID].RUnlock() + v, ok := d.chainLocks.Load(chainID) + if !ok { + panic(fmt.Errorf("chain %v is not init yet", chainID)) + } + v.(*sync.RWMutex).RUnlock() } // validateNonce check if nonce is in order and return first nonce of every address. @@ -189,21 +192,9 @@ func (d *DexconApp) preparePayload(ctx context.Context, position coreTypes.Posit } } - var root *common.Hash - value, ok := d.chainLatestRoot.Load(position.ChainID) - if ok { - root = value.(*common.Hash) - } else { - currentRoot := d.blockchain.CurrentBlock().Root() - root = ¤tRoot - } - - // Set state to the chain latest height. - latestState, err := d.blockchain.StateAt(*root) - if err != nil { - log.Error("Get pending state", "error", err) - return nil, fmt.Errorf("get pending state error: %v", err) - } + b, latestState := d.blockchain.GetPending() + log.Debug("Prepare payload", "chain", position.ChainID, "height", position.Height, "state", + b.Root().String()) txsMap, err := d.txPool.Pending() if err != nil { @@ -367,21 +358,10 @@ func (d *DexconApp) VerifyBlock(block *coreTypes.Block) coreTypes.BlockVerifySta } } - // Find the latest state for the given block height. - var root *common.Hash - value, ok := d.chainLatestRoot.Load(block.Position.ChainID) - if ok { - root = value.(*common.Hash) - } else { - currentRoot := d.blockchain.CurrentBlock().Root() - root = ¤tRoot - } - - latestState, err := d.blockchain.StateAt(*root) - if err != nil { - log.Error("Failed to get pending state", "error", err) - return coreTypes.VerifyInvalidBlock - } + // Get latest pending state. + b, latestState := d.blockchain.GetPending() + log.Debug("Verify block", "chain", block.Position.ChainID, "height", block.Position.Height, "state", + b.Root().String()) var transactions types.Transactions if len(block.Payload) == 0 { -- cgit v1.2.3