From 2b881e63b007c9f5894ed602a7f75aa220d8a9b5 Mon Sep 17 00:00:00 2001 From: Christopher Tarry Date: Fri, 16 Feb 2024 17:35:00 -0500 Subject: [PATCH 1/3] fix case where manager would panic when adding v1 transaction after v2 require height --- chain/manager.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/chain/manager.go b/chain/manager.go index 202f07b..a2d1327 100644 --- a/chain/manager.go +++ b/chain/manager.go @@ -14,6 +14,9 @@ import ( var ( // ErrFutureBlock is returned when a block's timestamp is too far in the future. ErrFutureBlock = errors.New("block's timestamp is too far in the future") + // ErrV1AfterV2Required is returned when a v1 transaction is introduced after + // v2 transactions are required. + ErrV1AfterV2Required = errors.New("v1 transaction added after v2 require height") ) // An ApplyUpdate reflects the changes to the blockchain resulting from the @@ -296,6 +299,9 @@ func (m *Manager) applyTip(index types.ChainIndex) error { panic("applyTip called with non-attaching block") } else if bs == nil { bs = new(consensus.V1BlockSupplement) + if cs.Index.Height > cs.Network.HardforkV2.RequireHeight && len(b.Transactions) > 0 { + return ErrV1AfterV2Required + } *bs = m.store.SupplementTipBlock(b) if err := consensus.ValidateBlock(m.tipState, b, *bs); err != nil { m.markBadBlock(index.ID, err) @@ -985,6 +991,10 @@ func (m *Manager) AddPoolTransactions(txns []types.Transaction) (known bool, err return true, m.txpool.invalidTxnSets[setID] } + if m.tipState.Index.Height > m.tipState.Network.HardforkV2.RequireHeight { + return false, m.markBadTxnSet(setID, fmt.Errorf("transactions are invalid: %w", ErrV1AfterV2Required)) + } + // validate as a standalone set ms := consensus.NewMidState(m.tipState) for _, txn := range txns { From 49a5d8870555e101f36dc4ad0a4e5d67b2c2dfa9 Mon Sep 17 00:00:00 2001 From: lukechampine Date: Sat, 17 Feb 2024 10:06:49 -0800 Subject: [PATCH 2/3] Revert "fix case where manager would panic when adding v1 transaction after v2 require height" This reverts commit 2b881e63b007c9f5894ed602a7f75aa220d8a9b5. --- chain/manager.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/chain/manager.go b/chain/manager.go index a2d1327..202f07b 100644 --- a/chain/manager.go +++ b/chain/manager.go @@ -14,9 +14,6 @@ import ( var ( // ErrFutureBlock is returned when a block's timestamp is too far in the future. ErrFutureBlock = errors.New("block's timestamp is too far in the future") - // ErrV1AfterV2Required is returned when a v1 transaction is introduced after - // v2 transactions are required. - ErrV1AfterV2Required = errors.New("v1 transaction added after v2 require height") ) // An ApplyUpdate reflects the changes to the blockchain resulting from the @@ -299,9 +296,6 @@ func (m *Manager) applyTip(index types.ChainIndex) error { panic("applyTip called with non-attaching block") } else if bs == nil { bs = new(consensus.V1BlockSupplement) - if cs.Index.Height > cs.Network.HardforkV2.RequireHeight && len(b.Transactions) > 0 { - return ErrV1AfterV2Required - } *bs = m.store.SupplementTipBlock(b) if err := consensus.ValidateBlock(m.tipState, b, *bs); err != nil { m.markBadBlock(index.ID, err) @@ -991,10 +985,6 @@ func (m *Manager) AddPoolTransactions(txns []types.Transaction) (known bool, err return true, m.txpool.invalidTxnSets[setID] } - if m.tipState.Index.Height > m.tipState.Network.HardforkV2.RequireHeight { - return false, m.markBadTxnSet(setID, fmt.Errorf("transactions are invalid: %w", ErrV1AfterV2Required)) - } - // validate as a standalone set ms := consensus.NewMidState(m.tipState) for _, txn := range txns { From ca6ce92faba54cd739f24d5f896e2ec9174a6c9d Mon Sep 17 00:00:00 2001 From: lukechampine Date: Sat, 17 Feb 2024 10:05:14 -0800 Subject: [PATCH 3/3] chain: No-op when supplementing v1 blocks post-hardfork --- chain/db.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/chain/db.go b/chain/db.go index d05c035..b1c3667 100644 --- a/chain/db.go +++ b/chain/db.go @@ -526,8 +526,12 @@ func (db *DBStore) BestIndex(height uint64) (index types.ChainIndex, ok bool) { // SupplementTipTransaction implements Store. func (db *DBStore) SupplementTipTransaction(txn types.Transaction) (ts consensus.V1TransactionSupplement) { + height := db.getHeight() + if height >= db.n.HardforkV2.RequireHeight { + return consensus.V1TransactionSupplement{} + } // get tip state, for proof-trimming - index, _ := db.BestIndex(db.getHeight()) + index, _ := db.BestIndex(height) cs, _ := db.State(index.ID) numLeaves := cs.Elements.NumLeaves @@ -559,8 +563,13 @@ func (db *DBStore) SupplementTipTransaction(txn types.Transaction) (ts consensus // SupplementTipBlock implements Store. func (db *DBStore) SupplementTipBlock(b types.Block) (bs consensus.V1BlockSupplement) { + height := db.getHeight() + if height >= db.n.HardforkV2.RequireHeight { + return consensus.V1BlockSupplement{Transactions: make([]consensus.V1TransactionSupplement, len(b.Transactions))} + } + // get tip state, for proof-trimming - index, _ := db.BestIndex(db.getHeight()) + index, _ := db.BestIndex(height) cs, _ := db.State(index.ID) numLeaves := cs.Elements.NumLeaves