Skip to content

Commit 7c04d76

Browse files
committed
refactored operationTx builder
1 parent 39cae3c commit 7c04d76

File tree

4 files changed

+207
-261
lines changed

4 files changed

+207
-261
lines changed

vms/avm/service.go

Lines changed: 41 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,32 +1393,6 @@ func (s *Service) buildMint(args *MintArgs) (*txs.Tx, ids.ShortID, error) {
13931393
return nil, ids.ShortEmpty, err
13941394
}
13951395

1396-
amountsSpent, ins, keys, err := s.vm.Spend(
1397-
feeUTXOs,
1398-
feeKc,
1399-
map[ids.ID]uint64{
1400-
s.vm.feeAssetID: s.vm.TxFee,
1401-
},
1402-
)
1403-
if err != nil {
1404-
return nil, ids.ShortEmpty, err
1405-
}
1406-
1407-
outs := []*avax.TransferableOutput{}
1408-
if amountSpent := amountsSpent[s.vm.feeAssetID]; amountSpent > s.vm.TxFee {
1409-
outs = append(outs, &avax.TransferableOutput{
1410-
Asset: avax.Asset{ID: s.vm.feeAssetID},
1411-
Out: &secp256k1fx.TransferOutput{
1412-
Amt: amountSpent - s.vm.TxFee,
1413-
OutputOwners: secp256k1fx.OutputOwners{
1414-
Locktime: 0,
1415-
Threshold: 1,
1416-
Addrs: []ids.ShortID{changeAddr},
1417-
},
1418-
},
1419-
})
1420-
}
1421-
14221396
// Get all UTXOs/keys for the user
14231397
utxos, kc, err := s.vm.LoadUser(args.Username, args.Password, nil)
14241398
if err != nil {
@@ -1436,18 +1410,44 @@ func (s *Service) buildMint(args *MintArgs) (*txs.Tx, ids.ShortID, error) {
14361410
if err != nil {
14371411
return nil, ids.ShortEmpty, err
14381412
}
1439-
keys = append(keys, opKeys...)
14401413

1441-
tx := &txs.Tx{Unsigned: &txs.OperationTx{
1414+
return buildOperation(s.vm, ops, opKeys, feeUTXOs, feeKc, changeAddr)
1415+
}
1416+
1417+
func buildOperation(
1418+
vm *VM,
1419+
ops []*txs.Operation,
1420+
opsKeys [][]*secp256k1.PrivateKey,
1421+
utxos []*avax.UTXO,
1422+
kc *secp256k1fx.Keychain,
1423+
changeAddr ids.ShortID,
1424+
) (*txs.Tx, ids.ShortID, error) {
1425+
uTx := &txs.OperationTx{
14421426
BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{
1443-
NetworkID: s.vm.ctx.NetworkID,
1444-
BlockchainID: s.vm.ctx.ChainID,
1445-
Outs: outs,
1446-
Ins: ins,
1427+
NetworkID: vm.ctx.NetworkID,
1428+
BlockchainID: vm.ctx.ChainID,
14471429
}},
14481430
Ops: ops,
1449-
}}
1450-
return tx, changeAddr, tx.SignSECP256K1Fx(s.vm.parser.Codec(), keys)
1431+
}
1432+
1433+
toBurn := map[ids.ID]uint64{
1434+
vm.feeAssetID: vm.TxFee,
1435+
}
1436+
ins, outs, keys, err := vm.NewSpend(
1437+
utxos,
1438+
kc,
1439+
toBurn,
1440+
changeAddr,
1441+
)
1442+
if err != nil {
1443+
return nil, ids.ShortEmpty, err
1444+
}
1445+
1446+
uTx.Ins = ins
1447+
uTx.Outs = outs
1448+
tx := &txs.Tx{Unsigned: uTx}
1449+
keys = append(keys, opsKeys...)
1450+
return tx, changeAddr, tx.SignSECP256K1Fx(vm.parser.Codec(), keys)
14511451
}
14521452

14531453
// SendNFTArgs are arguments for passing into SendNFT requests
@@ -1518,32 +1518,6 @@ func (s *Service) buildSendNFT(args *SendNFTArgs) (*txs.Tx, ids.ShortID, error)
15181518
return nil, ids.ShortEmpty, err
15191519
}
15201520

