From 47bf310abc899597e91c73b6303522adcc43f923 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Mon, 16 Mar 2020 16:38:06 -0400 Subject: [PATCH] Implemented filtered vertex issuance --- snow/engine/avalanche/issuer.go | 19 ++++-- snow/engine/avalanche/transitive.go | 2 +- snow/engine/avalanche/transitive_test.go | 78 ++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 5 deletions(-) diff --git a/snow/engine/avalanche/issuer.go b/snow/engine/avalanche/issuer.go index befe973..cdbc969 100644 --- a/snow/engine/avalanche/issuer.go +++ b/snow/engine/avalanche/issuer.go @@ -6,6 +6,7 @@ package avalanche import ( "github.com/ava-labs/gecko/ids" "github.com/ava-labs/gecko/snow/consensus/avalanche" + "github.com/ava-labs/gecko/snow/consensus/snowstorm" ) type issuer struct { @@ -44,14 +45,24 @@ func (i *issuer) Update() { vtxID := i.vtx.ID() i.t.pending.Remove(vtxID) - for _, tx := range i.vtx.Txs() { + txs := i.vtx.Txs() + validTxs := []snowstorm.Tx{} + for _, tx := range txs { if err := tx.Verify(); err != nil { - i.t.Config.Context.Log.Debug("Transaction failed verification due to %s, dropping vertex", err) - i.t.vtxBlocked.Abandon(vtxID) - return + i.t.Config.Context.Log.Debug("Transaction %s failed verification due to %s", tx.ID(), err) + } else { + validTxs = append(validTxs, tx) } } + if len(validTxs) != len(txs) { + i.t.Config.Context.Log.Debug("Abandoning %s due to failed transaction verification", vtxID) + + i.t.batch(validTxs, false /*=force*/, false /*=empty*/) + i.t.vtxBlocked.Abandon(vtxID) + return + } + i.t.Config.Context.Log.Verbo("Adding vertex to consensus:\n%s", i.vtx) i.t.Consensus.Add(i.vtx) diff --git a/snow/engine/avalanche/transitive.go b/snow/engine/avalanche/transitive.go index 4d6617f..4de2aa5 100644 --- a/snow/engine/avalanche/transitive.go +++ b/snow/engine/avalanche/transitive.go @@ -309,7 +309,7 @@ func (t *Transitive) batch(txs []snowstorm.Tx, force, empty bool) { } // Force allows for a conflict to be issued - if txID := tx.ID(); !overlaps && !issuedTxs.Contains(txID) && (force || (t.Consensus.IsVirtuous(tx))) && !tx.Status().Decided() { + if txID := tx.ID(); !overlaps && !issuedTxs.Contains(txID) && (force || t.Consensus.IsVirtuous(tx)) && !tx.Status().Decided() { batch = append(batch, tx) issuedTxs.Add(txID) consumed.Union(inputs) diff --git a/snow/engine/avalanche/transitive_test.go b/snow/engine/avalanche/transitive_test.go index 32799ec..764c75f 100644 --- a/snow/engine/avalanche/transitive_test.go +++ b/snow/engine/avalanche/transitive_test.go @@ -2469,3 +2469,81 @@ func TestEngineUndeclaredDependencyDeadlock(t *testing.T) { t.Fatalf("should have accepted the vertex due to transitive voting") } } + +func TestEnginePartiallyValidVertex(t *testing.T) { + config := DefaultConfig() + + vdr := validators.GenerateRandomValidator(1) + + vals := validators.NewSet() + config.Validators = vals + + vals.Add(vdr) + + st := &stateTest{t: t} + config.State = st + + gVtx := &Vtx{ + id: GenerateID(), + status: choices.Accepted, + } + + vts := []avalanche.Vertex{gVtx} + utxos := []ids.ID{GenerateID(), GenerateID()} + + tx0 := &TestTx{ + TestTx: snowstorm.TestTx{ + Identifier: GenerateID(), + Stat: choices.Processing, + }, + } + tx0.Ins.Add(utxos[0]) + + tx1 := &TestTx{ + TestTx: snowstorm.TestTx{ + Identifier: GenerateID(), + Stat: choices.Processing, + Validity: errors.New(""), + }, + } + tx1.Ins.Add(utxos[1]) + + vtx := &Vtx{ + parents: vts, + id: GenerateID(), + txs: []snowstorm.Tx{tx0, tx1}, + height: 1, + status: choices.Processing, + } + + te := &Transitive{} + te.Initialize(config) + te.finishBootstrapping() + + expectedVtxID := GenerateID() + st.buildVertex = func(_ ids.Set, txs []snowstorm.Tx) (avalanche.Vertex, error) { + consumers := []snowstorm.Tx{} + for _, tx := range txs { + consumers = append(consumers, tx) + } + return &Vtx{ + parents: vts, + id: expectedVtxID, + txs: consumers, + status: choices.Processing, + bytes: []byte{1}, + }, nil + } + + sender := &common.SenderTest{} + sender.T = t + te.Config.Sender = sender + + sender.PushQueryF = func(_ ids.ShortSet, _ uint32, vtxID ids.ID, _ []byte) { + if !expectedVtxID.Equals(vtxID) { + t.Fatalf("wrong vertex queried") + } + } + + te.insert(vtx) +}