rpc: refactor TestCalculateNetworkFee

We need to ensure that we don't add extra network fee during
calculation.
This commit is contained in:
Anna Shaleva 2021-03-25 11:38:15 +03:00
parent 44c87a460c
commit d2a81daf57

View file

@ -71,6 +71,7 @@ func TestAddNetworkFee(t *testing.T) {
defer chain.Close() defer chain.Close()
defer rpcSrv.Shutdown() defer rpcSrv.Shutdown()
const extraFee = 10 const extraFee = 10
var nonce uint32
c, err := client.New(context.Background(), httpSrv.URL, client.Options{}) c, err := client.New(context.Background(), httpSrv.URL, client.Options{})
require.NoError(t, err) require.NoError(t, err)
@ -98,41 +99,105 @@ func TestAddNetworkFee(t *testing.T) {
require.Error(t, c.AddNetworkFee(tx, extraFee, accs[0], accs[1])) require.Error(t, c.AddNetworkFee(tx, extraFee, accs[0], accs[1]))
}) })
t.Run("Simple", func(t *testing.T) { t.Run("Simple", func(t *testing.T) {
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) acc0 := wallet.NewAccountFromPrivateKey(testchain.PrivateKeyByID(0))
accs := getAccounts(t, 1) check := func(t *testing.T, extraFee int64) {
tx.Signers = []transaction.Signer{{ tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
Account: accs[0].PrivateKey().GetScriptHash(), tx.ValidUntilBlock = 20
Scopes: transaction.CalledByEntry, tx.Signers = []transaction.Signer{{
}} Account: acc0.PrivateKey().GetScriptHash(),
require.NoError(t, c.AddNetworkFee(tx, 10, accs[0])) Scopes: transaction.CalledByEntry,
require.NoError(t, accs[0].SignTx(testchain.Network(), tx)) }}
cFee, _ := fee.Calculate(chain.GetBaseExecFee(), accs[0].Contract.Script) tx.Nonce = nonce
require.Equal(t, int64(io.GetVarSize(tx))*feePerByte+cFee+extraFee, tx.NetworkFee) nonce++
require.NoError(t, c.AddNetworkFee(tx, extraFee, acc0))
actual := tx.NetworkFee
require.NoError(t, acc0.SignTx(testchain.Network(), tx))
cFee, _ := fee.Calculate(chain.GetBaseExecFee(), acc0.Contract.Script)
expected := int64(io.GetVarSize(tx))*feePerByte + cFee + extraFee
require.Equal(t, expected, actual)
err := chain.VerifyTx(tx)
if extraFee < 0 {
require.Error(t, err)
} else {
require.NoError(t, err)
}
}
t.Run("with extra fee", func(t *testing.T) {
// check that calculated network fee with extra value is enough
check(t, extraFee)
})
t.Run("without extra fee", func(t *testing.T) {
// check that calculated network fee without extra value is enough
check(t, 0)
})
t.Run("exactFee-1", func(t *testing.T) {
// check that we don't add unexpected extra GAS
check(t, -1)
})
}) })
t.Run("Multi", func(t *testing.T) { t.Run("Multi", func(t *testing.T) {
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) acc0 := wallet.NewAccountFromPrivateKey(testchain.PrivateKeyByID(0))
accs := getAccounts(t, 4) acc1 := wallet.NewAccountFromPrivateKey(testchain.PrivateKeyByID(0))
pubs := keys.PublicKeys{accs[1].PrivateKey().PublicKey(), accs[2].PrivateKey().PublicKey(), accs[3].PrivateKey().PublicKey()} acc1.ConvertMultisig(3, keys.PublicKeys{
require.NoError(t, accs[1].ConvertMultisig(2, pubs)) testchain.PrivateKeyByID(0).PublicKey(),
require.NoError(t, accs[2].ConvertMultisig(2, pubs)) testchain.PrivateKeyByID(1).PublicKey(),
tx.Signers = []transaction.Signer{ testchain.PrivateKeyByID(2).PublicKey(),
{ testchain.PrivateKeyByID(3).PublicKey(),
Account: accs[0].PrivateKey().GetScriptHash(), })
Scopes: transaction.CalledByEntry, check := func(t *testing.T, extraFee int64) {
}, tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
{ tx.ValidUntilBlock = 20
Account: hash.Hash160(accs[1].Contract.Script), tx.Signers = []transaction.Signer{
Scopes: transaction.Global, {
}, Account: acc0.PrivateKey().GetScriptHash(),
Scopes: transaction.CalledByEntry,
},
{
Account: hash.Hash160(acc1.Contract.Script),
Scopes: transaction.Global,
},
}
tx.Nonce = nonce
nonce++
require.NoError(t, c.AddNetworkFee(tx, extraFee, acc0, acc1))
actual := tx.NetworkFee
require.NoError(t, acc0.SignTx(testchain.Network(), tx))
tx.Scripts = append(tx.Scripts, transaction.Witness{
InvocationScript: testchain.Sign(tx),
VerificationScript: acc1.Contract.Script,
})
cFee, _ := fee.Calculate(chain.GetBaseExecFee(), acc0.Contract.Script)
cFeeM, _ := fee.Calculate(chain.GetBaseExecFee(), acc1.Contract.Script)
expected := int64(io.GetVarSize(tx))*feePerByte + cFee + cFeeM + extraFee
require.Equal(t, expected, actual)
err := chain.VerifyTx(tx)
if extraFee < 0 {
require.Error(t, err)
} else {
require.NoError(t, err)
}
} }
require.NoError(t, c.AddNetworkFee(tx, extraFee, accs[0], accs[1]))
require.NoError(t, accs[0].SignTx(testchain.Network(), tx)) t.Run("with extra fee", func(t *testing.T) {
require.NoError(t, accs[1].SignTx(testchain.Network(), tx)) // check that calculated network fee with extra value is enough
require.NoError(t, accs[2].SignTx(testchain.Network(), tx)) check(t, extraFee)
cFee, _ := fee.Calculate(chain.GetBaseExecFee(), accs[0].Contract.Script) })
cFeeM, _ := fee.Calculate(chain.GetBaseExecFee(), accs[1].Contract.Script) t.Run("without extra fee", func(t *testing.T) {
require.Equal(t, int64(io.GetVarSize(tx))*feePerByte+cFee+cFeeM+extraFee, tx.NetworkFee) // check that calculated network fee without extra value is enough
check(t, 0)
})
t.Run("exactFee-1", func(t *testing.T) {
// check that we don't add unexpected extra GAS
check(t, -1)
})
}) })
t.Run("Contract", func(t *testing.T) { t.Run("Contract", func(t *testing.T) {
h, err := util.Uint160DecodeStringLE(verifyContractHash) h, err := util.Uint160DecodeStringLE(verifyContractHash)
@ -142,16 +207,16 @@ func TestAddNetworkFee(t *testing.T) {
acc1 := wallet.NewAccountFromPrivateKey(priv) // contract account acc1 := wallet.NewAccountFromPrivateKey(priv) // contract account
acc1.Contract.Deployed = true acc1.Contract.Deployed = true
acc1.Contract.Script, err = base64.StdEncoding.DecodeString(verifyContractAVM) acc1.Contract.Script, err = base64.StdEncoding.DecodeString(verifyContractAVM)
require.NoError(t, err)
newTx := func(t *testing.T) *transaction.Transaction { newTx := func(t *testing.T) *transaction.Transaction {
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
require.NoError(t, err)
tx.ValidUntilBlock = chain.BlockHeight() + 10 tx.ValidUntilBlock = chain.BlockHeight() + 10
return tx return tx
} }
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
completeTx := func(t *testing.T) *transaction.Transaction { check := func(t *testing.T, extraFee int64) {
tx := newTx(t) tx := newTx(t)
tx.Signers = []transaction.Signer{ tx.Signers = []transaction.Signer{
{ {
@ -164,28 +229,28 @@ func TestAddNetworkFee(t *testing.T) {
}, },
} }
require.NoError(t, c.AddNetworkFee(tx, extraFee, acc0, acc1)) require.NoError(t, c.AddNetworkFee(tx, extraFee, acc0, acc1))
return tx require.NoError(t, acc0.SignTx(testchain.Network(), tx))
tx.Scripts = append(tx.Scripts, transaction.Witness{})
err = chain.VerifyTx(tx)
if extraFee < 0 {
require.Error(t, err)
} else {
require.NoError(t, err)
}
} }
// check that network fee with extra value is enough t.Run("with extra fee", func(t *testing.T) {
tx1 := completeTx(t) // check that calculated network fee with extra value is enough
require.NoError(t, acc0.SignTx(testchain.Network(), tx1)) check(t, extraFee)
tx1.Scripts = append(tx1.Scripts, transaction.Witness{}) })
require.NoError(t, chain.VerifyTx(tx1)) t.Run("without extra fee", func(t *testing.T) {
// check that calculated network fee without extra value is enough
// check that network fee without extra value is enough check(t, 0)
tx2 := completeTx(t) })
tx2.NetworkFee -= extraFee t.Run("exactFee-1", func(t *testing.T) {
require.NoError(t, acc0.SignTx(testchain.Network(), tx2)) // check that we don't add unexpected extra GAS
tx2.Scripts = append(tx2.Scripts, transaction.Witness{}) check(t, -1)
require.NoError(t, chain.VerifyTx(tx2)) })
// check that we don't add unexpected extra GAS
tx3 := completeTx(t)
tx3.NetworkFee -= extraFee + 1
require.NoError(t, acc0.SignTx(testchain.Network(), tx3))
tx3.Scripts = append(tx3.Scripts, transaction.Witness{})
require.Error(t, chain.VerifyTx(tx3))
}) })
t.Run("Invalid", func(t *testing.T) { t.Run("Invalid", func(t *testing.T) {
tx := newTx(t) tx := newTx(t)