1521-
amountsSpent, ins, secpKeys, err := s.vm.Spend(
1522-
utxos,
1523-
kc,
1524-
map[ids.ID]uint64{
1525-
s.vm.feeAssetID: s.vm.TxFee,
1526-
},
1527-
)
1528-
if err != nil {
1529-
return nil, ids.ShortEmpty, err
1530-
}
1531-
1532-
outs := []*avax.TransferableOutput{}
1533-
if amountSpent := amountsSpent[s.vm.feeAssetID]; amountSpent > s.vm.TxFee {
1534-
outs = append(outs, &avax.TransferableOutput{
1535-
Asset: avax.Asset{ID: s.vm.feeAssetID},
1536-
Out: &secp256k1fx.TransferOutput{
1537-
Amt: amountSpent - s.vm.TxFee,
1538-
OutputOwners: secp256k1fx.OutputOwners{
1539-
Locktime: 0,
1540-
Threshold: 1,
1541-
Addrs: []ids.ShortID{changeAddr},
1542-
},
1543-
},
1544-
})
1545-
}
1546-
15471521
ops, nftKeys, err := s.vm.SpendNFT(
15481522
utxos,
15491523
kc,
@@ -1555,21 +1529,12 @@ func (s *Service) buildSendNFT(args *SendNFTArgs) (*txs.Tx, ids.ShortID, error)
15551529
return nil, ids.ShortEmpty, err
15561530
}
15571531

1558-
tx := &txs.Tx{Unsigned: &txs.OperationTx{
1559-
BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{
1560-
NetworkID: s.vm.ctx.NetworkID,
1561-
BlockchainID: s.vm.ctx.ChainID,
1562-
Outs: outs,
1563-
Ins: ins,
1564-
}},
1565-
Ops: ops,
1566-
}}
1567-
1568-
codec := s.vm.parser.Codec()
1569-
if err := tx.SignSECP256K1Fx(codec, secpKeys); err != nil {
1532+
tx, _, err := buildOperation(s.vm, ops, nil, utxos, kc, changeAddr)
1533+
if err != nil {
15701534
return nil, ids.ShortEmpty, err
15711535
}
1572-
return tx, changeAddr, tx.SignNFTFx(codec, nftKeys)
1536+
1537+
return tx, changeAddr, tx.SignNFTFx(s.vm.parser.Codec(), nftKeys)
15731538
}
15741539

15751540
// MintNFTArgs are arguments for passing into MintNFT requests
@@ -1644,38 +1609,11 @@ func (s *Service) buildMintNFT(args *MintNFTArgs) (*txs.Tx, ids.ShortID, error)
16441609
return nil, ids.ShortEmpty, err
16451610
}
16461611

1647-
amountsSpent, ins, secpKeys, err := s.vm.Spend(
1648-
feeUTXOs,
1649-
feeKc,
1650-
map[ids.ID]uint64{
1651-
s.vm.feeAssetID: s.vm.TxFee,
1652-
},
1653-
)
1654-
if err != nil {
1655-
return nil, ids.ShortEmpty, err
1656-
}
1657-
1658-
outs := []*avax.TransferableOutput{}
1659-
if amountSpent := amountsSpent[s.vm.feeAssetID]; amountSpent > s.vm.TxFee {
1660-
outs = append(outs, &avax.TransferableOutput{
1661-
Asset: avax.Asset{ID: s.vm.feeAssetID},
1662-
Out: &secp256k1fx.TransferOutput{
1663-
Amt: amountSpent - s.vm.TxFee,
1664-
OutputOwners: secp256k1fx.OutputOwners{
1665-
Locktime: 0,
1666-
Threshold: 1,
1667-
Addrs: []ids.ShortID{changeAddr},
1668-
},
1669-
},
1670-
})
1671-
}
1672-
16731612
// Get all UTXOs/keys
16741613
utxos, kc, err := s.vm.LoadUser(args.Username, args.Password, nil)
16751614
if err != nil {
16761615
return nil, ids.ShortEmpty, err
16771616
}
1678-
16791617
ops, nftKeys, err := s.vm.MintNFT(
16801618
utxos,
16811619
kc,
@@ -1687,21 +1625,11 @@ func (s *Service) buildMintNFT(args *MintNFTArgs) (*txs.Tx, ids.ShortID, error)
16871625
return nil, ids.ShortEmpty, err
16881626
}
16891627

