Fixed bootstrapping put container ID error

This commit is contained in:
StephenButtolph 2020-05-03 18:38:12 -04:00
parent 71b2cf9c06
commit 456295888a
4 changed files with 240 additions and 10 deletions

View File

@ -93,15 +93,21 @@ func (b *bootstrapper) ForceAccepted(acceptedContainerIDs ids.Set) {
func (b *bootstrapper) Put(vdr ids.ShortID, requestID uint32, vtxID ids.ID, vtxBytes []byte) {
b.BootstrapConfig.Context.Log.Verbo("Put called for vertexID %s", vtxID)
if !b.pending.Contains(vtxID) {
return
}
vtx, err := b.State.ParseVertex(vtxBytes)
if err != nil {
b.BootstrapConfig.Context.Log.Warn("ParseVertex failed due to %s for block:\n%s",
err,
formatting.DumpBytes{Bytes: vtxBytes})
b.GetFailed(vdr, requestID)
return
}
if !b.pending.Contains(vtx.ID()) {
b.BootstrapConfig.Context.Log.Warn("Validator %s sent an unrequested vertex:\n%s",
vdr,
formatting.DumpBytes{Bytes: vtxBytes})
b.GetFailed(vdr, requestID)
return
}

View File

@ -288,7 +288,6 @@ func TestBootstrapperUnknownByzantineResponse(t *testing.T) {
bs.ForceAccepted(acceptedIDs)
state.getVertex = nil
sender.GetF = nil
state.parseVertex = func(vtxBytes []byte) (avalanche.Vertex, error) {
switch {
@ -1007,3 +1006,111 @@ func TestBootstrapperPartialFetch(t *testing.T) {
t.Fatalf("wrong number pending")
}
}
func TestBootstrapperWrongIDByzantineResponse(t *testing.T) {
config, peerID, sender, state, _ := newConfig(t)
vtxID0 := ids.Empty.Prefix(0)
vtxID1 := ids.Empty.Prefix(1)
vtxBytes0 := []byte{0}
vtxBytes1 := []byte{1}
vtx0 := &Vtx{
id: vtxID0,
height: 0,
status: choices.Processing,
bytes: vtxBytes0,
}
vtx1 := &Vtx{
id: vtxID1,
height: 0,
status: choices.Processing,
bytes: vtxBytes1,
}
bs := bootstrapper{}
bs.metrics.Initialize(config.Context.Log, fmt.Sprintf("gecko_%s", config.Context.ChainID), prometheus.NewRegistry())
bs.Initialize(config)
acceptedIDs := ids.Set{}
acceptedIDs.Add(
vtxID0,
)
state.getVertex = func(vtxID ids.ID) (avalanche.Vertex, error) {
switch {
case vtxID.Equals(vtxID0):
return nil, errUnknownVertex
default:
t.Fatal(errUnknownVertex)
panic(errUnknownVertex)
}
}
requestID := new(uint32)
sender.GetF = func(vdr ids.ShortID, reqID uint32, vtxID ids.ID) {
if !vdr.Equals(peerID) {
t.Fatalf("Should have requested vertex from %s, requested from %s", peerID, vdr)
}
switch {
case vtxID.Equals(vtxID0):
default:
t.Fatalf("Requested unknown vertex")
}
*requestID = reqID
}
bs.ForceAccepted(acceptedIDs)
state.getVertex = nil
sender.GetF = nil
state.parseVertex = func(vtxBytes []byte) (avalanche.Vertex, error) {
switch {
case bytes.Equal(vtxBytes, vtxBytes0):
return vtx0, nil
case bytes.Equal(vtxBytes, vtxBytes1):
return vtx1, nil
}
t.Fatal(errParsedUnknownVertex)
return nil, errParsedUnknownVertex
}
state.getVertex = func(vtxID ids.ID) (avalanche.Vertex, error) {
switch {
case vtxID.Equals(vtxID0):
return vtx0, nil
case vtxID.Equals(vtxID1):
return vtx1, nil
default:
t.Fatal(errUnknownVertex)
panic(errUnknownVertex)
}
}
finished := new(bool)
bs.onFinished = func() { *finished = true }
sender.CantGet = false
bs.Put(peerID, *requestID, vtxID0, vtxBytes1)
sender.CantGet = true
bs.Put(peerID, *requestID, vtxID0, vtxBytes0)
state.parseVertex = nil
state.edge = nil
bs.onFinished = nil
if !*finished {
t.Fatalf("Bootstrapping should have finished")
}
if vtx0.Status() != choices.Accepted {
t.Fatalf("Vertex should be accepted")
}
if vtx1.Status() != choices.Processing {
t.Fatalf("Vertex should be processing")
}
}

View File

@ -87,15 +87,21 @@ func (b *bootstrapper) ForceAccepted(acceptedContainerIDs ids.Set) {
func (b *bootstrapper) Put(vdr ids.ShortID, requestID uint32, blkID ids.ID, blkBytes []byte) {
b.BootstrapConfig.Context.Log.Verbo("Put called for blkID %s", blkID)
if !b.pending.Contains(blkID) {
return
}
blk, err := b.VM.ParseBlock(blkBytes)
if err != nil {
b.BootstrapConfig.Context.Log.Warn("ParseBlock failed due to %s for block:\n%s",
err,
formatting.DumpBytes{Bytes: blkBytes})
b.GetFailed(vdr, requestID)
return
}
if !b.pending.Contains(blk.ID()) {
b.BootstrapConfig.Context.Log.Warn("Validator %s sent an unrequested block:\n%s",
vdr,
formatting.DumpBytes{Bytes: blkBytes})
b.GetFailed(vdr, requestID)
return
}

View File

@ -222,12 +222,13 @@ func TestBootstrapperUnknownByzantineResponse(t *testing.T) {
bs.ForceAccepted(acceptedIDs)
vm.GetBlockF = nil
sender.GetF = nil
vm.ParseBlockF = func(blkBytes []byte) (snowman.Block, error) {
switch {
case bytes.Equal(blkBytes, blkBytes1):
return blk1, nil
case bytes.Equal(blkBytes, blkBytes2):
return blk2, nil
}
t.Fatal(errUnknownBlock)
return nil, errUnknownBlock
@ -476,3 +477,113 @@ func TestBootstrapperPartialFetch(t *testing.T) {
t.Fatalf("wrong number pending")
}
}
func TestBootstrapperWrongIDByzantineResponse(t *testing.T) {
config, peerID, sender, vm := newConfig(t)
blkID0 := ids.Empty.Prefix(0)
blkID1 := ids.Empty.Prefix(1)
blkID2 := ids.Empty.Prefix(2)
blkBytes0 := []byte{0}
blkBytes1 := []byte{1}
blkBytes2 := []byte{2}
blk0 := &Blk{
id: blkID0,
height: 0,
status: choices.Accepted,
bytes: blkBytes0,
}
blk1 := &Blk{
parent: blk0,
id: blkID1,
height: 1,
status: choices.Processing,
bytes: blkBytes1,
}
blk2 := &Blk{
parent: blk1,
id: blkID2,
height: 2,
status: choices.Processing,
bytes: blkBytes2,
}
bs := bootstrapper{}
bs.metrics.Initialize(config.Context.Log, fmt.Sprintf("gecko_%s", config.Context.ChainID), prometheus.NewRegistry())
bs.Initialize(config)
acceptedIDs := ids.Set{}
acceptedIDs.Add(blkID1)
vm.GetBlockF = func(blkID ids.ID) (snowman.Block, error) {
switch {
case blkID.Equals(blkID1):
return nil, errUnknownBlock
default:
t.Fatal(errUnknownBlock)
panic(errUnknownBlock)
}
}
requestID := new(uint32)
sender.GetF = func(vdr ids.ShortID, reqID uint32, vtxID ids.ID) {
if !vdr.Equals(peerID) {
t.Fatalf("Should have requested block from %s, requested from %s", peerID, vdr)
}
switch {
case vtxID.Equals(blkID1):
default:
t.Fatalf("Requested unknown block")
}
*requestID = reqID
}
bs.ForceAccepted(acceptedIDs)
vm.GetBlockF = nil
sender.GetF = nil
vm.ParseBlockF = func(blkBytes []byte) (snowman.Block, error) {
switch {
case bytes.Equal(blkBytes, blkBytes2):
return blk2, nil
}
t.Fatal(errUnknownBlock)
return nil, errUnknownBlock
}
sender.CantGet = false
bs.Put(peerID, *requestID, blkID1, blkBytes2)
sender.CantGet = true
vm.ParseBlockF = func(blkBytes []byte) (snowman.Block, error) {
switch {
case bytes.Equal(blkBytes, blkBytes1):
return blk1, nil
}
t.Fatal(errUnknownBlock)
return nil, errUnknownBlock
}
finished := new(bool)
bs.onFinished = func() { *finished = true }
bs.Put(peerID, *requestID, blkID1, blkBytes1)
vm.ParseBlockF = nil
if !*finished {
t.Fatalf("Bootstrapping should have finished")
}
if blk1.Status() != choices.Accepted {
t.Fatalf("Block should be accepted")
}
if blk2.Status() != choices.Processing {
t.Fatalf("Block should be processing")
}
}