Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v1.1.5 #550

Merged
merged 2 commits into from
Nov 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions core/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
71 changes: 48 additions & 23 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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()))

Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion params/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
)

Expand Down