Skip to content
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
36 changes: 23 additions & 13 deletions blockproducer/branch.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,22 @@ type branch struct {
unpacked map[hash.Hash]pi.Transaction
}

func fork(
from, to *blockNode, initState *metaState, initPool map[hash.Hash]pi.Transaction,
func newBranch(
baseNode, headNode *blockNode, baseState *metaState, basePool map[hash.Hash]pi.Transaction,
) (
br *branch, err error,
) {
var (
list = to.fetchNodeList(from.count)
list = headNode.fetchNodeList(baseNode.count)
inst = &branch{
head: to,
preview: initState.makeCopy(),
head: headNode,
preview: baseState.makeCopy(),
packed: make(map[hash.Hash]pi.Transaction),
unpacked: make(map[hash.Hash]pi.Transaction),
}
)
// Copy pool
for k, v := range initPool {
for k, v := range basePool {
inst.unpacked[k] = v
}
// Apply new blocks to view and pool
Expand Down Expand Up @@ -80,7 +80,16 @@ func fork(
return
}

func (b *branch) makeCopy() *branch {
// makeArena creates an arena branch from the receiver (origin) branch for tx/block applying test.
// It copies head node and transaction pools, but references the read-only preview index
// of the origin branch.
//
// This branch is typically used to attempt a block producing or applying base on the origin
// branch.
// Since it's sharing read-only index with the origin branch, result changes of the transactions
// in the new block should be written to its dirty index first, and committed to the read-only
// index later when the origin branch is being replaced by this new branch.
func (b *branch) makeArena() *branch {
var (
p = make(map[hash.Hash]pi.Transaction)
u = make(map[hash.Hash]pi.Transaction)
Expand All @@ -92,8 +101,11 @@ func (b *branch) makeCopy() *branch {
u[k] = v
}
return &branch{
head: b.head,
preview: b.preview.makeCopy(),
head: b.head,
preview: &metaState{
dirty: newMetaIndex(),
readonly: b.preview.readonly,
},
packed: p,
unpacked: u,
}
Expand All @@ -113,7 +125,7 @@ func (b *branch) applyBlock(n *blockNode) (br *branch, err error) {
err = ErrParentNotMatch
return
}
var cpy = b.makeCopy()
var cpy = b.makeArena()
for _, v := range n.block.Transactions {
var k = v.Hash()
// Check in tx pool
Expand All @@ -132,7 +144,6 @@ func (b *branch) applyBlock(n *blockNode) (br *branch, err error) {
return
}
}
cpy.preview.commit()
cpy.head = n
br = cpy
return
Expand Down Expand Up @@ -161,7 +172,7 @@ func (b *branch) produceBlock(
br *branch, bl *types.BPBlock, err error,
) {
var (
cpy = b.makeCopy()
cpy = b.makeArena()
txs = cpy.sortUnpackedTxs()
out = make([]pi.Transaction, 0, len(txs))
ierr error
Expand All @@ -175,7 +186,6 @@ func (b *branch) produceBlock(
cpy.packed[k] = v
out = append(out, v)
}
cpy.preview.commit()
// Create new block and update head
var block = &types.BPBlock{
SignedHeader: types.BPSignedHeader{
Expand Down
10 changes: 7 additions & 3 deletions blockproducer/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ func NewChainWithContext(ctx context.Context, cfg *Config) (c *Chain, err error)
"head_count": v.count,
}).Debug("checking head")
if v.hasAncestor(irre) {
if br, ierr = fork(irre, v, immutable, txPool); ierr != nil {
if br, ierr = newBranch(irre, v, immutable, txPool); ierr != nil {
err = errors.Wrapf(ierr, "failed to rebuild branch with head %s", v.hash.Short(4))
return
}
Expand Down Expand Up @@ -752,6 +752,7 @@ func (c *Chain) replaceAndSwitchToBranch(
for i, b := range c.branches {
if i == originBrIdx {
// Replace origin branch with new branch
newBranch.preview.commit()
brs = append(brs, newBranch)
idx = len(brs) - 1
} else if b.head.hasAncestor(lastIrre) {
Expand Down Expand Up @@ -836,7 +837,10 @@ func (c *Chain) applyBlock(bl *types.BPBlock) (err error) {
if br.head.count <= c.headBranch.head.count {
return store(c.st,
[]storageProcedure{addBlock(height, bl)},
func() { c.branches[i] = br },
func() {
br.preview.commit()
c.branches[i] = br
},
)
}
// Switch branch or grow current branch
Expand All @@ -854,7 +858,7 @@ func (c *Chain) applyBlock(bl *types.BPBlock) (err error) {
bl.SignedHeader.ParentHash, c.lastIrre.count,
); ok {
head = newBlockNode(height, bl, parent)
if br, ierr = fork(c.lastIrre, head, c.immutable, c.txPool); ierr != nil {
if br, ierr = newBranch(c.lastIrre, head, c.immutable, c.txPool); ierr != nil {
err = errors.Wrapf(ierr, "failed to fork from %s", parent.hash.Short(4))
return
}
Expand Down
8 changes: 6 additions & 2 deletions blockproducer/chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func TestChain(t *testing.T) {
So(err, ShouldBeNil)

// Fork from #0
f0 = chain.headBranch.makeCopy()
f0 = chain.headBranch.makeArena()

err = chain.storeTx(t1)
So(err, ShouldBeNil)
Expand All @@ -200,7 +200,7 @@ func TestChain(t *testing.T) {
So(err, ShouldBeNil)

// Fork from #1
f1 = chain.headBranch.makeCopy()
f1 = chain.headBranch.makeArena()

err = chain.storeTx(t2)
So(err, ShouldBeNil)
Expand All @@ -217,6 +217,7 @@ func TestChain(t *testing.T) {
f1, bl, err = f1.produceBlock(3, begin.Add(3*chain.period), addr2, priv2)
So(err, ShouldBeNil)
So(bl, ShouldNotBeNil)
f1.preview.commit()
err = chain.pushBlock(bl)
So(err, ShouldBeNil)

Expand All @@ -229,6 +230,7 @@ func TestChain(t *testing.T) {
i, begin.Add(time.Duration(i)*chain.period), addr2, priv2)
So(err, ShouldBeNil)
So(bl, ShouldNotBeNil)
f1.preview.commit()
err = chain.pushBlock(bl)
So(err, ShouldBeNil)
}
Expand Down Expand Up @@ -258,11 +260,13 @@ func TestChain(t *testing.T) {
f1, bl, err = f1.produceBlock(7, begin.Add(8*chain.period), addr2, priv2)
So(err, ShouldBeNil)
So(bl, ShouldNotBeNil)
f1.preview.commit()
err = chain.pushBlock(bl)
So(err, ShouldBeNil)
f1, bl, err = f1.produceBlock(8, begin.Add(9*chain.period), addr2, priv2)
So(err, ShouldBeNil)
So(bl, ShouldNotBeNil)
f1.preview.commit()
err = chain.pushBlock(bl)
So(err, ShouldBeNil)

Expand Down