Add Forkchoice Tie Breaker (#2459)

This commit is contained in:
terence tsao 2019-05-01 10:18:56 -07:00 committed by GitHub
parent 05336e16e0
commit 38da4a5cd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 98 additions and 1 deletions

View File

@ -259,7 +259,16 @@ func (c *ChainService) lmdGhost(
if err != nil {
return nil, fmt.Errorf("unable to determine vote count for block: %v", err)
}
if candidateChildVotes > maxChildVotes {
maxChildRoot, err := hashutil.HashBeaconBlock(maxChild)
if err != nil {
return nil, err
}
candidateChildRoot, err := hashutil.HashBeaconBlock(children[i])
if err != nil {
return nil, err
}
if candidateChildVotes > maxChildVotes ||
(candidateChildVotes == maxChildVotes && bytesutil.LowerThan(maxChildRoot[:], candidateChildRoot[:])) {
maxChild = children[i]
}
}

View File

@ -1,6 +1,7 @@
package blockchain
import (
"bytes"
"context"
"crypto/rand"
"encoding/binary"
@ -653,6 +654,93 @@ func TestLMDGhost_3WayChainSplitsSameHeight(t *testing.T) {
}
}
func TestLMDGhost_3WayChainSplitsEqualVotes(t *testing.T) {
beaconDB := internal.SetupDB(t)
defer internal.TeardownDB(t, beaconDB)
ctx := context.Background()
beaconState := &pb.BeaconState{
Slot: 10,
}
chainService := setupBeaconChain(t, beaconDB, nil)
// Construct the following chain:
// /- B2 (0 vote)
// B1 - B3 (0 vote)
// \- B4 (0 vote)
block1 := &pb.BeaconBlock{
Slot: 1,
ParentRootHash32: []byte{'A'},
}
root1, err := hashutil.HashBeaconBlock(block1)
if err != nil {
t.Fatalf("Could not hash block: %v", err)
}
if err = chainService.beaconDB.SaveBlock(block1); err != nil {
t.Fatalf("Could not save block: %v", err)
}
if err = chainService.beaconDB.UpdateChainHead(ctx, block1, beaconState); err != nil {
t.Fatalf("Could update chain head: %v", err)
}
block2 := &pb.BeaconBlock{
Slot: 2,
ParentRootHash32: root1[:],
}
root2, _ := hashutil.HashBeaconBlock(block2)
if err = chainService.beaconDB.SaveBlock(block2); err != nil {
t.Fatalf("Could not save block: %v", err)
}
if err = chainService.beaconDB.UpdateChainHead(ctx, block2, beaconState); err != nil {
t.Fatalf("Could update chain head: %v", err)
}
block3 := &pb.BeaconBlock{
Slot: 3,
ParentRootHash32: root1[:],
}
root3, _ := hashutil.HashBeaconBlock(block3)
if err = chainService.beaconDB.SaveBlock(block3); err != nil {
t.Fatalf("Could not save block: %v", err)
}
if err = chainService.beaconDB.UpdateChainHead(ctx, block3, beaconState); err != nil {
t.Fatalf("Could update chain head: %v", err)
}
block4 := &pb.BeaconBlock{
Slot: 4,
ParentRootHash32: root1[:],
}
root4, _ := hashutil.HashBeaconBlock(block4)
if err = chainService.beaconDB.SaveBlock(block4); err != nil {
t.Fatalf("Could not save block: %v", err)
}
if err = chainService.beaconDB.UpdateChainHead(ctx, block4, beaconState); err != nil {
t.Fatalf("Could update chain head: %v", err)
}
head, err := chainService.lmdGhost(ctx, block1, beaconState, nil)
if err != nil {
t.Fatalf("Could not run LMD GHOST: %v", err)
}
// Don't assign any vote to blocks 2, 3 and 4.
// Find which has a lexicographically higher root between block 2, 3 and 4.
higherRoot := root2
if bytesutil.LowerThan(root2[:], root3[:]) {
higherRoot = root3
}
if bytesutil.LowerThan(higherRoot[:], root4[:]) {
higherRoot = root4
}
// Compare the highest root with head root.
headRoot, _ := hashutil.HashBeaconBlock(head)
if !bytes.Equal(headRoot[:], higherRoot[:]) {
t.Errorf("Expected head root to equal %v, received %v", higherRoot, headRoot)
}
}
func TestIsDescendant_Ok(t *testing.T) {
beaconDB := internal.SetupDB(t)
defer internal.TeardownDB(t, beaconDB)