1690-
tx := &txs.Tx{Unsigned: &txs.OperationTx{
1691-
BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{
1692-
NetworkID: s.vm.ctx.NetworkID,
1693-
BlockchainID: s.vm.ctx.ChainID,
1694-
Outs: outs,
1695-
Ins: ins,
1696-
}},
1697-
Ops: ops,
1698-
}}
1699-
1700-
codec := s.vm.parser.Codec()
1701-
if err := tx.SignSECP256K1Fx(codec, secpKeys); err != nil {
1628+
tx, _, err := buildOperation(s.vm, ops, nil, feeUTXOs, feeKc, changeAddr)
1629+
if err != nil {
17021630
return nil, ids.ShortEmpty, err
17031631
}
1704-
return tx, changeAddr, tx.SignNFTFx(codec, nftKeys)
1632+
return tx, changeAddr, tx.SignNFTFx(s.vm.parser.Codec(), nftKeys)
17051633
}
17061634

17071635
// ImportArgs are arguments for passing into Import requests

vms/avm/service_test.go

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -866,7 +866,9 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) {
866866
require := require.New(t)
867867

868868
env := setup(t, &envConfig{
869-
vmStaticConfig: &config.Config{},
869+
vmStaticConfig: &config.Config{
870+
DurangoTime: time.Time{},
871+
},
870872
additionalFxs: []*common.Fx{{
871873
ID: propertyfx.ID,
872874
Fx: &propertyfx.Fx{},
@@ -883,7 +885,8 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) {
883885
createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env)
884886
issueAndAccept(require, env.vm, env.issuer, createAssetTx)
885887

886-
mintNFTTx := buildOperationTxWithOp(env.vm.ctx.ChainID, buildNFTxMintOp(createAssetTx, key, 2, 1))
888+
op := buildNFTxMintOp(createAssetTx, key, 2, 1)
889+
mintNFTTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}, nil)
887890
require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}}))
888891
issueAndAccept(require, env.vm, env.issuer, mintNFTTx)
889892

@@ -965,7 +968,9 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) {
965968
require := require.New(t)
966969

967970
env := setup(t, &envConfig{
968-
vmStaticConfig: &config.Config{},
971+
vmStaticConfig: &config.Config{
972+
DurangoTime: time.Time{},
973+
},
969974
additionalFxs: []*common.Fx{{
970975
ID: propertyfx.ID,
971976
Fx: &propertyfx.Fx{},
@@ -984,8 +989,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) {
984989

985990
mintOp1 := buildNFTxMintOp(createAssetTx, key, 2, 1)
986991
mintOp2 := buildNFTxMintOp(createAssetTx, key, 3, 2)
987-
mintNFTTx := buildOperationTxWithOp(env.vm.ctx.ChainID, mintOp1, mintOp2)
988-
992+
mintNFTTx := buildOperationTxWithOp(t, env, []*txs.Operation{mintOp1, mintOp2}, nil)
989993
require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}, {key}}))
990994
issueAndAccept(require, env.vm, env.issuer, mintNFTTx)
991995

@@ -1103,7 +1107,9 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) {
11031107
require := require.New(t)
11041108

11051109
env := setup(t, &envConfig{
1106-
vmStaticConfig: &config.Config{},
1110+
vmStaticConfig: &config.Config{
1111+
DurangoTime: time.Time{},
1112+
},
11071113
additionalFxs: []*common.Fx{{
11081114
ID: propertyfx.ID,
11091115
Fx: &propertyfx.Fx{},
@@ -1120,8 +1126,8 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) {
11201126
createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env)
11211127
issueAndAccept(require, env.vm, env.issuer, createAssetTx)
11221128

1123-
mintSecpOpTx := buildOperationTxWithOp(env.vm.ctx.ChainID, buildSecpMintOp(createAssetTx, key, 0))
1124-
require.NoError(mintSecpOpTx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}}))
1129+
op := buildSecpMintOp(createAssetTx, key, 0)
1130+
mintSecpOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}, [][]*secp256k1.PrivateKey{{key}})
11251131
issueAndAccept(require, env.vm, env.issuer, mintSecpOpTx)
11261132

