Skip to content

Commit 33b7b96

Browse files
committed
core: prohibit Conflicts attribute duplicate
Close #4289. Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
1 parent c41054f commit 33b7b96

2 files changed

Lines changed: 21 additions & 0 deletions

File tree

pkg/core/blockchain.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3019,6 +3019,7 @@ func (bc *Blockchain) CalculateAttributesFee(tx *transaction.Transaction) int64
30193019
}
30203020

30213021
func (bc *Blockchain) verifyTxAttributes(d *dao.Simple, tx *transaction.Transaction, isPartialTx bool) error {
3022+
var conflictsAttrs []transaction.Attribute
30223023
for i := range tx.Attributes {
30233024
switch attrType := tx.Attributes[i].Type; attrType {
30243025
case transaction.HighPriority:
@@ -3078,6 +3079,18 @@ func (bc *Blockchain) verifyTxAttributes(d *dao.Simple, tx *transaction.Transact
30783079
}
30793080
case transaction.ConflictsT:
30803081
conflicts := tx.Attributes[i].Value.(*transaction.Conflicts)
3082+
if conflictsAttrs == nil {
3083+
conflictsAttrs = tx.GetAttributes(transaction.ConflictsT)
3084+
}
3085+
var dup bool
3086+
for _, c := range conflictsAttrs {
3087+
if c.Value.(*transaction.Conflicts).Hash.Equals(conflicts.Hash) {
3088+
if dup {
3089+
return fmt.Errorf("%w: duplicate Conflicts attribute %s", ErrInvalidAttribute, conflicts.Hash.StringLE())
3090+
}
3091+
dup = true
3092+
}
3093+
}
30813094
// Only fully-qualified dao.ErrAlreadyExists error bothers us here, thus, we
30823095
// can safely omit the signers, current index and MTB arguments to HasTransaction call to improve performance a bit.
30833096
if err := bc.dao.HasTransaction(conflicts.Hash, nil, 0, 0); errors.Is(err, dao.ErrAlreadyExists) {

pkg/core/blockchain_neotest_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1977,6 +1977,14 @@ func TestBlockchain_VerifyTx(t *testing.T) {
19771977
require.NoError(t, err)
19781978
})
19791979
t.Run("enabled", func(t *testing.T) {
1980+
t.Run("duplicate", func(t *testing.T) {
1981+
conflict := random.Uint256()
1982+
tx := getConflictsTx(e, conflict, conflict)
1983+
1984+
err := bc.VerifyTx(tx)
1985+
require.ErrorIs(t, err, core.ErrInvalidAttribute)
1986+
require.ErrorContains(t, err, fmt.Sprintf("duplicate Conflicts attribute %s", conflict.StringLE()))
1987+
})
19801988
t.Run("dummy on-chain conflict", func(t *testing.T) {
19811989
t.Run("on-chain conflict signed by malicious party", func(t *testing.T) {
19821990
tx := newTestTx(t, h, testScript)

0 commit comments

Comments
 (0)