Merge pull request #1679 from nspcc-dev/fix/policysign

Check for committee witness in native contracts
This commit is contained in:
Roman Khimov 2021-01-21 15:42:36 +03:00 committed by GitHub
commit 8fad05c5bb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 104 additions and 96 deletions

View file

@ -91,17 +91,27 @@ func NewDeployTx(bc blockchainer.Blockchainer, name string, sender util.Uint160,
// SignTx signs provided transactions with validator keys.
func SignTx(bc blockchainer.Blockchainer, txs ...*transaction.Transaction) error {
signTxGeneric(bc, Sign, ownerScript, txs...)
return nil
}
// SignTxCommittee signs transactions by committee.
func SignTxCommittee(bc blockchainer.Blockchainer, txs ...*transaction.Transaction) error {
signTxGeneric(bc, SignCommittee, CommitteeVerificationScript(), txs...)
return nil
}
func signTxGeneric(bc blockchainer.Blockchainer, sign func([]byte) []byte, verif []byte, txs ...*transaction.Transaction) {
for _, tx := range txs {
size := io.GetVarSize(tx)
netFee, sizeDelta := fee.Calculate(bc.GetPolicer().GetBaseExecFee(), ownerScript)
netFee, sizeDelta := fee.Calculate(bc.GetPolicer().GetBaseExecFee(), verif)
tx.NetworkFee += netFee
size += sizeDelta
tx.NetworkFee += int64(size) * bc.FeePerByte()
data := tx.GetSignedPart()
tx.Scripts = []transaction.Witness{{
InvocationScript: Sign(data),
VerificationScript: ownerScript,
InvocationScript: sign(data),
VerificationScript: verif,
}}
}
return nil
}

View file

@ -139,7 +139,7 @@ func TestAddBlockStateRoot(t *testing.T) {
tx := newNEP17Transfer(bc.contracts.NEO.Hash, neoOwner, util.Uint160{}, 1)
tx.ValidUntilBlock = bc.BlockHeight() + 1
addSigners(tx)
addSigners(neoOwner, tx)
require.NoError(t, testchain.SignTx(bc, tx))
lastBlock := bc.topBlock.Load().(*block.Block)
@ -198,7 +198,7 @@ func TestGetHeader(t *testing.T) {
bc := newTestChain(t)
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.ValidUntilBlock = bc.BlockHeight() + 1
addSigners(tx)
addSigners(neoOwner, tx)
assert.Nil(t, testchain.SignTx(bc, tx))
block := bc.newBlock(tx)
err := bc.AddBlock(block)
@ -293,7 +293,7 @@ func TestVerifyTx(t *testing.T) {
require.Equal(t, 1, len(aer))
require.Equal(t, aer[0].VMState, vm.HaltState)
res, err := invokeContractMethod(bc, 100000000, bc.contracts.Policy.Hash, "blockAccount", accs[1].PrivateKey().GetScriptHash().BytesBE())
res, err := invokeContractMethodGeneric(bc, 100000000, bc.contracts.Policy.Hash, "blockAccount", true, accs[1].PrivateKey().GetScriptHash().BytesBE())
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(true))
@ -1176,7 +1176,7 @@ func TestIsTxStillRelevant(t *testing.T) {
txDeploy, h, err := testchain.NewDeployTx(bc, "TestVerify", neoOwner, strings.NewReader(src))
require.NoError(t, err)
txDeploy.ValidUntilBlock = bc.BlockHeight() + 1
addSigners(txDeploy)
addSigners(neoOwner, txDeploy)
require.NoError(t, testchain.SignTx(bc, txDeploy))
require.NoError(t, bc.AddBlock(bc.newBlock(txDeploy)))

View file

@ -400,10 +400,10 @@ func newDeployTx(t *testing.T, bc *Blockchain, sender util.Uint160, name, ctrNam
return tx, h
}
func addSigners(txs ...*transaction.Transaction) {
func addSigners(sender util.Uint160, txs ...*transaction.Transaction) {
for _, tx := range txs {
tx.Signers = []transaction.Signer{{
Account: neoOwner,
Account: sender,
Scopes: transaction.CalledByEntry,
AllowedContracts: nil,
AllowedGroups: nil,
@ -428,8 +428,8 @@ func addNetworkFee(bc *Blockchain, tx *transaction.Transaction, sender *wallet.A
return nil
}
func prepareContractMethodInvoke(chain *Blockchain, sysfee int64,
hash util.Uint160, method string, args ...interface{}) (*transaction.Transaction, error) {
func prepareContractMethodInvokeGeneric(chain *Blockchain, sysfee int64,
hash util.Uint160, method string, isCommittee bool, args ...interface{}) (*transaction.Transaction, error) {
w := io.NewBufBinWriter()
emit.AppCall(w.BinWriter, hash, method, callflag.All, args...)
if w.Err != nil {
@ -438,14 +438,26 @@ func prepareContractMethodInvoke(chain *Blockchain, sysfee int64,
script := w.Bytes()
tx := transaction.New(chain.GetConfig().Magic, script, sysfee)
tx.ValidUntilBlock = chain.blockHeight + 1
addSigners(tx)
err := testchain.SignTx(chain, tx)
var err error
if isCommittee {
addSigners(testchain.CommitteeScriptHash(), tx)
err = testchain.SignTxCommittee(chain, tx)
} else {
addSigners(neoOwner, tx)
err = testchain.SignTx(chain, tx)
}
if err != nil {
return nil, err
}
return tx, nil
}
func prepareContractMethodInvoke(chain *Blockchain, sysfee int64,
hash util.Uint160, method string, args ...interface{}) (*transaction.Transaction, error) {
return prepareContractMethodInvokeGeneric(chain, sysfee, hash,
method, false, args...)
}
func persistBlock(chain *Blockchain, txs ...*transaction.Transaction) ([]*state.AppExecResult, error) {
b := chain.newBlock(txs...)
err := chain.AddBlock(b)
@ -465,7 +477,13 @@ func persistBlock(chain *Blockchain, txs ...*transaction.Transaction) ([]*state.
}
func invokeContractMethod(chain *Blockchain, sysfee int64, hash util.Uint160, method string, args ...interface{}) (*state.AppExecResult, error) {
tx, err := prepareContractMethodInvoke(chain, sysfee, hash, method, args...)
return invokeContractMethodGeneric(chain, sysfee, hash, method, false, args...)
}
func invokeContractMethodGeneric(chain *Blockchain, sysfee int64, hash util.Uint160, method string,
isCommittee bool, args ...interface{}) (*state.AppExecResult, error) {
tx, err := prepareContractMethodInvokeGeneric(chain, sysfee, hash,
method, isCommittee, args...)
if err != nil {
return nil, err
}
@ -512,7 +530,7 @@ func transferTokenFromMultisigAccount(t *testing.T, chain *Blockchain, to, token
transferTx := newNEP17Transfer(tokenHash, testchain.MultisigScriptHash(), to, amount, additionalArgs...)
transferTx.SystemFee = 100000000
transferTx.ValidUntilBlock = chain.BlockHeight() + 1
addSigners(transferTx)
addSigners(neoOwner, transferTx)
require.NoError(t, testchain.SignTx(chain, transferTx))
b := chain.newBlock(transferTx)
require.NoError(t, chain.AddBlock(b))

View file

@ -63,6 +63,7 @@ func NewContracts(p2pSigExtensionsEnabled bool) *Contracts {
neo := newNEO()
neo.GAS = gas
gas.NEO = neo
mgmt.NEO = neo
cs.GAS = gas
cs.NEO = neo
@ -70,6 +71,7 @@ func NewContracts(p2pSigExtensionsEnabled bool) *Contracts {
cs.Contracts = append(cs.Contracts, gas)
policy := newPolicy()
policy.NEO = neo
cs.Policy = policy
cs.Contracts = append(cs.Contracts, policy)
@ -88,6 +90,7 @@ func NewContracts(p2pSigExtensionsEnabled bool) *Contracts {
if p2pSigExtensionsEnabled {
notary := newNotary()
notary.GAS = gas
notary.NEO = neo
notary.Desig = desig
cs.Notary = notary
cs.Contracts = append(cs.Contracts, notary)

View file

@ -27,6 +27,7 @@ import (
// Management is contract-managing native contract.
type Management struct {
interop.ContractMD
NEO *NEO
mtx sync.RWMutex
contracts map[util.Uint160]*state.Contract
@ -367,14 +368,10 @@ func (m *Management) setMinimumDeploymentFee(ic *interop.Context, args []stackit
if value < 0 {
panic(fmt.Errorf("MinimumDeploymentFee cannot be negative"))
}
ok, err := checkValidators(ic)
if err != nil {
panic(err)
}
if !ok {
if !m.NEO.checkCommittee(ic) {
return stackitem.NewBool(false)
}
err = setUint32WithKey(m.ContractID, ic.DAO, keyMinimumDeploymentFee, value)
err := setUint32WithKey(m.ContractID, ic.DAO, keyMinimumDeploymentFee, value)
if err != nil {
panic(err)
}

View file

@ -462,6 +462,14 @@ func (n *NEO) GetCommitteeAddress() util.Uint160 {
return n.committeeHash.Load().(util.Uint160)
}
func (n *NEO) checkCommittee(ic *interop.Context) bool {
ok, err := runtime.CheckHashedWitness(ic, n.GetCommitteeAddress())
if err != nil {
panic(err)
}
return ok
}
func (n *NEO) setGASPerBlock(ic *interop.Context, args []stackitem.Item) stackitem.Item {
gas := toBigInt(args[0])
ok, err := n.SetGASPerBlock(ic, ic.Block.Index+1, gas)

View file

@ -27,6 +27,7 @@ import (
type Notary struct {
interop.ContractMD
GAS *GAS
NEO *NEO
Desig *Designate
lock sync.RWMutex
@ -387,16 +388,12 @@ func (n *Notary) setMaxNotValidBeforeDelta(ic *interop.Context, args []stackitem
if value > transaction.MaxValidUntilBlockIncrement/2 || value < uint32(ic.Chain.GetConfig().ValidatorsCount) {
panic(fmt.Errorf("MaxNotValidBeforeDelta cannot be more than %d or less than %d", transaction.MaxValidUntilBlockIncrement/2, ic.Chain.GetConfig().ValidatorsCount))
}
ok, err := checkValidators(ic)
if err != nil {
panic(fmt.Errorf("failed to check committee signature: %w", err))
}
if !ok {
if !n.NEO.checkCommittee(ic) {
return stackitem.NewBool(false)
}
n.lock.Lock()
defer n.lock.Unlock()
err = setUint32WithKey(n.ContractID, ic.DAO, maxNotValidBeforeDeltaKey, value)
err := setUint32WithKey(n.ContractID, ic.DAO, maxNotValidBeforeDeltaKey, value)
if err != nil {
panic(fmt.Errorf("failed to put value into the storage: %w", err))
}

View file

@ -62,6 +62,7 @@ var (
// Policy represents Policy native contract.
type Policy struct {
interop.ContractMD
NEO *NEO
lock sync.RWMutex
// isValid defies whether cached values were changed during the current
// consensus iteration. If false, these values will be updated after
@ -307,15 +308,12 @@ func (p *Policy) setExecFeeFactor(ic *interop.Context, args []stackitem.Item) st
if value <= 0 || maxExecFeeFactor < value {
panic(fmt.Errorf("ExecFeeFactor must be between 0 and %d", maxExecFeeFactor))
}
ok, err := checkValidators(ic)
if err != nil {
panic(err)
} else if !ok {
if !p.NEO.checkCommittee(ic) {
return stackitem.NewBool(false)
}
p.lock.Lock()
defer p.lock.Unlock()
err = setUint32WithKey(p.ContractID, ic.DAO, execFeeFactorKey, uint32(value))
err := setUint32WithKey(p.ContractID, ic.DAO, execFeeFactorKey, uint32(value))
if err != nil {
panic(err)
}
@ -366,15 +364,12 @@ func (p *Policy) setStoragePrice(ic *interop.Context, args []stackitem.Item) sta
if value <= 0 || maxStoragePrice < value {
panic(fmt.Errorf("StoragePrice must be between 0 and %d", maxStoragePrice))
}
ok, err := checkValidators(ic)
if err != nil {
panic(err)
} else if !ok {
if !p.NEO.checkCommittee(ic) {
return stackitem.NewBool(false)
}
p.lock.Lock()
defer p.lock.Unlock()
err = setUint32WithKey(p.ContractID, ic.DAO, storagePriceKey, uint32(value))
err := setUint32WithKey(p.ContractID, ic.DAO, storagePriceKey, uint32(value))
if err != nil {
panic(err)
}
@ -389,16 +384,12 @@ func (p *Policy) setMaxTransactionsPerBlock(ic *interop.Context, args []stackite
if value > block.MaxTransactionsPerBlock {
panic(fmt.Errorf("MaxTransactionsPerBlock cannot exceed the maximum allowed transactions per block = %d", block.MaxTransactionsPerBlock))
}
ok, err := checkValidators(ic)
if err != nil {
panic(err)
}
if !ok {
if !p.NEO.checkCommittee(ic) {
return stackitem.NewBool(false)
}
p.lock.Lock()
defer p.lock.Unlock()
err = setUint32WithKey(p.ContractID, ic.DAO, maxTransactionsPerBlockKey, value)
err := setUint32WithKey(p.ContractID, ic.DAO, maxTransactionsPerBlockKey, value)
if err != nil {
panic(err)
}
@ -412,16 +403,12 @@ func (p *Policy) setMaxBlockSize(ic *interop.Context, args []stackitem.Item) sta
if value > payload.MaxSize {
panic(fmt.Errorf("MaxBlockSize cannot be more than the maximum payload size = %d", payload.MaxSize))
}
ok, err := checkValidators(ic)
if err != nil {
panic(err)
}
if !ok {
if !p.NEO.checkCommittee(ic) {
return stackitem.NewBool(false)
}
p.lock.Lock()
defer p.lock.Unlock()
err = setUint32WithKey(p.ContractID, ic.DAO, maxBlockSizeKey, value)
err := setUint32WithKey(p.ContractID, ic.DAO, maxBlockSizeKey, value)
if err != nil {
panic(err)
}
@ -435,16 +422,12 @@ func (p *Policy) setFeePerByte(ic *interop.Context, args []stackitem.Item) stack
if value < 0 || value > maxFeePerByte {
panic(fmt.Errorf("FeePerByte shouldn't be negative or greater than %d", maxFeePerByte))
}
ok, err := checkValidators(ic)
if err != nil {
panic(err)
}
if !ok {
if !p.NEO.checkCommittee(ic) {
return stackitem.NewBool(false)
}
p.lock.Lock()
defer p.lock.Unlock()
err = setInt64WithKey(p.ContractID, ic.DAO, feePerByteKey, value)
err := setInt64WithKey(p.ContractID, ic.DAO, feePerByteKey, value)
if err != nil {
panic(err)
}
@ -458,16 +441,12 @@ func (p *Policy) setMaxBlockSystemFee(ic *interop.Context, args []stackitem.Item
if value <= minBlockSystemFee {
panic(fmt.Errorf("MaxBlockSystemFee cannot be less then %d", minBlockSystemFee))
}
ok, err := checkValidators(ic)
if err != nil {
panic(err)
}
if !ok {
if !p.NEO.checkCommittee(ic) {
return stackitem.NewBool(false)
}
p.lock.Lock()
defer p.lock.Unlock()
err = setInt64WithKey(p.ContractID, ic.DAO, maxBlockSystemFeeKey, value)
err := setInt64WithKey(p.ContractID, ic.DAO, maxBlockSystemFeeKey, value)
if err != nil {
panic(err)
}
@ -478,11 +457,7 @@ func (p *Policy) setMaxBlockSystemFee(ic *interop.Context, args []stackitem.Item
// blockAccount is Policy contract method and adds given account hash to the list
// of blocked accounts.
func (p *Policy) blockAccount(ic *interop.Context, args []stackitem.Item) stackitem.Item {
ok, err := checkValidators(ic)
if err != nil {
panic(err)
}
if !ok {
if !p.NEO.checkCommittee(ic) {
return stackitem.NewBool(false)
}
hash := toUint160(args[0])
@ -492,7 +467,7 @@ func (p *Policy) blockAccount(ic *interop.Context, args []stackitem.Item) stacki
key := append([]byte{blockedAccountPrefix}, hash.BytesBE()...)
p.lock.Lock()
defer p.lock.Unlock()
err = ic.DAO.PutStorageItem(p.ContractID, key, &state.StorageItem{
err := ic.DAO.PutStorageItem(p.ContractID, key, &state.StorageItem{
Value: []byte{0x01},
})
if err != nil {
@ -505,11 +480,7 @@ func (p *Policy) blockAccount(ic *interop.Context, args []stackitem.Item) stacki
// unblockAccount is Policy contract method and removes given account hash from
// the list of blocked accounts.
func (p *Policy) unblockAccount(ic *interop.Context, args []stackitem.Item) stackitem.Item {
ok, err := checkValidators(ic)
if err != nil {
panic(err)
}
if !ok {
if !p.NEO.checkCommittee(ic) {
return stackitem.NewBool(false)
}
hash := toUint160(args[0])
@ -519,7 +490,7 @@ func (p *Policy) unblockAccount(ic *interop.Context, args []stackitem.Item) stac
key := append([]byte{blockedAccountPrefix}, hash.BytesBE()...)
p.lock.Lock()
defer p.lock.Unlock()
err = ic.DAO.DeleteStorageItem(p.ContractID, key)
err := ic.DAO.DeleteStorageItem(p.ContractID, key)
if err != nil {
panic(err)
}

View file

@ -4,8 +4,6 @@ import (
"encoding/binary"
"github.com/nspcc-dev/neo-go/pkg/core/dao"
"github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/storage"
"github.com/nspcc-dev/neo-go/pkg/io"
@ -65,14 +63,6 @@ func setUint32WithKey(id int32, dao dao.DAO, key []byte, value uint32) error {
return dao.PutStorageItem(id, key, si)
}
func checkValidators(ic *interop.Context) (bool, error) {
prevBlock, err := ic.Chain.GetBlock(ic.Block.PrevHash)
if err != nil {
return false, err
}
return runtime.CheckHashedWitness(ic, prevBlock.NextConsensus)
}
// makeUint160Key creates a key from account script hash.
func makeUint160Key(prefix byte, h util.Uint160) []byte {
k := make([]byte, util.Uint160Size+1)

View file

@ -30,6 +30,8 @@ func TestNotaryContractPipeline(t *testing.T) {
gasHash := chain.contracts.GAS.Hash
depositLock := 100
transferFundsToCommittee(t, chain)
// check Notary contract has no GAS on the account
checkBalanceOf(t, chain, notaryHash, 0)
@ -329,6 +331,8 @@ func TestMaxNotValidBeforeDelta(t *testing.T) {
defer chain.Close()
notaryHash := chain.contracts.Notary.Hash
transferFundsToCommittee(t, chain)
t.Run("get, internal method", func(t *testing.T) {
n := chain.contracts.Notary.GetMaxNotValidBeforeDelta(chain.dao)
require.Equal(t, 140, int(n))
@ -342,7 +346,7 @@ func TestMaxNotValidBeforeDelta(t *testing.T) {
})
t.Run("set", func(t *testing.T) {
res, err := invokeContractMethod(chain, 100000000, notaryHash, "setMaxNotValidBeforeDelta", bigint.ToBytes(big.NewInt(150)))
res, err := invokeContractMethodGeneric(chain, 100000000, notaryHash, "setMaxNotValidBeforeDelta", true, bigint.ToBytes(big.NewInt(150)))
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(true))
n := chain.contracts.Notary.GetMaxNotValidBeforeDelta(chain.dao)
@ -350,13 +354,13 @@ func TestMaxNotValidBeforeDelta(t *testing.T) {
})
t.Run("set, too big value", func(t *testing.T) {
res, err := invokeContractMethod(chain, 100000000, notaryHash, "setMaxNotValidBeforeDelta", bigint.ToBytes(big.NewInt(transaction.MaxValidUntilBlockIncrement/2+1)))
res, err := invokeContractMethodGeneric(chain, 100000000, notaryHash, "setMaxNotValidBeforeDelta", true, bigint.ToBytes(big.NewInt(transaction.MaxValidUntilBlockIncrement/2+1)))
require.NoError(t, err)
checkFAULTState(t, res)
})
t.Run("set, too small value", func(t *testing.T) {
res, err := invokeContractMethod(chain, 100000000, notaryHash, "setMaxNotValidBeforeDelta", bigint.ToBytes(big.NewInt(int64(chain.GetConfig().ValidatorsCount-1))))
res, err := invokeContractMethodGeneric(chain, 100000000, notaryHash, "setMaxNotValidBeforeDelta", true, bigint.ToBytes(big.NewInt(int64(chain.GetConfig().ValidatorsCount-1))))
require.NoError(t, err)
checkFAULTState(t, res)
})

View file

@ -4,6 +4,7 @@ import (
"testing"
"github.com/nspcc-dev/neo-go/internal/random"
"github.com/nspcc-dev/neo-go/internal/testchain"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/core/native"
@ -14,10 +15,16 @@ import (
"github.com/stretchr/testify/require"
)
func transferFundsToCommittee(t *testing.T, chain *Blockchain) {
transferTokenFromMultisigAccount(t, chain, testchain.CommitteeScriptHash(),
chain.contracts.GAS.Hash, 100_00000000)
}
func testGetSet(t *testing.T, chain *Blockchain, hash util.Uint160, name string, defaultValue, minValue, maxValue int64) {
getName := "get" + name
setName := "set" + name
transferFundsToCommittee(t, chain)
t.Run("set, not signed by committee", func(t *testing.T) {
signer, err := wallet.NewAccount()
require.NoError(t, err)
@ -33,14 +40,14 @@ func testGetSet(t *testing.T, chain *Blockchain, hash util.Uint160, name string,
})
t.Run("set, too small value", func(t *testing.T) {
res, err := invokeContractMethod(chain, 100000000, hash, setName, minValue-1)
res, err := invokeContractMethodGeneric(chain, 100000000, hash, setName, true, minValue-1)
require.NoError(t, err)
checkFAULTState(t, res)
})
if maxValue != 0 {
t.Run("set, too large value", func(t *testing.T) {
res, err := invokeContractMethod(chain, 100000000, hash, setName, maxValue+1)
res, err := invokeContractMethodGeneric(chain, 100000000, hash, setName, true, maxValue+1)
require.NoError(t, err)
checkFAULTState(t, res)
})
@ -48,7 +55,7 @@ func testGetSet(t *testing.T, chain *Blockchain, hash util.Uint160, name string,
t.Run("set, success", func(t *testing.T) {
// Set and get in the same block.
txSet, err := prepareContractMethodInvoke(chain, 100000000, hash, setName, defaultValue+1)
txSet, err := prepareContractMethodInvokeGeneric(chain, 100000000, hash, setName, true, defaultValue+1)
require.NoError(t, err)
txGet1, err := prepareContractMethodInvoke(chain, 100000000, hash, getName)
require.NoError(t, err)
@ -144,6 +151,9 @@ func TestBlockedAccounts(t *testing.T) {
account := util.Uint160{1, 2, 3}
policyHash := chain.contracts.Policy.Metadata().Hash
transferTokenFromMultisigAccount(t, chain, testchain.CommitteeScriptHash(),
chain.contracts.GAS.Hash, 100_00000000)
t.Run("isBlocked, internal method", func(t *testing.T) {
isBlocked := chain.contracts.Policy.IsBlockedInternal(chain.dao, random.Uint160())
require.Equal(t, false, isBlocked)
@ -157,7 +167,7 @@ func TestBlockedAccounts(t *testing.T) {
})
t.Run("block-unblock account", func(t *testing.T) {
res, err := invokeContractMethod(chain, 100000000, policyHash, "blockAccount", account.BytesBE())
res, err := invokeContractMethodGeneric(chain, 100000000, policyHash, "blockAccount", true, account.BytesBE())
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(true))
@ -165,7 +175,7 @@ func TestBlockedAccounts(t *testing.T) {
require.Equal(t, isBlocked, true)
require.NoError(t, chain.persist())
res, err = invokeContractMethod(chain, 100000000, policyHash, "unblockAccount", account.BytesBE())
res, err = invokeContractMethodGeneric(chain, 100000000, policyHash, "unblockAccount", true, account.BytesBE())
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(true))
@ -176,25 +186,25 @@ func TestBlockedAccounts(t *testing.T) {
t.Run("double-block", func(t *testing.T) {
// block
res, err := invokeContractMethod(chain, 100000000, policyHash, "blockAccount", account.BytesBE())
res, err := invokeContractMethodGeneric(chain, 100000000, policyHash, "blockAccount", true, account.BytesBE())
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(true))
require.NoError(t, chain.persist())
// double-block should fail
res, err = invokeContractMethod(chain, 100000000, policyHash, "blockAccount", account.BytesBE())
res, err = invokeContractMethodGeneric(chain, 100000000, policyHash, "blockAccount", true, account.BytesBE())
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(false))
require.NoError(t, chain.persist())
// unblock
res, err = invokeContractMethod(chain, 100000000, policyHash, "unblockAccount", account.BytesBE())
res, err = invokeContractMethodGeneric(chain, 100000000, policyHash, "unblockAccount", true, account.BytesBE())
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(true))
require.NoError(t, chain.persist())
// unblock the same account should fail as we don't have it blocked
res, err = invokeContractMethod(chain, 100000000, policyHash, "unblockAccount", account.BytesBE())
res, err = invokeContractMethodGeneric(chain, 100000000, policyHash, "unblockAccount", true, account.BytesBE())
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(false))
require.NoError(t, chain.persist())