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

[factory] add parent to workingset #4539

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
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
36 changes: 24 additions & 12 deletions blockchain/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,14 @@ type (
BlockBuilderFactory interface {
// NewBlockBuilder creates block builder
NewBlockBuilder(context.Context, func(action.Envelope) (*action.SealedEnvelope, error)) (*block.Builder, error)
// OngoingBlockHeight returns the height of current ongoing block (not yet committed)
OngoingBlockHeight() uint64
// PendingBlockHeader returns the header of pending blocks (not yet committed)
PendingBlockHeader(uint64) (*block.Header, error)
// PutBlockHeader stores the pending block header
PutBlockHeader(*block.Header)
// CancelBlock indicates the block producing fails
CancelBlock(uint64)
}

// blockchain implements the Blockchain interface
Expand Down Expand Up @@ -287,10 +295,7 @@ func (bc *blockchain) ValidateBlock(blk *block.Block, opts ...BlockValidationOpt
if blk == nil {
return ErrInvalidBlock
}
tipHeight, err := bc.dao.Height()
if err != nil {
return err
}
tipHeight := blk.Height() - 1
tip, err := bc.tipInfo(tipHeight)
if err != nil {
return err
Expand Down Expand Up @@ -412,10 +417,7 @@ func (bc *blockchain) MintNewBlock(timestamp time.Time) (*block.Block, error) {
defer bc.mu.RUnlock()
mintNewBlockTimer := bc.timerFactory.NewTimer("MintNewBlock")
defer mintNewBlockTimer.End()
tipHeight, err := bc.dao.Height()
if err != nil {
return nil, err
}
tipHeight := bc.bbf.OngoingBlockHeight()
newblockHeight := tipHeight + 1
ctx, err := bc.context(context.Background(), tipHeight)
if err != nil {
Expand All @@ -439,6 +441,7 @@ func (bc *blockchain) MintNewBlock(timestamp time.Time) (*block.Block, error) {
if err != nil {
return nil, errors.Wrapf(err, "failed to create block")
}
bc.bbf.PutBlockHeader(&blk.Header)
_blockMtc.WithLabelValues("MintGas").Set(float64(blk.GasUsed()))
_blockMtc.WithLabelValues("MintActions").Set(float64(len(blk.Actions)))
return &blk, nil
Expand Down Expand Up @@ -478,21 +481,30 @@ func (bc *blockchain) Genesis() genesis.Genesis {
// private functions
//=====================================

func (bc *blockchain) tipInfo(tipHeight uint64) (*protocol.TipInfo, error) {
if tipHeight == 0 {
func (bc *blockchain) tipInfo(height uint64) (*protocol.TipInfo, error) {
if height == 0 {
return &protocol.TipInfo{
Height: 0,
Hash: bc.genesis.Hash(),
Timestamp: time.Unix(bc.genesis.Timestamp, 0),
}, nil
}
header, err := bc.dao.HeaderByHeight(tipHeight)
tipHeight, err := bc.dao.Height()
if err != nil {
return nil, err
}
var header *block.Header
if height <= tipHeight {
header, err = bc.dao.HeaderByHeight(height)
} else {
header, err = bc.bbf.PendingBlockHeader(height)
}
if err != nil {
return nil, err
}

return &protocol.TipInfo{
Height: tipHeight,
Height: height,
GasUsed: header.GasUsed(),
Hash: header.HashBlock(),
Timestamp: header.Timestamp(),
Expand Down
127 changes: 127 additions & 0 deletions blockchain/integrity/integrity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,133 @@ func createChain(cfg config.Config, inMem bool) (blockchain.Blockchain, factory.
return bc, sf, dao, ap, nil
}

func TestBlockPipeline(t *testing.T) {
require := require.New(t)

cfg := config.Default
testIndexPath, err := testutil.PathOfTempFile("index")
require.NoError(err)

defer func() {
testutil.CleanupPath(testIndexPath)
// clear the gateway
delete(cfg.Plugins, config.GatewayPlugin)
}()

minGas := big.NewInt(unit.Qev)
cfg.Chain.IndexDBPath = testIndexPath
cfg.Chain.ProducerPrivKey = "a000000000000000000000000000000000000000000000000000000000000000"
cfg.Genesis.EnableGravityChainVoting = false
cfg.Plugins[config.GatewayPlugin] = true
cfg.Chain.EnableAsyncIndexWrite = false
cfg.ActPool.MinGasPriceStr = minGas.String()
cfg.Genesis.PacificBlockHeight = 2
cfg.Genesis.AleutianBlockHeight = 2
cfg.Genesis.BeringBlockHeight = 2
cfg.Genesis.CookBlockHeight = 2
cfg.Genesis.DaytonaBlockHeight = 2
cfg.Genesis.DardanellesBlockHeight = 2
cfg.Genesis.EasterBlockHeight = 2
cfg.Genesis.FbkMigrationBlockHeight = 2
cfg.Genesis.FairbankBlockHeight = 2
cfg.Genesis.GreenlandBlockHeight = 2
cfg.Genesis.HawaiiBlockHeight = 2
cfg.Genesis.IcelandBlockHeight = 2
cfg.Genesis.JutlandBlockHeight = 2
cfg.Genesis.KamchatkaBlockHeight = 2
cfg.Genesis.LordHoweBlockHeight = 2
cfg.Genesis.MidwayBlockHeight = 2
cfg.Genesis.NewfoundlandBlockHeight = 2
cfg.Genesis.OkhotskBlockHeight = 2
cfg.Genesis.PalauBlockHeight = 2
cfg.Genesis.InitBalanceMap[identityset.Address(27).String()] = unit.ConvertIotxToRau(10000000000).String()

ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis)
bc, sf, _, ap, err := createChain(cfg, true)
require.NoError(err)
sk, err := iotexcrypto.HexStringToPrivateKey(cfg.Chain.ProducerPrivKey)
require.NoError(err)
producer := sk.PublicKey().Address()
ctrl := gomock.NewController(t)
pp := mock_poll.NewMockProtocol(ctrl)
pp.EXPECT().CreateGenesisStates(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
pp.EXPECT().Candidates(gomock.Any(), gomock.Any()).Return([]*state.Candidate{
{
Address: producer.String(),
RewardAddress: producer.String(),
},
}, nil).AnyTimes()
pp.EXPECT().Register(gomock.Any()).DoAndReturn(func(reg *protocol.Registry) error {
return reg.Register("poll", pp)
}).AnyTimes()
pp.EXPECT().Validate(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
require.NoError(sf.Register(pp))
require.NoError(bc.Start(ctx))
defer func() {
require.NoError(bc.Stop(ctx))
}()

// Add block 1
nonce, err := ap.GetPendingNonce(identityset.Address(27).String())
require.NoError(err)
require.EqualValues(1, nonce)
nonce, err = ap.GetPendingNonce(identityset.Address(25).String())
require.NoError(err)
require.EqualValues(1, nonce)
priKey0 := identityset.PrivateKey(27)
ex1, err := action.SignedExecution(action.EmptyAddress, priKey0, 1, new(big.Int), 500000, minGas, _constantinopleOpCodeContract)
require.NoError(err)
require.NoError(ap.Add(ctx, ex1))
tsf1, err := action.SignedTransfer(identityset.Address(25).String(), priKey0, 2, big.NewInt(10000), nil, 500000, minGas)
require.NoError(err)
require.NoError(ap.Add(ctx, tsf1))
tsf2, err := action.SignedTransfer(identityset.Address(24).String(), priKey0, 3, big.NewInt(20000), nil, 500000, minGas)
require.NoError(err)
require.NoError(ap.Add(ctx, tsf2))
blockTime := time.Unix(1546329600, 0)
blk, err := bc.MintNewBlock(blockTime)
require.NoError(err)
require.EqualValues(1, blk.Height())
require.Equal(4, len(blk.Body.Actions))
require.NoError(bc.ValidateBlock(blk))
// add block 2
tsf3, err := action.SignedTransfer(identityset.Address(23).String(), priKey0, 4, big.NewInt(30000), nil, 500000, minGas)
require.NoError(err)
require.NoError(ap.Add(ctx, tsf3))
deterministic, err := address.FromHex("3fab184622dc19b6109349b94811493bf2a45362")
require.NoError(err)
tsf4, err := action.SignedTransfer(deterministic.String(), priKey0, 5, big.NewInt(10000000000000000), nil, 500000, minGas)
require.NoError(err)
require.NoError(ap.Add(ctx, tsf4))
println("mint block 2")
blk1, err := bc.MintNewBlock(blockTime.Add(time.Second))
require.NoError(err)
require.EqualValues(2, blk1.Height())
require.Equal(3, len(blk1.Body.Actions))
require.NoError(bc.ValidateBlock(blk1))
require.NoError(bc.CommitBlock(blk))
require.NoError(bc.CommitBlock(blk1))
// verify accounts
for _, v := range []struct {
a address.Address
atype int32
nonce uint64
b string
}{
{identityset.Address(27), 0, 6, "9999999999180825999999940000"},
{identityset.Address(25), 0, 1, "100000000000000000000010000"},
{identityset.Address(24), 0, 1, "100000000000000000000020000"},
{identityset.Address(23), 0, 1, "100000000000000000000030000"},
{deterministic, 1, 0, "10000000000000000"},
} {
a, err := accountutil.AccountState(ctx, sf, v.a)
require.NoError(err)
require.Equal(v.atype, a.AccountType())
require.Equal(v.nonce, a.PendingNonce())
require.Equal(v.b, a.Balance.String())
}
}

func TestBlockchainHardForkFeatures(t *testing.T) {
require := require.New(t)

Expand Down
5 changes: 3 additions & 2 deletions consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,16 @@ func NewConsensus(
SetAddr(cfg.Chain.ProducerAddress().String()).
SetPriKey(cfg.Chain.ProducerPrivateKey()).
SetConfig(cfg).
SetChainManager(rolldpos.NewChainManager(bc)).
SetChainManager(rolldpos.NewChainManager2(bc, sf)).
SetBlockDeserializer(block.NewDeserializer(bc.EvmNetworkID())).
SetClock(clock).
SetBroadcast(ops.broadcastHandler).
SetDelegatesByEpochFunc(delegatesByEpochFunc).
SetProposersByEpochFunc(proposersByEpochFunc).
RegisterProtocol(ops.rp)
// TODO: explorer dependency deleted here at #1085, need to revive by migrating to api
cs.scheme, err = bd.Build()
// cs.scheme, err = bd.Build()
cs.scheme = rolldpos.NewChainedRollDPoS(bd)
if err != nil {
log.Logger("consensus").Panic("Error when constructing RollDPoS.", zap.Error(err))
}
Expand Down
Loading
Loading