11271133
reply := api.GetTxReply{}
@@ -1206,7 +1212,9 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) {
12061212
require := require.New(t)
12071213

12081214
env := setup(t, &envConfig{
1209-
vmStaticConfig: &config.Config{},
1215+
vmStaticConfig: &config.Config{
1216+
DurangoTime: time.Time{},
1217+
},
12101218
additionalFxs: []*common.Fx{{
12111219
ID: propertyfx.ID,
12121220
Fx: &propertyfx.Fx{},
@@ -1225,9 +1233,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) {
12251233

12261234
op1 := buildSecpMintOp(createAssetTx, key, 0)
12271235
op2 := buildSecpMintOp(createAssetTx, key, 1)
1228-
mintSecpOpTx := buildOperationTxWithOp(env.vm.ctx.ChainID, op1, op2)
1229-
1230-
require.NoError(mintSecpOpTx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}, {key}}))
1236+
mintSecpOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op1, op2}, [][]*secp256k1.PrivateKey{{key}, {key}})
12311237
issueAndAccept(require, env.vm, env.issuer, mintSecpOpTx)
12321238

12331239
reply := api.GetTxReply{}
@@ -1352,7 +1358,9 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) {
13521358
require := require.New(t)
13531359

13541360
env := setup(t, &envConfig{
1355-
vmStaticConfig: &config.Config{},
1361+
vmStaticConfig: &config.Config{
1362+
DurangoTime: time.Time{},
1363+
},
13561364
additionalFxs: []*common.Fx{{
13571365
ID: propertyfx.ID,
13581366
Fx: &propertyfx.Fx{},
@@ -1369,7 +1377,8 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) {
13691377
createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env)
13701378
issueAndAccept(require, env.vm, env.issuer, createAssetTx)
13711379

1372-
mintPropertyFxOpTx := buildOperationTxWithOp(env.vm.ctx.ChainID, buildPropertyFxMintOp(createAssetTx, key, 4))
1380+
op := buildPropertyFxMintOp(createAssetTx, key, 4)
1381+
mintPropertyFxOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}, nil)
13731382
require.NoError(mintPropertyFxOpTx.SignPropertyFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}}))
13741383
issueAndAccept(require, env.vm, env.issuer, mintPropertyFxOpTx)
13751384

@@ -1452,7 +1461,9 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T)
14521461
require := require.New(t)
14531462

14541463
env := setup(t, &envConfig{
1455-
vmStaticConfig: &config.Config{},
1464+
vmStaticConfig: &config.Config{
1465+
DurangoTime: time.Time{},
1466+
},
14561467
additionalFxs: []*common.Fx{{
14571468
ID: propertyfx.ID,
14581469
Fx: &propertyfx.Fx{},
@@ -1471,8 +1482,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T)
14711482

14721483
op1 := buildPropertyFxMintOp(createAssetTx, key, 4)
14731484
op2 := buildPropertyFxMintOp(createAssetTx, key, 5)
1474-
mintPropertyFxOpTx := buildOperationTxWithOp(env.vm.ctx.ChainID, op1, op2)
1475-
1485+
mintPropertyFxOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op1, op2}, nil)
14761486
require.NoError(mintPropertyFxOpTx.SignPropertyFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}, {key}}))
14771487
issueAndAccept(require, env.vm, env.issuer, mintPropertyFxOpTx)
14781488

@@ -1809,14 +1819,25 @@ func buildSecpMintOp(createAssetTx *txs.Tx, key *secp256k1.PrivateKey, outputInd
18091819
}
18101820
}
18111821

1812-
func buildOperationTxWithOp(chainID ids.ID, op ...*txs.Operation) *txs.Tx {
1813-
return &txs.Tx{Unsigned: &txs.OperationTx{
1814-
BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{
1815-
NetworkID: constants.UnitTestID,
1816-
BlockchainID: chainID,
1817-
}},
1818-
Ops: op,
1819-
}}
1822+
func buildOperationTxWithOp(t *testing.T, env *environment, ops []*txs.Operation, opsKeys [][]*secp256k1.PrivateKey) *txs.Tx {
1823+
var (
1824+
key = keys[0]
1825+
kc = secp256k1fx.NewKeychain()
1826+
)
1827+
kc.Add(key)
1828+
utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses())
1829+
require.NoError(t, err)
1830+
1831+
tx, _, err := buildOperation(
1832+
env.vm,
1833+
ops,
1834+
opsKeys,
1835+
utxos,
1836+
kc,
1837+
key.Address(),
1838+
)
1839+
require.NoError(t, err)
1840+
return tx
18201841
}
18211842

18221843
func TestServiceGetNilTx(t *testing.T) {

0 commit comments

Comments
 (0)