core: refactor out policy check for transaction
We were checking blocked accounts twice which is obviously excessive. We also have our accounts sorted, so we can rely on that in CheckPolicy(). It also doesn't make much sense to check MaxBlockSystemFee in Blockchain code, policy contract can handle that.
This commit is contained in:
parent
90180c6fb6
commit
d5a9d80c12
2 changed files with 17 additions and 26 deletions
|
@ -4,7 +4,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"sort"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
@ -1206,21 +1205,10 @@ func (bc *Blockchain) verifyTx(t *transaction.Transaction, block *block.Block) e
|
|||
if t.ValidUntilBlock <= height || t.ValidUntilBlock > height+transaction.MaxValidUntilBlockIncrement {
|
||||
return fmt.Errorf("transaction has expired. ValidUntilBlock = %d, current height = %d", t.ValidUntilBlock, height)
|
||||
}
|
||||
blockedAccounts, err := bc.contracts.Policy.GetBlockedAccountsInternal(bc.dao)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, signer := range t.Signers {
|
||||
i := sort.Search(len(blockedAccounts), func(i int) bool {
|
||||
return !blockedAccounts[i].Less(signer.Account)
|
||||
})
|
||||
if i != len(blockedAccounts) && blockedAccounts[i].Equals(signer.Account) {
|
||||
return fmt.Errorf("policy check failed: account %s is blocked", signer.Account.StringLE())
|
||||
}
|
||||
}
|
||||
maxBlockSystemFee := bc.contracts.Policy.GetMaxBlockSystemFeeInternal(bc.dao)
|
||||
if maxBlockSystemFee < t.SystemFee {
|
||||
return fmt.Errorf("policy check failed: transaction's fee shouldn't exceed maximum block system fee %d", maxBlockSystemFee)
|
||||
// Policying.
|
||||
if err := bc.contracts.Policy.CheckPolicy(bc.dao, t); err != nil {
|
||||
// Only one %w can be used.
|
||||
return fmt.Errorf("%w: %v", ErrPolicy, err)
|
||||
}
|
||||
balance := bc.GetUtilityTokenBalance(t.Sender())
|
||||
need := t.SystemFee + t.NetworkFee
|
||||
|
@ -1368,11 +1356,6 @@ func (bc *Blockchain) PoolTx(t *transaction.Transaction) error {
|
|||
if err := bc.verifyTx(t, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
// Policying.
|
||||
if err := bc.contracts.Policy.CheckPolicy(bc.dao, t); err != nil {
|
||||
// Only one %w can be used.
|
||||
return fmt.Errorf("%w: %v", ErrPolicy, err)
|
||||
}
|
||||
if err := bc.memPool.Add(t, bc); err != nil {
|
||||
switch {
|
||||
case errors.Is(err, mempool.ErrOOM):
|
||||
|
|
|
@ -509,19 +509,27 @@ func (p *Policy) checkValidators(ic *interop.Context) (bool, error) {
|
|||
return runtime.CheckHashedWitness(ic, prevBlock.NextConsensus)
|
||||
}
|
||||
|
||||
// CheckPolicy checks whether transaction's script hashes for verifying are
|
||||
// included into blocked accounts list.
|
||||
// CheckPolicy checks whether transaction conforms to current policy restrictions
|
||||
// like not being signed by blocked account or not exceeding block-level system
|
||||
// fee limit.
|
||||
func (p *Policy) CheckPolicy(d dao.DAO, tx *transaction.Transaction) error {
|
||||
ba, err := p.GetBlockedAccountsInternal(d)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get blocked accounts list: %w", err)
|
||||
}
|
||||
for _, acc := range ba {
|
||||
if len(ba) > 0 {
|
||||
for _, signer := range tx.Signers {
|
||||
if acc.Equals(signer.Account) {
|
||||
return fmt.Errorf("account %s is blocked", acc.StringLE())
|
||||
i := sort.Search(len(ba), func(i int) bool {
|
||||
return !ba[i].Less(signer.Account)
|
||||
})
|
||||
if i != len(ba) && ba[i].Equals(signer.Account) {
|
||||
return fmt.Errorf("account %s is blocked", signer.Account.StringLE())
|
||||
}
|
||||
}
|
||||
}
|
||||
maxBlockSystemFee := p.GetMaxBlockSystemFeeInternal(d)
|
||||
if maxBlockSystemFee < tx.SystemFee {
|
||||
return fmt.Errorf("transaction's fee can't exceed maximum block system fee %d", maxBlockSystemFee)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue