Bläddra i källkod

Merge pull request #550 from binance-chain/develop

Release v1.1.5
yutianwu 4 år sedan
förälder
incheckning
8ff7d531e8
7 ändrade filer med 71 tillägg och 26 borttagningar
  1. 9 0
      CHANGELOG.md
  2. 1 1
      core/blockchain.go
  3. 3 0
      core/error.go
  4. 8 0
      core/state/statedb.go
  5. 48 23
      internal/ethapi/api.go
  6. 1 1
      params/config.go
  7. 1 1
      params/version.go

+ 9 - 0
CHANGELOG.md

@@ -1,4 +1,13 @@
 # Changelog
+## v1.1.5
+BUGFIX
+* [\#509](https://github.com/binance-chain/bsc/pull/509) fix graceful shutdown bug
+
+IMPROVEMENT
+* [\#536](https://github.com/binance-chain/bsc/pull/536) get diff accounts by replaying block when diff layer not found
+* [\#527](https://github.com/binance-chain/bsc/pull/527) improve diffsync protocol in many aspects
+* [\#493](https://github.com/binance-chain/bsc/pull/493) implement fast getDiffAccountsWithScope API
+
 ## v1.1.4
 Improvement
 * [\#472](https://github.com/binance-chain/bsc/pull/472) add metrics for contract code bitmap cache

+ 1 - 1
core/blockchain.go

@@ -1011,7 +1011,7 @@ func (bc *BlockChain) GetDiffAccounts(blockHash common.Hash) ([]common.Address,
 
 	if diffLayer == nil {
 		if header.TxHash != types.EmptyRootHash {
-			return nil, fmt.Errorf("no diff layer found")
+			return nil, ErrDiffLayerNotFound
 		}
 
 		return nil, nil

+ 3 - 0
core/error.go

@@ -31,6 +31,9 @@ var (
 
 	// ErrNoGenesis is returned when there is no Genesis Block.
 	ErrNoGenesis = errors.New("genesis not found in chain")
+
+	// ErrDiffLayerNotFound is returned when diff layer not found.
+	ErrDiffLayerNotFound = errors.New("diff layer not found")
 )
 
 // List of evm-call-message pre-checking errors. All state transition messages will

+ 8 - 0
core/state/statedb.go

@@ -1493,3 +1493,11 @@ func (s *StateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addre
 	}
 	return s.accessList.Contains(addr, slot)
 }
+
+func (s *StateDB) GetDirtyAccounts() []common.Address {
+	accounts := make([]common.Address, 0, len(s.stateObjectsDirty))
+	for account := range s.stateObjectsDirty {
+		accounts = append(accounts, account)
+	}
+	return accounts
+}

+ 48 - 23
internal/ethapi/api.go

@@ -1098,7 +1098,21 @@ func (s *PublicBlockChainAPI) GetDiffAccounts(ctx context.Context, blockNr rpc.B
 		return nil, fmt.Errorf("block not found for block number (%d): %v", blockNr, err)
 	}
 
-	return s.b.Chain().GetDiffAccounts(header.Hash())
+	accounts, err := s.b.Chain().GetDiffAccounts(header.Hash())
+	if err == nil || !errors.Is(err, core.ErrDiffLayerNotFound) {
+		return accounts, err
+	}
+
+	// Replay the block when diff layer not found, it is very slow.
+	block, err := s.b.BlockByNumber(ctx, blockNr)
+	if err != nil {
+		return nil, fmt.Errorf("block not found for block number (%d): %v", blockNr, err)
+	}
+	_, statedb, err := s.replay(ctx, block, nil)
+	if err != nil {
+		return nil, err
+	}
+	return statedb.GetDirtyAccounts(), nil
 }
 
 func (s *PublicBlockChainAPI) needToReplay(ctx context.Context, block *types.Block, accounts []common.Address) (bool, error) {
@@ -1161,36 +1175,20 @@ func (s *PublicBlockChainAPI) needToReplay(ctx context.Context, block *types.Blo
 	return false, nil
 }
 
-// GetDiffAccountsWithScope returns detailed changes of some interested accounts in a specific block number.
-func (s *PublicBlockChainAPI) GetDiffAccountsWithScope(ctx context.Context, blockNr rpc.BlockNumber, accounts []common.Address) (*types.DiffAccountsInBlock, error) {
-	if s.b.Chain() == nil {
-		return nil, fmt.Errorf("blockchain not support get diff accounts")
-	}
-
-	block, err := s.b.BlockByNumber(ctx, blockNr)
-	if err != nil {
-		return nil, fmt.Errorf("block not found for block number (%d): %v", blockNr, err)
-	}
-
+func (s *PublicBlockChainAPI) replay(ctx context.Context, block *types.Block, accounts []common.Address) (*types.DiffAccountsInBlock, *state.StateDB, error) {
 	result := &types.DiffAccountsInBlock{
-		Number:       uint64(blockNr),
+		Number:       block.NumberU64(),
 		BlockHash:    block.Hash(),
 		Transactions: make([]types.DiffAccountsInTx, 0),
 	}
 
-	if needReplay, err := s.needToReplay(ctx, block, accounts); err != nil {
-		return nil, err
-	} else if !needReplay {
-		return result, nil
-	}
-
 	parent, err := s.b.BlockByHash(ctx, block.ParentHash())
 	if err != nil {
-		return nil, fmt.Errorf("block not found for block number (%d): %v", blockNr-1, err)
+		return nil, nil, fmt.Errorf("block not found for block number (%d): %v", block.NumberU64()-1, err)
 	}
 	statedb, err := s.b.Chain().StateAt(parent.Root())
 	if err != nil {
-		return nil, fmt.Errorf("state not found for block number (%d): %v", blockNr-1, err)
+		return nil, nil, fmt.Errorf("state not found for block number (%d): %v", block.NumberU64()-1, err)
 	}
 
 	accountSet := make(map[common.Address]struct{}, len(accounts))
@@ -1240,7 +1238,7 @@ func (s *PublicBlockChainAPI) GetDiffAccountsWithScope(ctx context.Context, bloc
 		}
 
 		if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
-			return nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
+			return nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
 		}
 		statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
 
@@ -1259,7 +1257,34 @@ func (s *PublicBlockChainAPI) GetDiffAccountsWithScope(ctx context.Context, bloc
 		}
 	}
 
-	return result, nil
+	return result, statedb, nil
+}
+
+// GetDiffAccountsWithScope returns detailed changes of some interested accounts in a specific block number.
+func (s *PublicBlockChainAPI) GetDiffAccountsWithScope(ctx context.Context, blockNr rpc.BlockNumber, accounts []common.Address) (*types.DiffAccountsInBlock, error) {
+	if s.b.Chain() == nil {
+		return nil, fmt.Errorf("blockchain not support get diff accounts")
+	}
+
+	block, err := s.b.BlockByNumber(ctx, blockNr)
+	if err != nil {
+		return nil, fmt.Errorf("block not found for block number (%d): %v", blockNr, err)
+	}
+
+	needReplay, err := s.needToReplay(ctx, block, accounts)
+	if err != nil {
+		return nil, err
+	}
+	if !needReplay {
+		return &types.DiffAccountsInBlock{
+			Number:       uint64(blockNr),
+			BlockHash:    block.Hash(),
+			Transactions: make([]types.DiffAccountsInTx, 0),
+		}, nil
+	}
+
+	result, _, err := s.replay(ctx, block, accounts)
+	return result, err
 }
 
 // ExecutionResult groups all structured logs emitted by the EVM

+ 1 - 1
params/config.go

@@ -250,7 +250,7 @@ var (
 		RamanujanBlock:      big.NewInt(0),
 		NielsBlock:          big.NewInt(0),
 		MirrorSyncBlock:     big.NewInt(5184000),
-		BrunoBlock:          nil,
+		BrunoBlock:          big.NewInt(13082000),
 		Parlia: &ParliaConfig{
 			Period: 3,
 			Epoch:  200,

+ 1 - 1
params/version.go

@@ -23,7 +23,7 @@ import (
 const (
 	VersionMajor = 1  // Major version component of the current release
 	VersionMinor = 1  // Minor version component of the current release
-	VersionPatch = 4  // Patch version component of the current release
+	VersionPatch = 5  // Patch version component of the current release
 	VersionMeta  = "" // Version metadata to append to the version string
 )