From dd258921bea32eaef3f4ece4d6f8c4a64bd26b7f Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 15 Apr 2024 15:51:35 +0100 Subject: [PATCH] fix BIC underflow and add test --- .../engine/accounts/accountsledger/manager.go | 3 +-- pkg/tests/accounts_test.go | 12 ++++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pkg/protocol/engine/accounts/accountsledger/manager.go b/pkg/protocol/engine/accounts/accountsledger/manager.go index 916a3a20f..7416434d5 100644 --- a/pkg/protocol/engine/accounts/accountsledger/manager.go +++ b/pkg/protocol/engine/accounts/accountsledger/manager.go @@ -531,12 +531,11 @@ func (m *Manager) commitAccountTree(slot iotago.SlotIndex, accountDiffChanges ma if diffChange.BICChange != 0 || !exists { // decay the credits to the current slot if the account exists - if exists { + if exists && accountData.Credits.Value > 0 { decayedPreviousCredits, err := m.apiProvider.APIForSlot(slot).ManaDecayProvider().DecayManaBySlots(iotago.Mana(accountData.Credits.Value), accountData.Credits.UpdateSlot, slot) if err != nil { return ierrors.Wrapf(err, "can't retrieve account, could not decay credits for account %s in slot %d", accountData.ID, slot) } - // update the account data diff taking into account the decay, the modified diff will be stored in the calling // ApplyDiff function to be able to properly rollback the account to a previous slot. diffChange.BICChange -= accountData.Credits.Value - iotago.BlockIssuanceCredits(decayedPreviousCredits) diff --git a/pkg/tests/accounts_test.go b/pkg/tests/accounts_test.go index dfe4cde40..8c32a9352 100644 --- a/pkg/tests/accounts_test.go +++ b/pkg/tests/accounts_test.go @@ -464,7 +464,10 @@ func Test_NegativeBIC_BlockIssuerLocked(t *testing.T) { iotago.SlotIndex(0), testsuite.GenesisTimeWithOffsetBySlots(iotago.SlotIndex(200), testsuite.DefaultSlotDurationInSeconds), testsuite.DefaultSlotDurationInSeconds, - testsuite.DefaultSlotsPerEpochExponent, + 3, + ), + iotago.WithLivenessOptions( + 10, 10, 2, 4, 5, ), ), ) @@ -588,6 +591,7 @@ func Test_NegativeBIC_BlockIssuerLocked(t *testing.T) { // Allot some mana to the locked account to unlock it. // The locked wallet 2 is preparing and signs the transaction, but it's issued by wallet 1 whose account is not locked. { + latestParents = ts.CommitUntilSlot(block3Slot+ts.API.TimeProvider().EpochDurationSlots(), ts.BlockID("block2.1")) allottedBIC := testPayloadCost tx1 := wallet2.AllotManaFromInputs("TX1", iotago.Allotments{&iotago.Allotment{ @@ -608,7 +612,7 @@ func Test_NegativeBIC_BlockIssuerLocked(t *testing.T) { ts.AssertAccountData(&accounts.AccountData{ ID: wallet1.BlockIssuer.AccountData.ID, - Credits: accounts.NewBlockIssuanceCredits(wallet1BIC, block3Slot), + Credits: accounts.NewBlockIssuanceCredits(wallet1BIC, block31.ID().Slot()), OutputID: wallet1OutputID, ExpirySlot: iotago.MaxSlotIndex, BlockIssuerKeys: wallet1.BlockIssuer.BlockIssuerKeys(), @@ -616,7 +620,7 @@ func Test_NegativeBIC_BlockIssuerLocked(t *testing.T) { ts.AssertAccountData(&accounts.AccountData{ ID: wallet2.BlockIssuer.AccountData.ID, - Credits: accounts.NewBlockIssuanceCredits(wallet2BIC, block3Slot), + Credits: accounts.NewBlockIssuanceCredits(wallet2BIC, block31.ID().Slot()), ExpirySlot: iotago.MaxSlotIndex, OutputID: wallet2OutputID, BlockIssuerKeys: wallet2.BlockIssuer.BlockIssuerKeys(), @@ -639,7 +643,7 @@ func Test_NegativeBIC_BlockIssuerLocked(t *testing.T) { ts.AssertAccountData(&accounts.AccountData{ ID: wallet1.BlockIssuer.AccountData.ID, - Credits: accounts.NewBlockIssuanceCredits(wallet1BIC, block3Slot), + Credits: accounts.NewBlockIssuanceCredits(wallet1BIC, ts.BlockID("block3.1").Slot()), OutputID: wallet1OutputID, ExpirySlot: iotago.MaxSlotIndex, BlockIssuerKeys: wallet1.BlockIssuer.BlockIssuerKeys(),