Skip to content

Commit 615f0f3

Browse files
authored
IOTEX-126 Remove dummy block handling logic (iotexproject#241)
1 parent 00729b6 commit 615f0f3

File tree

16 files changed

+23
-583
lines changed

16 files changed

+23
-583
lines changed

blockchain/block.go

+1-12
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,6 @@ func NewSecretBlock(
130130
return block
131131
}
132132

133-
// IsDummyBlock checks whether block is a dummy block
134-
func (b *Block) IsDummyBlock() bool {
135-
return b.Header.height > 0 &&
136-
len(b.Header.blockSig) == 0 &&
137-
b.Header.Pubkey == keypair.ZeroPublicKey &&
138-
len(b.Actions) == 0
139-
}
140-
141133
// Height returns the height of this block
142134
func (b *Block) Height() uint64 {
143135
return b.Header.height
@@ -168,10 +160,7 @@ func (b *Block) ByteStreamHeader() []byte {
168160
tmp8B := make([]byte, 8)
169161
enc.MachineEndian.PutUint64(tmp8B, b.Header.height)
170162
stream = append(stream, tmp8B...)
171-
// TODO: exclude timestamp from block hash because dummy block needs to have a consistent hash no matter which
172-
// node produces it at a given height. Once we get rid of the dummy block concept, we need to include it into
173-
// the hash block hash again
174-
//enc.MachineEndian.PutUint64(tmp8B, b.Header.timestamp)
163+
enc.MachineEndian.PutUint64(tmp8B, b.Header.timestamp)
175164
stream = append(stream, tmp8B...)
176165
stream = append(stream, b.Header.prevBlockHash[:]...)
177166
stream = append(stream, b.Header.txRoot[:]...)

blockchain/blockchain.go

+3-56
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,6 @@ type Blockchain interface {
107107
// MintNewSecretBlock creates a new DKG secret block with given DKG secrets and witness
108108
MintNewSecretBlock(secretProposals []*action.SecretProposal, secretWitness *action.SecretWitness,
109109
producer *iotxaddress.Address) (*Block, error)
110-
// MintDummyNewBlock creates a new dummy block, used for unreached consensus
111-
MintNewDummyBlock() *Block
112110
// CommitBlock validates and appends a block to the chain
113111
CommitBlock(blk *Block) error
114112
// ValidateBlock validates a new block before adding it to the blockchain
@@ -728,30 +726,6 @@ func (bc *blockchain) MintNewSecretBlock(
728726
return blk, nil
729727
}
730728

731-
// MintDummyNewBlock creates a new dummy block, used for unreached consensus
732-
func (bc *blockchain) MintNewDummyBlock() *Block {
733-
bc.mu.RLock()
734-
defer bc.mu.RUnlock()
735-
736-
blk := NewBlock(bc.config.Chain.ID, bc.tipHeight+1, bc.tipHash, bc.now(), nil)
737-
blk.Header.Pubkey = keypair.ZeroPublicKey
738-
blk.Header.blockSig = []byte{}
739-
740-
// run execution and update state trie root hash
741-
ws, err := bc.sf.NewWorkingSet()
742-
if err != nil {
743-
return nil
744-
}
745-
root, err := bc.runActions(blk, ws, false)
746-
if err != nil {
747-
return nil
748-
}
749-
blk.Header.stateRoot = root
750-
// attach working set to be committed to state factory
751-
blk.workingSet = ws
752-
return blk
753-
}
754-
755729
// CommitBlock validates and appends a block to the chain
756730
func (bc *blockchain) CommitBlock(blk *Block) error {
757731
bc.mu.Lock()
@@ -818,13 +792,8 @@ func (bc *blockchain) validateBlock(blk *Block, containCoinbase bool) error {
818792
logger.Panic().Msg("no block validator")
819793
}
820794

821-
tipHeight, tipHash, err := bc.replaceHeightAndHash(blk)
822-
if err != nil {
823-
return errors.Wrap(err, "failed to get the tip height and tip hash of blockchain")
824-
}
825-
826-
if err := bc.validator.Validate(blk, tipHeight, tipHash, containCoinbase); err != nil {
827-
return errors.Wrapf(err, "Failed to validate block on height %d", tipHeight)
795+
if err := bc.validator.Validate(blk, bc.tipHeight, bc.tipHash, containCoinbase); err != nil {
796+
return errors.Wrapf(err, "Failed to validate block on height %d", bc.tipHeight)
828797
}
829798
// run actions and update state factory
830799
ws, err := bc.sf.NewWorkingSet()
@@ -833,7 +802,7 @@ func (bc *blockchain) validateBlock(blk *Block, containCoinbase bool) error {
833802
}
834803
// TODO: disable validation before resolve the state root doesn't match issue
835804
if _, err := bc.runActions(blk, ws, false); err != nil {
836-
logger.Panic().Err(err).Msgf("Failed to update state on height %d", tipHeight)
805+
logger.Panic().Err(err).Msgf("Failed to update state on height %d", bc.tipHeight)
837806
}
838807
// attach working set to be committed to state factory
839808
blk.workingSet = ws
@@ -891,28 +860,6 @@ func (bc *blockchain) runActions(blk *Block, ws state.WorkingSet, verify bool) (
891860
return root, nil
892861
}
893862

894-
func (bc *blockchain) replaceHeightAndHash(blk *Block) (uint64, hash.Hash32B, error) {
895-
tipHeight := bc.tipHeight
896-
tipHash := bc.tipHash
897-
// replacement logic, used to replace a fake old dummy block
898-
if blk.Height() != 0 && blk.Height() <= bc.tipHeight {
899-
oldDummyBlock, err := bc.GetBlockByHeight(blk.Height())
900-
if err != nil {
901-
return 0, hash.ZeroHash32B, errors.Wrapf(err, "The height of the new block is invalid")
902-
}
903-
if !oldDummyBlock.IsDummyBlock() {
904-
return 0, hash.ZeroHash32B, errors.New("The replaced block is not a dummy block")
905-
}
906-
lastBlock, err := bc.GetBlockByHeight(blk.Height() - 1)
907-
if err != nil {
908-
return 0, hash.ZeroHash32B, errors.Wrapf(err, "Failed to get the last block when replacing the dummy block")
909-
}
910-
tipHeight = lastBlock.Height()
911-
tipHash = lastBlock.HashBlock()
912-
}
913-
return tipHeight, tipHash, nil
914-
}
915-
916863
func (bc *blockchain) SubscribeBlockCreation(ch chan *Block) error {
917864
bc.blocklistener = append(bc.blocklistener, ch)
918865
return nil

blockchain/blockchain_test.go

+1-120
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ import (
1111
"encoding/hex"
1212
"fmt"
1313
"math/big"
14-
"strings"
1514
"testing"
16-
"time"
1715

1816
"github.com/facebookgo/clock"
1917
"github.com/stretchr/testify/require"
@@ -644,40 +642,6 @@ func TestBlockchain_Validator(t *testing.T) {
644642
require.NotNil(t, bc.Validator())
645643
}
646644

647-
func TestBlockchain_MintNewDummyBlock(t *testing.T) {
648-
cfg := &config.Default
649-
testutil.CleanupPath(t, cfg.Chain.TrieDBPath)
650-
defer testutil.CleanupPath(t, cfg.Chain.TrieDBPath)
651-
testutil.CleanupPath(t, cfg.Chain.ChainDBPath)
652-
defer testutil.CleanupPath(t, cfg.Chain.ChainDBPath)
653-
require := require.New(t)
654-
sf, err := state.NewFactory(cfg, state.DefaultTrieOption())
655-
require.NoError(err)
656-
require.NoError(sf.Start(context.Background()))
657-
val := validator{sf, ""}
658-
659-
ctx := context.Background()
660-
bc := NewBlockchain(cfg, InMemDaoOption(), InMemStateFactoryOption())
661-
require.NoError(bc.Start(ctx))
662-
defer func() {
663-
err := bc.Stop(ctx)
664-
require.Nil(err)
665-
}()
666-
require.NotNil(bc)
667-
668-
blk := bc.MintNewDummyBlock()
669-
require.Equal(uint64(1), blk.Height())
670-
tipHash := bc.TipHash()
671-
require.NoError(val.Validate(blk, 0, tipHash, true))
672-
tsf, _ := action.NewTransfer(1, big.NewInt(1), "", "", []byte{}, uint64(100000), big.NewInt(10))
673-
blk.Actions = []action.Action{tsf}
674-
err = val.Validate(blk, 0, tipHash, true)
675-
require.Error(err)
676-
require.True(
677-
strings.Contains(err.Error(), "failed to verify block's signature"),
678-
)
679-
}
680-
681645
func TestBlockchainInitialCandidate(t *testing.T) {
682646
require := require.New(t)
683647

@@ -870,85 +834,6 @@ func TestActions(t *testing.T) {
870834
require.Nil(val.Validate(blk, 0, blk.PrevHash(), true))
871835
}
872836

873-
func TestDummyReplacement(t *testing.T) {
874-
require := require.New(t)
875-
cfg := config.Default
876-
877-
testutil.CleanupPath(t, testTriePath)
878-
defer testutil.CleanupPath(t, testTriePath)
879-
testutil.CleanupPath(t, testDBPath)
880-
defer testutil.CleanupPath(t, testDBPath)
881-
882-
cfg.Chain.TrieDBPath = testTriePath
883-
cfg.Chain.ChainDBPath = testDBPath
884-
885-
sf, _ := state.NewFactory(&cfg, state.InMemTrieOption())
886-
require.NoError(sf.Start(context.Background()))
887-
require.NoError(addCreatorToFactory(sf))
888-
889-
// Create a blockchain from scratch
890-
bc := NewBlockchain(&cfg, PrecreatedStateFactoryOption(sf), BoltDBDaoOption())
891-
require.NoError(bc.Start(context.Background()))
892-
dummy := bc.MintNewDummyBlock()
893-
require.Nil(bc.ValidateBlock(dummy, true))
894-
require.NoError(bc.CommitBlock(dummy))
895-
actualDummyBlock, err := bc.GetBlockByHeight(1)
896-
require.NoError(err)
897-
require.Equal(dummy.HashBlock(), actualDummyBlock.HashBlock())
898-
899-
chain := bc.(*blockchain)
900-
chain.tipHeight = 0
901-
realBlock, err := bc.MintNewBlock(nil, ta.Addrinfo["producer"],
902-
nil, nil, "")
903-
require.NotNil(realBlock)
904-
require.NoError(err)
905-
require.Nil(bc.ValidateBlock(realBlock, true))
906-
require.NoError(bc.CommitBlock(realBlock))
907-
actualRealBlock, err := bc.GetBlockByHeight(1)
908-
require.NoError(err)
909-
require.Equal(realBlock.HashBlock(), actualRealBlock.HashBlock())
910-
911-
block2, err := bc.MintNewBlock(nil, ta.Addrinfo["producer"],
912-
nil, nil, "")
913-
require.NoError(err)
914-
require.Nil(bc.ValidateBlock(block2, true))
915-
require.NoError(bc.CommitBlock(block2))
916-
dummyBlock3 := bc.MintNewDummyBlock()
917-
require.Nil(bc.ValidateBlock(dummyBlock3, true))
918-
require.NoError(bc.CommitBlock(dummyBlock3))
919-
block4, err := bc.MintNewBlock(nil, ta.Addrinfo["producer"],
920-
nil, nil, "")
921-
require.NoError(err)
922-
require.NoError(bc.ValidateBlock(block4, true))
923-
require.NoError(bc.CommitBlock(block4))
924-
actualDummyBlock3, err := bc.GetBlockByHeight(3)
925-
require.NoError(err)
926-
require.True(actualDummyBlock3.IsDummyBlock())
927-
chain.tipHeight = 2
928-
block3, err := bc.MintNewBlock(nil, ta.Addrinfo["producer"],
929-
nil, nil, "")
930-
require.NotNil(block3)
931-
require.NoError(err)
932-
require.NoError(bc.ValidateBlock(block3, true))
933-
require.NoError(bc.CommitBlock(block3))
934-
actualBlock3, err := bc.GetBlockByHeight(3)
935-
require.NoError(err)
936-
require.Equal(block3.HashBlock(), actualBlock3.HashBlock())
937-
}
938-
939-
func TestMintNewBlock(t *testing.T) {
940-
t.Parallel()
941-
cfg := config.Default
942-
clk := clock.NewMock()
943-
chain := NewBlockchain(&cfg, InMemDaoOption(), InMemStateFactoryOption(), ClockOption(clk))
944-
require.NoError(t, chain.Start(context.Background()))
945-
blk1 := chain.MintNewDummyBlock()
946-
clk.Add(2 * time.Second)
947-
blk2 := chain.MintNewDummyBlock()
948-
require.Equal(t, uint64(2), blk2.Header.timestamp-blk1.Header.timestamp)
949-
require.Equal(t, blk1.HashBlock(), blk2.HashBlock())
950-
}
951-
952837
func TestMintDKGBlock(t *testing.T) {
953838
require := require.New(t)
954839
lastSeed, _ := hex.DecodeString("9de6306b08158c423330f7a27243a1a5cbe39bfd764f07818437882d21241567")
@@ -1015,10 +900,6 @@ func TestMintDKGBlock(t *testing.T) {
1015900
}
1016901

1017902
// Generate dkg signature for each block
1018-
require.NoError(err)
1019-
dummy := chain.MintNewDummyBlock()
1020-
require.NoError(chain.ValidateBlock(dummy, true))
1021-
require.NoError(chain.CommitBlock(dummy))
1022903
for i := 1; i < numNodes; i++ {
1023904
iotxAddr := iotxaddress.Address{
1024905
PublicKey: ec283PKList[i],
@@ -1036,7 +917,7 @@ func TestMintDKGBlock(t *testing.T) {
1036917
}
1037918
height, err := chain.GetFactory().Height()
1038919
require.NoError(err)
1039-
require.Equal(uint64(21), height)
920+
require.Equal(uint64(20), height)
1040921
candidates, err := chain.CandidatesByHeight(height)
1041922
require.NoError(err)
1042923
require.Equal(21, len(candidates))

blockchain/blockvalidator.go

-3
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,6 @@ func (v *validator) Validate(blk *Block, tipHeight uint64, tipHash hash.Hash32B,
5656
if err := verifyHeightAndHash(blk, tipHeight, tipHash); err != nil {
5757
return errors.Wrap(err, "failed to verify block's height and hash")
5858
}
59-
if blk.IsDummyBlock() {
60-
return nil
61-
}
6259
if err := verifySigAndRoot(blk); err != nil {
6360
return errors.Wrap(err, "failed to verify block's signature and merkle root")
6461
}

blocksync/blocksync.go

+1-4
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,7 @@ func (bs *blockSyncer) P2P() network.Overlay {
7979
// Start starts a block syncer
8080
func (bs *blockSyncer) Start(ctx context.Context) error {
8181
logger.Debug().Msg("Starting block syncer")
82-
startHeight, err := findSyncStartHeight(bs.bc)
83-
if err != nil {
84-
return err
85-
}
82+
startHeight := bs.bc.TipHeight() + 1
8683
bs.buf.startHeight = startHeight
8784
bs.buf.confirmedHeight = startHeight - 1
8885
return bs.worker.Start(ctx)

blocksync/buffer.go

+3-17
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,6 @@ func (b *blockBuffer) Flush(blk *blockchain.Block) (bool, bCheckinResult) {
5151
return moved, bCheckinLower
5252
}
5353
if h < b.startHeight {
54-
// try to replace a dummy block
55-
if blk.IsDummyBlock() {
56-
return moved, bCheckinLower
57-
}
5854
if err := commitBlock(b.bc, b.ap, blk); err != nil {
5955
return moved, bCheckinLower
6056
}
@@ -78,11 +74,8 @@ func (b *blockBuffer) Flush(blk *blockchain.Block) (bool, bCheckinResult) {
7874
}
7975
if err := commitBlock(b.bc, b.ap, b.blocks[syncHeight]); err == nil {
8076
syncedHeight = syncHeight
81-
if !b.blocks[syncedHeight].IsDummyBlock() {
82-
b.confirmedHeight = syncedHeight
83-
}
84-
l.Info().Uint64("syncedHeight", syncedHeight).Bool("dummy", b.blocks[syncedHeight].IsDummyBlock()).
85-
Msg("Successfully committed block.")
77+
b.confirmedHeight = syncedHeight
78+
l.Info().Uint64("syncedHeight", syncedHeight).Msg("Successfully committed block.")
8679
delete(b.blocks, syncHeight)
8780
continue
8881
} else {
@@ -94,14 +87,7 @@ func (b *blockBuffer) Flush(blk *blockchain.Block) (bool, bCheckinResult) {
9487
if blk.HashBlock() == b.blocks[syncHeight].HashBlock() {
9588
// same existing block
9689
syncedHeight = syncHeight
97-
if !b.blocks[syncedHeight].IsDummyBlock() {
98-
b.confirmedHeight = syncedHeight
99-
}
100-
} else if blk.IsDummyBlock() {
101-
// existing dummy but get a bad block
102-
l.Error().Uint64("syncHeight", syncHeight).
103-
Uint64("syncedHeight", syncedHeight).
104-
Msg("Failed to replace dummy block.")
90+
b.confirmedHeight = syncedHeight
10591
}
10692
delete(b.blocks, syncHeight)
10793
} else {

blocksync/util.go

-25
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ package blocksync
99
import (
1010
"time"
1111

12-
"github.com/pkg/errors"
13-
1412
"github.com/iotexproject/iotex-core/actpool"
1513
"github.com/iotexproject/iotex-core/blockchain"
1614
"github.com/iotexproject/iotex-core/config"
@@ -28,29 +26,6 @@ func commitBlock(bc blockchain.Blockchain, ap actpool.ActPool, blk *blockchain.B
2826
return nil
2927
}
3028

31-
// findSyncStartHeight needs to find a reasonable start point to sync
32-
// 1. current height + 1 if current height is not dummy
33-
// 2. current height remove all dummy on top + 1
34-
// 3. FIXME this node may still has issue, if it was following the wrong chain, this is actually a general version of 2, but in 3, we need to rollback blockchain first
35-
func findSyncStartHeight(bc blockchain.Blockchain) (uint64, error) {
36-
var next uint64
37-
h := bc.TipHeight()
38-
for ; ; h-- {
39-
blk, err := bc.GetBlockByHeight(h)
40-
if err != nil {
41-
return next, err
42-
}
43-
if !blk.IsDummyBlock() {
44-
next = h + 1
45-
break
46-
}
47-
if h == 0 { // 0 height is dummy
48-
return next, errors.New("0 height block is dummy block")
49-
}
50-
}
51-
return next, nil
52-
}
53-
5429
// syncTaskInterval returns the recurring sync task interval, or 0 if this config should not need to run sync task
5530
func syncTaskInterval(cfg *config.Config) time.Duration {
5631
if cfg.IsLightweight() {

0 commit comments

Comments
 (0)