From a20285a50b1b30cc0e3dbaffb214eb9ef5afce44 Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 17 Apr 2023 18:18:33 -0500 Subject: [PATCH 01/27] Added a conversion function --- pkg/state/snapshot.go | 79 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 pkg/state/snapshot.go diff --git a/pkg/state/snapshot.go b/pkg/state/snapshot.go new file mode 100644 index 000000000..d59f35627 --- /dev/null +++ b/pkg/state/snapshot.go @@ -0,0 +1,79 @@ +package state + +import "github.com/wavesplatform/gowaves/pkg/proto" + +func (SnapshotManager) TxSnapshotFromTx(tx proto.Transaction) TransactionSnapshot { + var snapshots []AtomicSnapshot + + switch tx.GetTypeInfo().Type { + case proto.GenesisTransaction: // 1 + out = &GenesisTransactionInfo{} + case proto.PaymentTransaction: // 2 + out = &PaymentTransactionInfo{} + case proto.IssueTransaction: // 3 + if t.Version >= 2 { + out = &IssueWithProofsTransactionInfo{} + } else { + out = &IssueWithSigTransactionInfo{} + } + case proto.TransferTransaction: // 4 + if t.Version >= 2 { + out = &TransferWithProofsTransactionInfo{} + } else { + out = &TransferWithSigTransactionInfo{} + } + case proto.ReissueTransaction: // 5 + if t.Version >= 2 { + out = &ReissueWithProofsTransactionInfo{} + } else { + out = &ReissueWithSigTransactionInfo{} + } + case proto.BurnTransaction: // 6 + if t.Version >= 2 { + out = &BurnWithProofsTransactionInfo{} + } else { + out = &BurnWithSigTransactionInfo{} + } + case proto.ExchangeTransaction: // 7 + if t.Version >= 2 { + out = &ExchangeWithProofsTransactionInfo{} + } else { + out = &ExchangeWithSigTransactionInfo{} + } + case proto.LeaseTransaction: // 8 + if t.Version >= 2 { + out = &LeaseWithProofsTransactionInfo{} + } else { + out = &LeaseWithSigTransactionInfo{} + } + case proto.LeaseCancelTransaction: // 9 + if t.Version >= 2 { + out = &LeaseCancelWithProofsTransactionInfo{} + } else { + out = &LeaseCancelWithSigTransactionInfo{} + } + case proto.CreateAliasTransaction: // 10 + if t.Version >= 2 { + out = &CreateAliasWithProofsTransactionInfo{} + } else { + out = &CreateAliasWithSigTransactionInfo{} + } + case proto.MassTransferTransaction: // 11 + out = &MassTransferTransactionInfo{} + case proto.DataTransaction: // 12 + out = &DataTransactionInfo{} + case proto.SetScriptTransaction: // 13 + out = &SetScriptTransactionInfo{} + case proto.SponsorshipTransaction: // 14 + out = &SponsorshipTransactionInfo{} + case proto.SetAssetScriptTransaction: // 15 + out = &SetAssetScriptTransactionInfo{} + case proto.InvokeScriptTransaction: // 16 + out = &InvokeScriptTransactionInfo{} + case proto.UpdateAssetInfoTransaction: // 17 + out = &UpdateAssetInfoTransactionInfo{} + case proto.EthereumMetamaskTransaction: // 18 + out = &EthereumTransactionInfo{} + } + return snapshots +} From fe5e2eb4447fb0d52ef04644206691418535ae13 Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 17 Apr 2023 21:39:41 -0500 Subject: [PATCH 02/27] Added payment transaction conversion --- pkg/state/snapshot.go | 63 ++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/pkg/state/snapshot.go b/pkg/state/snapshot.go index d59f35627..696005bc6 100644 --- a/pkg/state/snapshot.go +++ b/pkg/state/snapshot.go @@ -2,78 +2,87 @@ package state import "github.com/wavesplatform/gowaves/pkg/proto" -func (SnapshotManager) TxSnapshotFromTx(tx proto.Transaction) TransactionSnapshot { +func (s *SnapshotManager) TxSnapshotFromTx(tx proto.Transaction, scheme proto.Scheme) (TransactionSnapshot, error) { var snapshots []AtomicSnapshot switch tx.GetTypeInfo().Type { case proto.GenesisTransaction: // 1 - out = &GenesisTransactionInfo{} + out = &Genesis{} case proto.PaymentTransaction: // 2 - out = &PaymentTransactionInfo{} + paymentTx := tx.(*proto.Payment) + senderAddress, err := proto.NewAddressFromPublicKey(scheme, paymentTx.SenderPK) + if err != nil { + //... + } + senderBalanceProfile, err := s.stor.balances.wavesBalance(senderAddress.ID()) + recipientBalanceProfile, err := s.stor.balances.wavesBalance(paymentTx.Recipient.ID()) + + wavesBalanaceSnapshot := WavesBalancesSnapshot{wavesBalances: balanceWaves{address: *senderAddress}} + case proto.IssueTransaction: // 3 if t.Version >= 2 { - out = &IssueWithProofsTransactionInfo{} + out = &IssueWithProofs{} } else { - out = &IssueWithSigTransactionInfo{} + out = &IssueWithSig{} } case proto.TransferTransaction: // 4 if t.Version >= 2 { - out = &TransferWithProofsTransactionInfo{} + out = &TransferWithProofs{} } else { - out = &TransferWithSigTransactionInfo{} + out = &TransferWithSig{} } case proto.ReissueTransaction: // 5 if t.Version >= 2 { - out = &ReissueWithProofsTransactionInfo{} + out = &ReissueWithProofs{} } else { - out = &ReissueWithSigTransactionInfo{} + out = &ReissueWithSig{} } case proto.BurnTransaction: // 6 if t.Version >= 2 { - out = &BurnWithProofsTransactionInfo{} + out = &BurnWithProofs{} } else { - out = &BurnWithSigTransactionInfo{} + out = &BurnWithSig{} } case proto.ExchangeTransaction: // 7 if t.Version >= 2 { - out = &ExchangeWithProofsTransactionInfo{} + out = &ExchangeWithProofs{} } else { - out = &ExchangeWithSigTransactionInfo{} + out = &ExchangeWithSig{} } case proto.LeaseTransaction: // 8 if t.Version >= 2 { - out = &LeaseWithProofsTransactionInfo{} + out = &LeaseWithProofs{} } else { - out = &LeaseWithSigTransactionInfo{} + out = &LeaseWithSig{} } case proto.LeaseCancelTransaction: // 9 if t.Version >= 2 { - out = &LeaseCancelWithProofsTransactionInfo{} + out = &LeaseCancelWithProofs{} } else { - out = &LeaseCancelWithSigTransactionInfo{} + out = &LeaseCancelWithSig{} } case proto.CreateAliasTransaction: // 10 if t.Version >= 2 { - out = &CreateAliasWithProofsTransactionInfo{} + out = &CreateAliasWithProofs{} } else { - out = &CreateAliasWithSigTransactionInfo{} + out = &CreateAliasWithSig{} } case proto.MassTransferTransaction: // 11 - out = &MassTransferTransactionInfo{} + out = &MassTransferWithProofs{} case proto.DataTransaction: // 12 - out = &DataTransactionInfo{} + out = &DataWithProofs{} case proto.SetScriptTransaction: // 13 - out = &SetScriptTransactionInfo{} + out = &SetScriptWithProofs{} case proto.SponsorshipTransaction: // 14 - out = &SponsorshipTransactionInfo{} + out = &SponsorshipWithProofs{} case proto.SetAssetScriptTransaction: // 15 - out = &SetAssetScriptTransactionInfo{} + out = &SetAssetScriptWithProofs{} case proto.InvokeScriptTransaction: // 16 - out = &InvokeScriptTransactionInfo{} + out = &InvokeScriptWithProofs{} case proto.UpdateAssetInfoTransaction: // 17 - out = &UpdateAssetInfoTransactionInfo{} + out = &UpdateAssetInfoWithProofs{} case proto.EthereumMetamaskTransaction: // 18 - out = &EthereumTransactionInfo{} + out = &EthereumTransaction{} } return snapshots } From a80fb2bf69d46b34bb8e7233128790cb6502642d Mon Sep 17 00:00:00 2001 From: esuwu Date: Tue, 18 Apr 2023 00:23:11 -0500 Subject: [PATCH 03/27] Added transfer tx conversion --- pkg/state/snapshot.go | 179 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 166 insertions(+), 13 deletions(-) diff --git a/pkg/state/snapshot.go b/pkg/state/snapshot.go index 696005bc6..7149d78dc 100644 --- a/pkg/state/snapshot.go +++ b/pkg/state/snapshot.go @@ -1,36 +1,124 @@ package state -import "github.com/wavesplatform/gowaves/pkg/proto" +import ( + "github.com/wavesplatform/gowaves/pkg/proto" +) +// TODO validation of the transactions should be before or after? func (s *SnapshotManager) TxSnapshotFromTx(tx proto.Transaction, scheme proto.Scheme) (TransactionSnapshot, error) { var snapshots []AtomicSnapshot switch tx.GetTypeInfo().Type { case proto.GenesisTransaction: // 1 - out = &Genesis{} + genesisTx, ok := tx.(*proto.Genesis) + if !ok { + // ... + } + wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ + {address: &genesisTx.Recipient, balance: genesisTx.Amount}}, + } + snapshots = append(snapshots, wavesBalancesSnapshot) + return snapshots, nil case proto.PaymentTransaction: // 2 - paymentTx := tx.(*proto.Payment) + paymentTx, ok := tx.(*proto.Payment) + if !ok { + // ... + } senderAddress, err := proto.NewAddressFromPublicKey(scheme, paymentTx.SenderPK) if err != nil { //... } - senderBalanceProfile, err := s.stor.balances.wavesBalance(senderAddress.ID()) - recipientBalanceProfile, err := s.stor.balances.wavesBalance(paymentTx.Recipient.ID()) + senderBalance, err := s.wavesBalanceByAddress(senderAddress) + if err != nil { + //... + } + recipientBalance, err := s.wavesBalanceByAddress(paymentTx.Recipient) + if err != nil { + //... + } - wavesBalanaceSnapshot := WavesBalancesSnapshot{wavesBalances: balanceWaves{address: *senderAddress}} + // TODO validate balances + wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ + {address: &senderAddress, balance: senderBalance - paymentTx.Amount - paymentTx.Fee}, + {address: &paymentTx.Recipient, balance: recipientBalance + paymentTx.Amount}}, + } + snapshots = append(snapshots, wavesBalancesSnapshot) + return snapshots, nil case proto.IssueTransaction: // 3 - if t.Version >= 2 { - out = &IssueWithProofs{} - } else { - out = &IssueWithSig{} + var issue proto.Issue + switch i := tx.(type) { + case *proto.IssueWithSig: + issue = i.Issue + case *proto.IssueWithProofs: + issue = i.Issue + default: + // return err } + senderAddress, err := proto.NewAddressFromPublicKey(scheme, issue.SenderPK) + if err != nil { + //... + } + senderBalance, err := s.wavesBalanceByAddress(senderAddress) + if err != nil { + //... + } + // TODO validate balances + wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ + {address: &senderAddress, balance: senderBalance - issue.Fee}}, + } + + assetsSnapshot := &AssetDescriptionSnapshot{ + // TODO generate asset id and fill change height + assetID: proto.AssetID{}, + assetName: &issue.Name, + assetDescription: issue.Description, + changeHeight: 0, + } + + snapshots = append(snapshots, wavesBalancesSnapshot, assetsSnapshot) + return snapshots, nil case proto.TransferTransaction: // 4 - if t.Version >= 2 { - out = &TransferWithProofs{} + var transfer proto.Transfer + switch t := tx.(type) { + case *proto.TransferWithSig: + transfer = t.Transfer + case *proto.TransferWithProofs: + transfer = t.Transfer + default: + // return err + } + if transfer.AmountAsset.Present { + + } else { + senderAddress, err := proto.NewAddressFromPublicKey(scheme, transfer.SenderPK) + if err != nil { + //... + } + // TODO handle alias + recipientAddress := transfer.Recipient.Address() + senderBalance, err := s.wavesBalanceByAddress(senderAddress) + if err != nil { + //... + } + recipientBalance, err := s.wavesBalanceByAddress(*recipientAddress) + if err != nil { + //... + } + wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ + {address: &senderAddress, balance: senderBalance - transfer.Amount - transfer.Fee}, + {address: recipientAddress, balance: recipientBalance + transfer.Amount}}, + } + snapshots = append(snapshots, wavesBalancesSnapshot) + } + + if transfer.FeeAsset.Present { + } else { - out = &TransferWithSig{} + } + + // TODO merge different arrays of wavesBalances and assetBalances for the same addresses case proto.ReissueTransaction: // 5 if t.Version >= 2 { out = &ReissueWithProofs{} @@ -86,3 +174,68 @@ func (s *SnapshotManager) TxSnapshotFromTx(tx proto.Transaction, scheme proto.Sc } return snapshots } + +//func (s *SnapshotManager) balanceByPublicKey(pk crypto.PublicKey, scheme proto.Scheme) uint64 { +// address, err := proto.NewAddressFromPublicKey(scheme, pk) +// if err != nil { +// //... +// } +// balanceProfile, err := s.stor.balances.wavesBalance(address.ID()) +// if err != nil { +// //... +// } +// return balanceProfile.balance +//} + +func (s SnapshotManager) wavesBalanceSnapshotAmountFee(sender proto.WavesAddress, recipient proto.WavesAddress, + amount uint64, fee uint64) (*WavesBalancesSnapshot, error) { + senderBalance, err := s.wavesBalanceByAddress(sender) + if err != nil { + //... + } + recipientBalance, err := s.wavesBalanceByAddress(recipient) + if err != nil { + //... + } + wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ + {address: &sender, balance: senderBalance - amount - fee}, + {address: recipient, balance: recipientBalance + amount}}, + } + return wavesBalancesSnapshot, nil +} + +func (s SnapshotManager) wavesBalanceSnapshotFee(sender proto.WavesAddress, fee uint64) (*WavesBalancesSnapshot, error) { + senderBalance, err := s.wavesBalanceByAddress(sender) + if err != nil { + //... + } + wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ + {address: &sender, balance: senderBalance - fee}}, + } + return wavesBalancesSnapshot, nil +} + +func (s SnapshotManager) assetBalanceSnapshotAmount(sender proto.WavesAddress, recipient proto.WavesAddress, assetID proto.AssetID, + amount uint64) (*AssetBalancesSnapshot, error) { + senderAssetBalance, err := s.stor.balances.assetBalance(sender.ID(), assetID) + if err != nil { + //... + } + recipientAssetBalance, err := s.stor.balances.assetBalance(recipient.ID(), assetID) + if err != nil { + //... + } + wavesBalancesSnapshot := &AssetBalancesSnapshot{assetBalances: []balanceAsset{ + {address: &sender, balance: senderAssetBalance - amount}, + {address: recipient, balance: recipientAssetBalance + amount}}, + } + return wavesBalancesSnapshot, nil +} + +func (s *SnapshotManager) wavesBalanceByAddress(address proto.WavesAddress) (uint64, error) { + recipientWavesBalanceProfile, err := s.stor.balances.wavesBalance(address.ID()) + if err != nil { + //... + } + return recipientWavesBalanceProfile.balance, nil +} \ No newline at end of file From ef5c2f73653c45e92f33ee03464d78d6da0f80c8 Mon Sep 17 00:00:00 2001 From: esuwu Date: Tue, 18 Apr 2023 00:36:14 -0500 Subject: [PATCH 04/27] Transfer tx conversion changed --- pkg/state/snapshot.go | 83 +++++++++++-------------------------------- 1 file changed, 21 insertions(+), 62 deletions(-) diff --git a/pkg/state/snapshot.go b/pkg/state/snapshot.go index 7149d78dc..d03eb27f2 100644 --- a/pkg/state/snapshot.go +++ b/pkg/state/snapshot.go @@ -89,27 +89,30 @@ func (s *SnapshotManager) TxSnapshotFromTx(tx proto.Transaction, scheme proto.Sc // return err } if transfer.AmountAsset.Present { - - } else { senderAddress, err := proto.NewAddressFromPublicKey(scheme, transfer.SenderPK) if err != nil { //... } // TODO handle alias recipientAddress := transfer.Recipient.Address() - senderBalance, err := s.wavesBalanceByAddress(senderAddress) + assetBalanceSnapshotFromAmount, err := s.assetBalanceSnapshotTransfer(senderAddress, *recipientAddress, proto.AssetIDFromDigest(transfer.AmountAsset.ID), transfer.Amount) if err != nil { //... } - recipientBalance, err := s.wavesBalanceByAddress(*recipientAddress) + snapshots = append(snapshots, assetBalanceSnapshotFromAmount) + } else { + senderAddress, err := proto.NewAddressFromPublicKey(scheme, transfer.SenderPK) if err != nil { //... } - wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ - {address: &senderAddress, balance: senderBalance - transfer.Amount - transfer.Fee}, - {address: recipientAddress, balance: recipientBalance + transfer.Amount}}, + // TODO handle alias + recipientAddress := transfer.Recipient.Address() + + wavesBalanceSnapshotFromAmount, err := s.wavesBalanceSnapshotTransfer(senderAddress, *recipientAddress, transfer.Amount) + if err != nil { + //... } - snapshots = append(snapshots, wavesBalancesSnapshot) + snapshots = append(snapshots, wavesBalanceSnapshotFromAmount) } if transfer.FeeAsset.Present { @@ -120,59 +123,27 @@ func (s *SnapshotManager) TxSnapshotFromTx(tx proto.Transaction, scheme proto.Sc // TODO merge different arrays of wavesBalances and assetBalances for the same addresses case proto.ReissueTransaction: // 5 - if t.Version >= 2 { - out = &ReissueWithProofs{} - } else { - out = &ReissueWithSig{} - } + case proto.BurnTransaction: // 6 - if t.Version >= 2 { - out = &BurnWithProofs{} - } else { - out = &BurnWithSig{} - } + case proto.ExchangeTransaction: // 7 - if t.Version >= 2 { - out = &ExchangeWithProofs{} - } else { - out = &ExchangeWithSig{} - } + case proto.LeaseTransaction: // 8 - if t.Version >= 2 { - out = &LeaseWithProofs{} - } else { - out = &LeaseWithSig{} - } + case proto.LeaseCancelTransaction: // 9 - if t.Version >= 2 { - out = &LeaseCancelWithProofs{} - } else { - out = &LeaseCancelWithSig{} - } + case proto.CreateAliasTransaction: // 10 - if t.Version >= 2 { - out = &CreateAliasWithProofs{} - } else { - out = &CreateAliasWithSig{} - } + case proto.MassTransferTransaction: // 11 - out = &MassTransferWithProofs{} case proto.DataTransaction: // 12 - out = &DataWithProofs{} case proto.SetScriptTransaction: // 13 - out = &SetScriptWithProofs{} case proto.SponsorshipTransaction: // 14 - out = &SponsorshipWithProofs{} case proto.SetAssetScriptTransaction: // 15 - out = &SetAssetScriptWithProofs{} case proto.InvokeScriptTransaction: // 16 - out = &InvokeScriptWithProofs{} case proto.UpdateAssetInfoTransaction: // 17 - out = &UpdateAssetInfoWithProofs{} case proto.EthereumMetamaskTransaction: // 18 - out = &EthereumTransaction{} } - return snapshots + return snapshots, nil } //func (s *SnapshotManager) balanceByPublicKey(pk crypto.PublicKey, scheme proto.Scheme) uint64 { @@ -187,8 +158,7 @@ func (s *SnapshotManager) TxSnapshotFromTx(tx proto.Transaction, scheme proto.Sc // return balanceProfile.balance //} -func (s SnapshotManager) wavesBalanceSnapshotAmountFee(sender proto.WavesAddress, recipient proto.WavesAddress, - amount uint64, fee uint64) (*WavesBalancesSnapshot, error) { +func (s SnapshotManager) wavesBalanceSnapshotTransfer(sender proto.WavesAddress, recipient proto.WavesAddress, amount uint64) (*WavesBalancesSnapshot, error) { senderBalance, err := s.wavesBalanceByAddress(sender) if err != nil { //... @@ -198,24 +168,13 @@ func (s SnapshotManager) wavesBalanceSnapshotAmountFee(sender proto.WavesAddress //... } wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ - {address: &sender, balance: senderBalance - amount - fee}, + {address: &sender, balance: senderBalance - amount}, {address: recipient, balance: recipientBalance + amount}}, } return wavesBalancesSnapshot, nil } -func (s SnapshotManager) wavesBalanceSnapshotFee(sender proto.WavesAddress, fee uint64) (*WavesBalancesSnapshot, error) { - senderBalance, err := s.wavesBalanceByAddress(sender) - if err != nil { - //... - } - wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ - {address: &sender, balance: senderBalance - fee}}, - } - return wavesBalancesSnapshot, nil -} - -func (s SnapshotManager) assetBalanceSnapshotAmount(sender proto.WavesAddress, recipient proto.WavesAddress, assetID proto.AssetID, +func (s SnapshotManager) assetBalanceSnapshotTransfer(sender proto.WavesAddress, recipient proto.WavesAddress, assetID proto.AssetID, amount uint64) (*AssetBalancesSnapshot, error) { senderAssetBalance, err := s.stor.balances.assetBalance(sender.ID(), assetID) if err != nil { From 1d2004872c7251cf3d7c9cd9bd5fdfef88075fa4 Mon Sep 17 00:00:00 2001 From: esuwu Date: Tue, 18 Apr 2023 23:17:13 -0500 Subject: [PATCH 05/27] Added issue and reissue tx conversions --- pkg/state/snapshot.go | 200 ----------------------------------- pkg/state/snapshots.go | 231 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 231 insertions(+), 200 deletions(-) delete mode 100644 pkg/state/snapshot.go create mode 100644 pkg/state/snapshots.go diff --git a/pkg/state/snapshot.go b/pkg/state/snapshot.go deleted file mode 100644 index d03eb27f2..000000000 --- a/pkg/state/snapshot.go +++ /dev/null @@ -1,200 +0,0 @@ -package state - -import ( - "github.com/wavesplatform/gowaves/pkg/proto" -) - -// TODO validation of the transactions should be before or after? -func (s *SnapshotManager) TxSnapshotFromTx(tx proto.Transaction, scheme proto.Scheme) (TransactionSnapshot, error) { - var snapshots []AtomicSnapshot - - switch tx.GetTypeInfo().Type { - case proto.GenesisTransaction: // 1 - genesisTx, ok := tx.(*proto.Genesis) - if !ok { - // ... - } - wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ - {address: &genesisTx.Recipient, balance: genesisTx.Amount}}, - } - snapshots = append(snapshots, wavesBalancesSnapshot) - return snapshots, nil - case proto.PaymentTransaction: // 2 - paymentTx, ok := tx.(*proto.Payment) - if !ok { - // ... - } - senderAddress, err := proto.NewAddressFromPublicKey(scheme, paymentTx.SenderPK) - if err != nil { - //... - } - senderBalance, err := s.wavesBalanceByAddress(senderAddress) - if err != nil { - //... - } - recipientBalance, err := s.wavesBalanceByAddress(paymentTx.Recipient) - if err != nil { - //... - } - - // TODO validate balances - - wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ - {address: &senderAddress, balance: senderBalance - paymentTx.Amount - paymentTx.Fee}, - {address: &paymentTx.Recipient, balance: recipientBalance + paymentTx.Amount}}, - } - snapshots = append(snapshots, wavesBalancesSnapshot) - return snapshots, nil - case proto.IssueTransaction: // 3 - var issue proto.Issue - switch i := tx.(type) { - case *proto.IssueWithSig: - issue = i.Issue - case *proto.IssueWithProofs: - issue = i.Issue - default: - // return err - } - senderAddress, err := proto.NewAddressFromPublicKey(scheme, issue.SenderPK) - if err != nil { - //... - } - senderBalance, err := s.wavesBalanceByAddress(senderAddress) - if err != nil { - //... - } - // TODO validate balances - wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ - {address: &senderAddress, balance: senderBalance - issue.Fee}}, - } - - assetsSnapshot := &AssetDescriptionSnapshot{ - // TODO generate asset id and fill change height - assetID: proto.AssetID{}, - assetName: &issue.Name, - assetDescription: issue.Description, - changeHeight: 0, - } - - snapshots = append(snapshots, wavesBalancesSnapshot, assetsSnapshot) - return snapshots, nil - case proto.TransferTransaction: // 4 - var transfer proto.Transfer - switch t := tx.(type) { - case *proto.TransferWithSig: - transfer = t.Transfer - case *proto.TransferWithProofs: - transfer = t.Transfer - default: - // return err - } - if transfer.AmountAsset.Present { - senderAddress, err := proto.NewAddressFromPublicKey(scheme, transfer.SenderPK) - if err != nil { - //... - } - // TODO handle alias - recipientAddress := transfer.Recipient.Address() - assetBalanceSnapshotFromAmount, err := s.assetBalanceSnapshotTransfer(senderAddress, *recipientAddress, proto.AssetIDFromDigest(transfer.AmountAsset.ID), transfer.Amount) - if err != nil { - //... - } - snapshots = append(snapshots, assetBalanceSnapshotFromAmount) - } else { - senderAddress, err := proto.NewAddressFromPublicKey(scheme, transfer.SenderPK) - if err != nil { - //... - } - // TODO handle alias - recipientAddress := transfer.Recipient.Address() - - wavesBalanceSnapshotFromAmount, err := s.wavesBalanceSnapshotTransfer(senderAddress, *recipientAddress, transfer.Amount) - if err != nil { - //... - } - snapshots = append(snapshots, wavesBalanceSnapshotFromAmount) - } - - if transfer.FeeAsset.Present { - - } else { - - } - - // TODO merge different arrays of wavesBalances and assetBalances for the same addresses - case proto.ReissueTransaction: // 5 - - case proto.BurnTransaction: // 6 - - case proto.ExchangeTransaction: // 7 - - case proto.LeaseTransaction: // 8 - - case proto.LeaseCancelTransaction: // 9 - - case proto.CreateAliasTransaction: // 10 - - case proto.MassTransferTransaction: // 11 - case proto.DataTransaction: // 12 - case proto.SetScriptTransaction: // 13 - case proto.SponsorshipTransaction: // 14 - case proto.SetAssetScriptTransaction: // 15 - case proto.InvokeScriptTransaction: // 16 - case proto.UpdateAssetInfoTransaction: // 17 - case proto.EthereumMetamaskTransaction: // 18 - } - return snapshots, nil -} - -//func (s *SnapshotManager) balanceByPublicKey(pk crypto.PublicKey, scheme proto.Scheme) uint64 { -// address, err := proto.NewAddressFromPublicKey(scheme, pk) -// if err != nil { -// //... -// } -// balanceProfile, err := s.stor.balances.wavesBalance(address.ID()) -// if err != nil { -// //... -// } -// return balanceProfile.balance -//} - -func (s SnapshotManager) wavesBalanceSnapshotTransfer(sender proto.WavesAddress, recipient proto.WavesAddress, amount uint64) (*WavesBalancesSnapshot, error) { - senderBalance, err := s.wavesBalanceByAddress(sender) - if err != nil { - //... - } - recipientBalance, err := s.wavesBalanceByAddress(recipient) - if err != nil { - //... - } - wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ - {address: &sender, balance: senderBalance - amount}, - {address: recipient, balance: recipientBalance + amount}}, - } - return wavesBalancesSnapshot, nil -} - -func (s SnapshotManager) assetBalanceSnapshotTransfer(sender proto.WavesAddress, recipient proto.WavesAddress, assetID proto.AssetID, - amount uint64) (*AssetBalancesSnapshot, error) { - senderAssetBalance, err := s.stor.balances.assetBalance(sender.ID(), assetID) - if err != nil { - //... - } - recipientAssetBalance, err := s.stor.balances.assetBalance(recipient.ID(), assetID) - if err != nil { - //... - } - wavesBalancesSnapshot := &AssetBalancesSnapshot{assetBalances: []balanceAsset{ - {address: &sender, balance: senderAssetBalance - amount}, - {address: recipient, balance: recipientAssetBalance + amount}}, - } - return wavesBalancesSnapshot, nil -} - -func (s *SnapshotManager) wavesBalanceByAddress(address proto.WavesAddress) (uint64, error) { - recipientWavesBalanceProfile, err := s.stor.balances.wavesBalance(address.ID()) - if err != nil { - //... - } - return recipientWavesBalanceProfile.balance, nil -} \ No newline at end of file diff --git a/pkg/state/snapshots.go b/pkg/state/snapshots.go new file mode 100644 index 000000000..4436c9299 --- /dev/null +++ b/pkg/state/snapshots.go @@ -0,0 +1,231 @@ +package state + +import ( + "github.com/wavesplatform/gowaves/pkg/proto" +) + +// TODO validation of the transactions should be before or after? +func (s *SnapshotManager) TxSnapshotFromTx(tx proto.Transaction, scheme proto.Scheme) (TransactionSnapshot, error) { + var snapshots []AtomicSnapshot + + switch tx.GetTypeInfo().Type { + case proto.GenesisTransaction: // 1 + genesisTx, ok := tx.(*proto.Genesis) + if !ok { + // ... + } + wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ + {address: &genesisTx.Recipient, balance: genesisTx.Amount}}, + } + snapshots = append(snapshots, wavesBalancesSnapshot) + return snapshots, nil + case proto.PaymentTransaction: // 2 + paymentTx, ok := tx.(*proto.Payment) + if !ok { + // ... + } + senderAddress, err := proto.NewAddressFromPublicKey(scheme, paymentTx.SenderPK) + if err != nil { + //... + } + senderBalance, err := s.wavesBalanceByAddress(senderAddress) + if err != nil { + //... + } + recipientBalance, err := s.wavesBalanceByAddress(paymentTx.Recipient) + if err != nil { + //... + } + + // TODO validate balances + + wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ + {address: &senderAddress, balance: senderBalance - paymentTx.Amount - paymentTx.Fee}, + {address: &paymentTx.Recipient, balance: recipientBalance + paymentTx.Amount}}, + } + snapshots = append(snapshots, wavesBalancesSnapshot) + return snapshots, nil + case proto.IssueTransaction: // 3 + var issue proto.Issue + switch i := tx.(type) { + case *proto.IssueWithSig: + issue = i.Issue + case *proto.IssueWithProofs: + issue = i.Issue + default: + // return err + } + senderAddress, err := proto.NewAddressFromPublicKey(scheme, issue.SenderPK) + if err != nil { + //... + } + senderBalance, err := s.wavesBalanceByAddress(senderAddress) + if err != nil { + //... + } + // TODO validate balances + wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ + {address: &senderAddress, balance: senderBalance - issue.Fee}}, + } + + assetsSnapshot := &AssetDescriptionSnapshot{ + // TODO generate asset id and fill change height + assetID: proto.AssetID{}, + assetName: &issue.Name, + assetDescription: issue.Description, + changeHeight: 0, + } + + snapshots = append(snapshots, wavesBalancesSnapshot, assetsSnapshot) + return snapshots, nil + case proto.TransferTransaction: // 4 + var transfer proto.Transfer + switch t := tx.(type) { + case *proto.TransferWithSig: + transfer = t.Transfer + case *proto.TransferWithProofs: + transfer = t.Transfer + default: + // return err + } + senderAddress, err := proto.NewAddressFromPublicKey(scheme, transfer.SenderPK) + if err != nil { + //... + } + // TODO handle alias + recipientAddress := transfer.Recipient.Address() + assetBalancesSnapshot, wavesBalancesSnapshot, err := s.optionalAssetBalanceSnapshotTransfer(senderAddress, *recipientAddress, transfer.AmountAsset, transfer.Amount, transfer.FeeAsset, transfer.Fee) + if err != nil { + //... + } + if assetBalancesSnapshot != nil { + snapshots = append(snapshots, assetBalancesSnapshot) + } + if wavesBalancesSnapshot != nil { + snapshots = append(snapshots, wavesBalancesSnapshot) + } + return snapshots, nil + // TODO should be a snapshot about the quantity + case proto.ReissueTransaction: // 5 + var reissue proto.Reissue + switch t := tx.(type) { + case *proto.ReissueWithSig: + reissue = t.Reissue + case *proto.ReissueWithProofs: + reissue = t.Reissue + default: + // return err + } + assetInfo, err := s.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(reissue.AssetID)) + if err != nil { + // ... + } + senderAddress, err := proto.NewAddressFromPublicKey(scheme, reissue.SenderPK) + if err != nil { + //... + } + senderBalance, err := s.wavesBalanceByAddress(senderAddress) + if err != nil { + //... + } + // TODO validate balances + wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ + {address: &senderAddress, balance: senderBalance - reissue.Fee}}, + } + snapshots = append(snapshots, wavesBalancesSnapshot) + // TODO can you make an asset reissuable again? + if assetInfo.reissuable != reissue.Reissuable { + assetReissuabilitySnapshot := &AssetReissuabilitySnapshot{ + assetID: proto.AssetIDFromDigest(reissue.AssetID), + isReissuable: reissue.Reissuable, + } + snapshots = append(snapshots, assetReissuabilitySnapshot) + } + return snapshots, nil + case proto.BurnTransaction: // 6 + + case proto.ExchangeTransaction: // 7 + + case proto.LeaseTransaction: // 8 + + case proto.LeaseCancelTransaction: // 9 + + case proto.CreateAliasTransaction: // 10 + + case proto.MassTransferTransaction: // 11 + case proto.DataTransaction: // 12 + case proto.SetScriptTransaction: // 13 + case proto.SponsorshipTransaction: // 14 + case proto.SetAssetScriptTransaction: // 15 + case proto.InvokeScriptTransaction: // 16 + case proto.UpdateAssetInfoTransaction: // 17 + case proto.EthereumMetamaskTransaction: // 18 + } + return snapshots, nil +} + +func (s SnapshotManager) optionalAssetBalanceSnapshotTransfer(sender proto.WavesAddress, recipient proto.WavesAddress, amountAsset proto.OptionalAsset, + amount uint64, feeAsset proto.OptionalAsset, fee uint64) (*AssetBalancesSnapshot, *WavesBalancesSnapshot, error) { + + if amountAsset.Present { + senderAssetBalance, err := s.stor.balances.assetBalance(sender.ID(), proto.AssetIDFromDigest(amountAsset.ID)) + if err != nil { + //... + } + recipientAssetBalance, err := s.stor.balances.assetBalance(recipient.ID(), proto.AssetIDFromDigest(amountAsset.ID)) + if err != nil { + //... + } + if feeAsset.Present { + return &AssetBalancesSnapshot{assetBalances: []balanceAsset{ + {address: sender, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: senderAssetBalance - amount - fee}, + {address: recipient, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: recipientAssetBalance + amount}, + }}, nil, nil + } + + senderWavesBalance, err := s.stor.balances.wavesBalance(sender.ID()) + if err != nil { + //... + } + return &AssetBalancesSnapshot{assetBalances: []balanceAsset{ + {address: sender, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: senderAssetBalance - amount}, + {address: recipient, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: recipientAssetBalance + amount}, + }}, &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ + {address: sender, balance: senderWavesBalance.balance - fee}, + }}, nil + } + + senderWavesBalance, err := s.stor.balances.wavesBalance(sender.ID()) + if err != nil { + //... + } + recipientWavesBalance, err := s.stor.balances.wavesBalance(recipient.ID()) + if err != nil { + //... + } + if feeAsset.Present { + senderAssetBalance, err := s.stor.balances.assetBalance(sender.ID(), proto.AssetIDFromDigest(amountAsset.ID)) + if err != nil { + //... + } + return &AssetBalancesSnapshot{assetBalances: []balanceAsset{ + {address: sender, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: senderAssetBalance - fee}, + }}, &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ + {address: sender, balance: senderWavesBalance.balance - amount}, + {address: recipient, balance: recipientWavesBalance.balance + amount}, + }}, nil + } + + return nil, &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ + {address: sender, balance: senderWavesBalance.balance - fee - amount}, + {address: recipient, balance: senderWavesBalance.balance + amount}, + }}, nil +} + +func (s *SnapshotManager) wavesBalanceByAddress(address proto.WavesAddress) (uint64, error) { + recipientWavesBalanceProfile, err := s.stor.balances.wavesBalance(address.ID()) + if err != nil { + //... + } + return recipientWavesBalanceProfile.balance, nil +} From 39fb959d963f519e0b7e27df3d93589145d6a329 Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 24 Apr 2023 18:09:21 -0500 Subject: [PATCH 06/27] Issue --- pkg/state/appender.go | 24 ++++++++++++++---------- pkg/state/transaction_handler.go | 9 +++++---- pkg/state/transaction_performer.go | 15 +++++++++++++-- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 9a9b5982d..f21bda374 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -326,11 +326,11 @@ func (a *txAppender) saveTransactionIdByAddresses(addresses []proto.WavesAddress return nil } -func (a *txAppender) commitTxApplication(tx proto.Transaction, params *appendTxParams, res *applicationResult) error { +func (a *txAppender) commitTxApplication(tx proto.Transaction, params *appendTxParams, res *applicationResult) (TransactionSnapshot, error) { // Add transaction ID to recent IDs. txID, err := tx.GetID(a.settings.AddressSchemeCharacter) if err != nil { - return wrapErr(TxCommitmentError, errors.Errorf("failed to get tx id: %v", err)) + return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to get tx id: %v", err)) } a.recentTxIds[string(txID)] = empty // Update script runs. @@ -339,35 +339,37 @@ func (a *txAppender) commitTxApplication(tx proto.Transaction, params *appendTxP a.sc.addRecentTxComplexity() // Save balance diff. if err := a.diffStor.saveTxDiff(res.changes.diff); err != nil { - return wrapErr(TxCommitmentError, errors.Errorf("failed to save balance diff: %v", err)) + return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to save balance diff: %v", err)) } // Perform state changes. + var snapshot TransactionSnapshot if res.status { // We only perform tx in case it has not failed. performerInfo := &performerInfo{ height: params.checkerInfo.height, blockID: params.checkerInfo.blockID, } - if err := a.txHandler.performTx(tx, performerInfo); err != nil { - return wrapErr(TxCommitmentError, errors.Errorf("failed to perform: %v", err)) + snapshot, err := a.txHandler.performTx(tx, performerInfo) + if err != nil { + return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to perform: %v", err)) } } if params.validatingUtx { // Save transaction to in-mem storage. if err := a.rw.writeTransactionToMem(tx, !res.status); err != nil { - return wrapErr(TxCommitmentError, errors.Errorf("failed to write transaction to in mem stor: %v", err)) + return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to write transaction to in mem stor: %v", err)) } } else { // Count tx fee. if err := a.blockDiffer.countMinerFee(tx); err != nil { - return wrapErr(TxCommitmentError, errors.Errorf("failed to count miner fee: %v", err)) + return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to count miner fee: %v", err)) } // Save transaction to storage. if err := a.rw.writeTransaction(tx, !res.status); err != nil { - return wrapErr(TxCommitmentError, errors.Errorf("failed to write transaction to storage: %v", err)) + return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to write transaction to storage: %v", err)) } } - return nil + return snapshot, nil } func (a *txAppender) verifyWavesTxSigAndData(tx proto.Transaction, params *appendTxParams, accountHasVerifierScript bool) error { @@ -547,7 +549,9 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro if err != nil { return errs.Extend(err, "get transaction id") } - if err := a.commitTxApplication(tx, params, applicationRes); err != nil { + + snapshot, err := a.commitTxApplication(tx, params, applicationRes) + if err != nil { zap.S().Errorf("failed to commit transaction (id %s) after successful validation; this should NEVER happen", base58.Encode(txID)) return err } diff --git a/pkg/state/transaction_handler.go b/pkg/state/transaction_handler.go index 33a3c686e..6f1ae9eb6 100644 --- a/pkg/state/transaction_handler.go +++ b/pkg/state/transaction_handler.go @@ -8,7 +8,7 @@ import ( ) type txCheckFunc func(proto.Transaction, *checkerInfo) ([]crypto.Digest, error) -type txPerformFunc func(proto.Transaction, *performerInfo) error +type txPerformFunc func(proto.Transaction, *performerInfo) (TransactionSnapshot, error) type txCreateDiffFunc func(proto.Transaction, *differInfo) (txBalanceChanges, error) type txCountFeeFunc func(proto.Transaction, *feeDistribution) error @@ -154,16 +154,17 @@ func (h *transactionHandler) checkTx(tx proto.Transaction, info *checkerInfo) ([ return funcs.check(tx, info) } -func (h *transactionHandler) performTx(tx proto.Transaction, info *performerInfo) error { +func (h *transactionHandler) performTx(tx proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tv := tx.GetTypeInfo() funcs, ok := h.funcs[tv] if !ok { - return errors.Errorf("No function handler implemented for tx struct type %T\n", tx) + return nil, errors.Errorf("No function handler implemented for tx struct type %T\n", tx) } if funcs.perform == nil { // No perform func for this combination of transaction type and version. - return nil + return nil, nil } + return funcs.perform(tx, info) } diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 80ba4f94c..7c38912b4 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -23,7 +23,7 @@ func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings return &transactionPerformer{stor, settings}, nil } -func (tp *transactionPerformer) performIssue(tx *proto.Issue, assetID crypto.Digest, info *performerInfo) error { +func (tp *transactionPerformer) performIssue(tx *proto.Issue, assetID crypto.Digest, info *performerInfo) (TransactionSnapshot, error) { blockHeight := info.height + 1 // Create new asset. assetInfo := &assetInfo{ @@ -40,13 +40,24 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, assetID crypto.Dig reissuable: tx.Reissuable, }, } + if err := tp.stor.assets.issueAsset(proto.AssetIDFromDigest(assetID), assetInfo, info.blockID); err != nil { return errors.Wrap(err, "failed to issue asset") } + + + sender := proto.MustAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) + issueSnapshot := StaticAssetInfoSnapshot{ + assetID: proto.AssetIDFromDigest(assetID), + issuer: sender, + isNFT: assetInfo.isNFT(), + } + tp.stor.assets. + return nil } -func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.IssueWithSig) if !ok { return errors.New("failed to convert interface to IssueWithSig transaction") From de38edcacc385db50fbef28f8379e71004feb0ca Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 24 Apr 2023 20:19:42 -0500 Subject: [PATCH 07/27] Issue, reissue, burn, exchange --- pkg/state/snapshots.go | 451 ++++++++++++++--------------- pkg/state/transaction_performer.go | 149 +++++++--- 2 files changed, 325 insertions(+), 275 deletions(-) diff --git a/pkg/state/snapshots.go b/pkg/state/snapshots.go index 4436c9299..7dca1b339 100644 --- a/pkg/state/snapshots.go +++ b/pkg/state/snapshots.go @@ -1,231 +1,224 @@ package state -import ( - "github.com/wavesplatform/gowaves/pkg/proto" -) - -// TODO validation of the transactions should be before or after? -func (s *SnapshotManager) TxSnapshotFromTx(tx proto.Transaction, scheme proto.Scheme) (TransactionSnapshot, error) { - var snapshots []AtomicSnapshot - - switch tx.GetTypeInfo().Type { - case proto.GenesisTransaction: // 1 - genesisTx, ok := tx.(*proto.Genesis) - if !ok { - // ... - } - wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ - {address: &genesisTx.Recipient, balance: genesisTx.Amount}}, - } - snapshots = append(snapshots, wavesBalancesSnapshot) - return snapshots, nil - case proto.PaymentTransaction: // 2 - paymentTx, ok := tx.(*proto.Payment) - if !ok { - // ... - } - senderAddress, err := proto.NewAddressFromPublicKey(scheme, paymentTx.SenderPK) - if err != nil { - //... - } - senderBalance, err := s.wavesBalanceByAddress(senderAddress) - if err != nil { - //... - } - recipientBalance, err := s.wavesBalanceByAddress(paymentTx.Recipient) - if err != nil { - //... - } - - // TODO validate balances - - wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ - {address: &senderAddress, balance: senderBalance - paymentTx.Amount - paymentTx.Fee}, - {address: &paymentTx.Recipient, balance: recipientBalance + paymentTx.Amount}}, - } - snapshots = append(snapshots, wavesBalancesSnapshot) - return snapshots, nil - case proto.IssueTransaction: // 3 - var issue proto.Issue - switch i := tx.(type) { - case *proto.IssueWithSig: - issue = i.Issue - case *proto.IssueWithProofs: - issue = i.Issue - default: - // return err - } - senderAddress, err := proto.NewAddressFromPublicKey(scheme, issue.SenderPK) - if err != nil { - //... - } - senderBalance, err := s.wavesBalanceByAddress(senderAddress) - if err != nil { - //... - } - // TODO validate balances - wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ - {address: &senderAddress, balance: senderBalance - issue.Fee}}, - } - - assetsSnapshot := &AssetDescriptionSnapshot{ - // TODO generate asset id and fill change height - assetID: proto.AssetID{}, - assetName: &issue.Name, - assetDescription: issue.Description, - changeHeight: 0, - } - - snapshots = append(snapshots, wavesBalancesSnapshot, assetsSnapshot) - return snapshots, nil - case proto.TransferTransaction: // 4 - var transfer proto.Transfer - switch t := tx.(type) { - case *proto.TransferWithSig: - transfer = t.Transfer - case *proto.TransferWithProofs: - transfer = t.Transfer - default: - // return err - } - senderAddress, err := proto.NewAddressFromPublicKey(scheme, transfer.SenderPK) - if err != nil { - //... - } - // TODO handle alias - recipientAddress := transfer.Recipient.Address() - assetBalancesSnapshot, wavesBalancesSnapshot, err := s.optionalAssetBalanceSnapshotTransfer(senderAddress, *recipientAddress, transfer.AmountAsset, transfer.Amount, transfer.FeeAsset, transfer.Fee) - if err != nil { - //... - } - if assetBalancesSnapshot != nil { - snapshots = append(snapshots, assetBalancesSnapshot) - } - if wavesBalancesSnapshot != nil { - snapshots = append(snapshots, wavesBalancesSnapshot) - } - return snapshots, nil - // TODO should be a snapshot about the quantity - case proto.ReissueTransaction: // 5 - var reissue proto.Reissue - switch t := tx.(type) { - case *proto.ReissueWithSig: - reissue = t.Reissue - case *proto.ReissueWithProofs: - reissue = t.Reissue - default: - // return err - } - assetInfo, err := s.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(reissue.AssetID)) - if err != nil { - // ... - } - senderAddress, err := proto.NewAddressFromPublicKey(scheme, reissue.SenderPK) - if err != nil { - //... - } - senderBalance, err := s.wavesBalanceByAddress(senderAddress) - if err != nil { - //... - } - // TODO validate balances - wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ - {address: &senderAddress, balance: senderBalance - reissue.Fee}}, - } - snapshots = append(snapshots, wavesBalancesSnapshot) - // TODO can you make an asset reissuable again? - if assetInfo.reissuable != reissue.Reissuable { - assetReissuabilitySnapshot := &AssetReissuabilitySnapshot{ - assetID: proto.AssetIDFromDigest(reissue.AssetID), - isReissuable: reissue.Reissuable, - } - snapshots = append(snapshots, assetReissuabilitySnapshot) - } - return snapshots, nil - case proto.BurnTransaction: // 6 - - case proto.ExchangeTransaction: // 7 - - case proto.LeaseTransaction: // 8 - - case proto.LeaseCancelTransaction: // 9 - - case proto.CreateAliasTransaction: // 10 - - case proto.MassTransferTransaction: // 11 - case proto.DataTransaction: // 12 - case proto.SetScriptTransaction: // 13 - case proto.SponsorshipTransaction: // 14 - case proto.SetAssetScriptTransaction: // 15 - case proto.InvokeScriptTransaction: // 16 - case proto.UpdateAssetInfoTransaction: // 17 - case proto.EthereumMetamaskTransaction: // 18 - } - return snapshots, nil -} - -func (s SnapshotManager) optionalAssetBalanceSnapshotTransfer(sender proto.WavesAddress, recipient proto.WavesAddress, amountAsset proto.OptionalAsset, - amount uint64, feeAsset proto.OptionalAsset, fee uint64) (*AssetBalancesSnapshot, *WavesBalancesSnapshot, error) { - - if amountAsset.Present { - senderAssetBalance, err := s.stor.balances.assetBalance(sender.ID(), proto.AssetIDFromDigest(amountAsset.ID)) - if err != nil { - //... - } - recipientAssetBalance, err := s.stor.balances.assetBalance(recipient.ID(), proto.AssetIDFromDigest(amountAsset.ID)) - if err != nil { - //... - } - if feeAsset.Present { - return &AssetBalancesSnapshot{assetBalances: []balanceAsset{ - {address: sender, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: senderAssetBalance - amount - fee}, - {address: recipient, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: recipientAssetBalance + amount}, - }}, nil, nil - } - - senderWavesBalance, err := s.stor.balances.wavesBalance(sender.ID()) - if err != nil { - //... - } - return &AssetBalancesSnapshot{assetBalances: []balanceAsset{ - {address: sender, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: senderAssetBalance - amount}, - {address: recipient, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: recipientAssetBalance + amount}, - }}, &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ - {address: sender, balance: senderWavesBalance.balance - fee}, - }}, nil - } - - senderWavesBalance, err := s.stor.balances.wavesBalance(sender.ID()) - if err != nil { - //... - } - recipientWavesBalance, err := s.stor.balances.wavesBalance(recipient.ID()) - if err != nil { - //... - } - if feeAsset.Present { - senderAssetBalance, err := s.stor.balances.assetBalance(sender.ID(), proto.AssetIDFromDigest(amountAsset.ID)) - if err != nil { - //... - } - return &AssetBalancesSnapshot{assetBalances: []balanceAsset{ - {address: sender, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: senderAssetBalance - fee}, - }}, &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ - {address: sender, balance: senderWavesBalance.balance - amount}, - {address: recipient, balance: recipientWavesBalance.balance + amount}, - }}, nil - } - - return nil, &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ - {address: sender, balance: senderWavesBalance.balance - fee - amount}, - {address: recipient, balance: senderWavesBalance.balance + amount}, - }}, nil -} - -func (s *SnapshotManager) wavesBalanceByAddress(address proto.WavesAddress) (uint64, error) { - recipientWavesBalanceProfile, err := s.stor.balances.wavesBalance(address.ID()) - if err != nil { - //... - } - return recipientWavesBalanceProfile.balance, nil -} +//import ( +// "github.com/wavesplatform/gowaves/pkg/proto" +//) +// +//func (s *SnapshotManager) TxSnapshotFromTx(tx proto.Transaction, scheme proto.Scheme) (TransactionSnapshot, error) { +// var snapshots []AtomicSnapshot +// +// switch tx.GetTypeInfo().Type { +// case proto.GenesisTransaction: // 1 +// genesisTx, ok := tx.(*proto.Genesis) +// if !ok { +// // ... +// } +// wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ +// {address: &genesisTx.Recipient, balance: genesisTx.Amount}}, +// } +// snapshots = append(snapshots, wavesBalancesSnapshot) +// return snapshots, nil +// case proto.PaymentTransaction: // 2 +// paymentTx, ok := tx.(*proto.Payment) +// if !ok { +// // ... +// } +// senderAddress, err := proto.NewAddressFromPublicKey(scheme, paymentTx.SenderPK) +// if err != nil { +// //... +// } +// senderBalance, err := s.wavesBalanceByAddress(senderAddress) +// if err != nil { +// //... +// } +// recipientBalance, err := s.wavesBalanceByAddress(paymentTx.Recipient) +// if err != nil { +// //... +// } +// +// +// wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ +// {address: &senderAddress, balance: senderBalance - paymentTx.Amount - paymentTx.Fee}, +// {address: &paymentTx.Recipient, balance: recipientBalance + paymentTx.Amount}}, +// } +// snapshots = append(snapshots, wavesBalancesSnapshot) +// return snapshots, nil +// case proto.IssueTransaction: // 3 +// var issue proto.Issue +// switch i := tx.(type) { +// case *proto.IssueWithSig: +// issue = i.Issue +// case *proto.IssueWithProofs: +// issue = i.Issue +// default: +// // return err +// } +// senderAddress, err := proto.NewAddressFromPublicKey(scheme, issue.SenderPK) +// if err != nil { +// //... +// } +// senderBalance, err := s.wavesBalanceByAddress(senderAddress) +// if err != nil { +// //... +// } +// wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ +// {address: &senderAddress, balance: senderBalance - issue.Fee}}, +// } +// +// assetsSnapshot := &AssetDescriptionSnapshot{ +// assetID: proto.AssetID{}, +// assetName: &issue.Name, +// assetDescription: issue.Description, +// changeHeight: 0, +// } +// +// snapshots = append(snapshots, wavesBalancesSnapshot, assetsSnapshot) +// return snapshots, nil +// case proto.TransferTransaction: // 4 +// var transfer proto.Transfer +// switch t := tx.(type) { +// case *proto.TransferWithSig: +// transfer = t.Transfer +// case *proto.TransferWithProofs: +// transfer = t.Transfer +// default: +// // return err +// } +// senderAddress, err := proto.NewAddressFromPublicKey(scheme, transfer.SenderPK) +// if err != nil { +// //... +// } +// recipientAddress := transfer.Recipient.Address() +// assetBalancesSnapshot, wavesBalancesSnapshot, err := s.optionalAssetBalanceSnapshotTransfer(senderAddress, *recipientAddress, transfer.AmountAsset, transfer.Amount, transfer.FeeAsset, transfer.Fee) +// if err != nil { +// //... +// } +// if assetBalancesSnapshot != nil { +// snapshots = append(snapshots, assetBalancesSnapshot) +// } +// if wavesBalancesSnapshot != nil { +// snapshots = append(snapshots, wavesBalancesSnapshot) +// } +// return snapshots, nil +// case proto.ReissueTransaction: // 5 +// var reissue proto.Reissue +// switch t := tx.(type) { +// case *proto.ReissueWithSig: +// reissue = t.Reissue +// case *proto.ReissueWithProofs: +// reissue = t.Reissue +// default: +// // return err +// } +// assetInfo, err := s.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(reissue.AssetID)) +// if err != nil { +// // ... +// } +// senderAddress, err := proto.NewAddressFromPublicKey(scheme, reissue.SenderPK) +// if err != nil { +// //... +// } +// senderBalance, err := s.wavesBalanceByAddress(senderAddress) +// if err != nil { +// //... +// } +// wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ +// {address: &senderAddress, balance: senderBalance - reissue.Fee}}, +// } +// snapshots = append(snapshots, wavesBalancesSnapshot) +// // TODO can you make an asset reissuable again? +// if assetInfo.reissuable != reissue.Reissuable { +// assetReissuabilitySnapshot := &AssetReissuabilitySnapshot{ +// assetID: proto.AssetIDFromDigest(reissue.AssetID), +// isReissuable: reissue.Reissuable, +// } +// snapshots = append(snapshots, assetReissuabilitySnapshot) +// } +// return snapshots, nil +// case proto.BurnTransaction: // 6 +// +// case proto.ExchangeTransaction: // 7 +// +// case proto.LeaseTransaction: // 8 +// +// case proto.LeaseCancelTransaction: // 9 +// +// case proto.CreateAliasTransaction: // 10 +// +// case proto.MassTransferTransaction: // 11 +// case proto.DataTransaction: // 12 +// case proto.SetScriptTransaction: // 13 +// case proto.SponsorshipTransaction: // 14 +// case proto.SetAssetScriptTransaction: // 15 +// case proto.InvokeScriptTransaction: // 16 +// case proto.UpdateAssetInfoTransaction: // 17 +// case proto.EthereumMetamaskTransaction: // 18 +// } +// return snapshots, nil +//} +// +//func (s SnapshotManager) optionalAssetBalanceSnapshotTransfer(sender proto.WavesAddress, recipient proto.WavesAddress, amountAsset proto.OptionalAsset, +// amount uint64, feeAsset proto.OptionalAsset, fee uint64) (*AssetBalancesSnapshot, *WavesBalancesSnapshot, error) { +// +// if amountAsset.Present { +// senderAssetBalance, err := s.stor.balances.assetBalance(sender.ID(), proto.AssetIDFromDigest(amountAsset.ID)) +// if err != nil { +// //... +// } +// recipientAssetBalance, err := s.stor.balances.assetBalance(recipient.ID(), proto.AssetIDFromDigest(amountAsset.ID)) +// if err != nil { +// //... +// } +// if feeAsset.Present { +// return &AssetBalancesSnapshot{assetBalances: []balanceAsset{ +// {address: sender, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: senderAssetBalance - amount - fee}, +// {address: recipient, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: recipientAssetBalance + amount}, +// }}, nil, nil +// } +// +// senderWavesBalance, err := s.stor.balances.wavesBalance(sender.ID()) +// if err != nil { +// //... +// } +// return &AssetBalancesSnapshot{assetBalances: []balanceAsset{ +// {address: sender, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: senderAssetBalance - amount}, +// {address: recipient, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: recipientAssetBalance + amount}, +// }}, &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ +// {address: sender, balance: senderWavesBalance.balance - fee}, +// }}, nil +// } +// +// senderWavesBalance, err := s.stor.balances.wavesBalance(sender.ID()) +// if err != nil { +// //... +// } +// recipientWavesBalance, err := s.stor.balances.wavesBalance(recipient.ID()) +// if err != nil { +// //... +// } +// if feeAsset.Present { +// senderAssetBalance, err := s.stor.balances.assetBalance(sender.ID(), proto.AssetIDFromDigest(amountAsset.ID)) +// if err != nil { +// //... +// } +// return &AssetBalancesSnapshot{assetBalances: []balanceAsset{ +// {address: sender, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: senderAssetBalance - fee}, +// }}, &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ +// {address: sender, balance: senderWavesBalance.balance - amount}, +// {address: recipient, balance: recipientWavesBalance.balance + amount}, +// }}, nil +// } +// +// return nil, &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ +// {address: sender, balance: senderWavesBalance.balance - fee - amount}, +// {address: recipient, balance: senderWavesBalance.balance + amount}, +// }}, nil +//} +// +//func (s *SnapshotManager) wavesBalanceByAddress(address proto.WavesAddress) (uint64, error) { +// recipientWavesBalanceProfile, err := s.stor.balances.wavesBalance(address.ID()) +// if err != nil { +// //... +// } +// return recipientWavesBalanceProfile.balance, nil +//} diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 7c38912b4..30b8553a9 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -42,152 +42,209 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, assetID crypto.Dig } if err := tp.stor.assets.issueAsset(proto.AssetIDFromDigest(assetID), assetInfo, info.blockID); err != nil { - return errors.Wrap(err, "failed to issue asset") + return nil, errors.Wrap(err, "failed to issue asset") } - sender := proto.MustAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) - issueSnapshot := StaticAssetInfoSnapshot{ - assetID: proto.AssetIDFromDigest(assetID), - issuer: sender, - isNFT: assetInfo.isNFT(), + issueStaticInfoSnapshot := &StaticAssetInfoSnapshot{ + assetID: proto.AssetIDFromDigest(assetID), + issuer: sender, + decimals: assetInfo.decimals, + isNFT: assetInfo.isNFT(), } - tp.stor.assets. - return nil + assetDescription := &AssetDescriptionSnapshot{ + assetID: proto.AssetIDFromDigest(assetID), + assetName: assetInfo.name, + assetDescription: assetInfo.description, + changeHeight: assetInfo.lastNameDescChangeHeight, + } + + assetReissuability := &AssetReissuabilitySnapshot{ + assetID: proto.AssetIDFromDigest(assetID), + isReissuable: assetInfo.reissuable, + } + + var snapshot TransactionSnapshot + snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) + return snapshot, nil } func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.IssueWithSig) if !ok { - return errors.New("failed to convert interface to IssueWithSig transaction") + return nil, errors.New("failed to convert interface to IssueWithSig transaction") } txID, err := tx.GetID(tp.settings.AddressSchemeCharacter) if err != nil { - return errors.Errorf("failed to get transaction ID: %v\n", err) + return nil, errors.Errorf("failed to get transaction ID: %v\n", err) } assetID, err := crypto.NewDigestFromBytes(txID) if err != nil { - return err + return nil, err } if err := tp.stor.scriptsStorage.setAssetScript(assetID, proto.Script{}, tx.SenderPK, info.blockID); err != nil { - return err + return nil, err } return tp.performIssue(&tx.Issue, assetID, info) } -func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.IssueWithProofs) if !ok { - return errors.New("failed to convert interface to IssueWithProofs transaction") + return nil, errors.New("failed to convert interface to IssueWithProofs transaction") } txID, err := tx.GetID(tp.settings.AddressSchemeCharacter) if err != nil { - return errors.Errorf("failed to get transaction ID: %v\n", err) + return nil, errors.Errorf("failed to get transaction ID: %v\n", err) } assetID, err := crypto.NewDigestFromBytes(txID) if err != nil { - return err + return nil, err } if err := tp.stor.scriptsStorage.setAssetScript(assetID, tx.Script, tx.SenderPK, info.blockID); err != nil { - return err + return nil, err } return tp.performIssue(&tx.Issue, assetID, info) } -func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performerInfo) error { +func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performerInfo) (TransactionSnapshot, error) { // Modify asset. change := &assetReissueChange{ reissuable: tx.Reissuable, diff: int64(tx.Quantity), } if err := tp.stor.assets.reissueAsset(proto.AssetIDFromDigest(tx.AssetID), change, info.blockID); err != nil { - return errors.Wrap(err, "failed to reissue asset") + return nil, errors.Wrap(err, "failed to reissue asset") } - return nil + + newestTokenInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(tx.AssetID)) + if err != nil { + return nil, errors.Wrap(err, "failed to pull the newest info for an asset") + } + + assetReissuability := &AssetReissuabilitySnapshot{ + assetID: proto.AssetIDFromDigest(tx.AssetID), + totalQuantity: newestTokenInfo.quantity, + isReissuable: change.reissuable, + } + + var snapshot TransactionSnapshot + snapshot = append(snapshot, assetReissuability) + return snapshot, nil } -func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.ReissueWithSig) if !ok { - return errors.New("failed to convert interface to ReissueWithSig transaction") + return nil, errors.New("failed to convert interface to ReissueWithSig transaction") } return tp.performReissue(&tx.Reissue, info) } -func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.ReissueWithProofs) if !ok { - return errors.New("failed to convert interface to ReissueWithProofs transaction") + return nil, errors.New("failed to convert interface to ReissueWithProofs transaction") } return tp.performReissue(&tx.Reissue, info) } -func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo) error { +func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo) (TransactionSnapshot, error) { // Modify asset. change := &assetBurnChange{ diff: int64(tx.Amount), } if err := tp.stor.assets.burnAsset(proto.AssetIDFromDigest(tx.AssetID), change, info.blockID); err != nil { - return errors.Wrap(err, "failed to burn asset") + return nil, errors.Wrap(err, "failed to burn asset") } - return nil + + newestTokenInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(tx.AssetID)) + if err != nil { + return nil, errors.Wrap(err, "failed to pull the newest info for an asset") + } + + assetReissuability := &AssetReissuabilitySnapshot{ + assetID: proto.AssetIDFromDigest(tx.AssetID), + totalQuantity: newestTokenInfo.quantity, + isReissuable: newestTokenInfo.reissuable, + } + + var snapshot TransactionSnapshot + snapshot = append(snapshot, assetReissuability) + return snapshot, nil } -func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.BurnWithSig) if !ok { - return errors.New("failed to convert interface to BurnWithSig transaction") + return nil, errors.New("failed to convert interface to BurnWithSig transaction") } return tp.performBurn(&tx.Burn, info) } -func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.BurnWithProofs) if !ok { - return errors.New("failed to convert interface to BurnWithProofs transaction") + return nil, errors.New("failed to convert interface to BurnWithProofs transaction") } return tp.performBurn(&tx.Burn, info) } -func (tp *transactionPerformer) increaseOrderVolume(order proto.Order, tx proto.Exchange, info *performerInfo) error { +func (tp *transactionPerformer) increaseOrderVolume(order proto.Order, tx proto.Exchange, info *performerInfo) (*FilledVolumeFeeSnapshot, error) { orderId, err := order.GetID() if err != nil { - return err + return nil, err } fee := tx.GetBuyMatcherFee() if order.GetOrderType() == proto.Sell { fee = tx.GetSellMatcherFee() } + volume := tx.GetAmount() + if err := tp.stor.ordersVolumes.increaseFilledFee(orderId, fee, info.blockID); err != nil { - return err + return nil, err } - if err := tp.stor.ordersVolumes.increaseFilledAmount(orderId, tx.GetAmount(), info.blockID); err != nil { - return err + if err := tp.stor.ordersVolumes.increaseFilledAmount(orderId, volume, info.blockID); err != nil { + return nil, err } - return nil + + volumeRecord, err := tp.stor.ordersVolumes.newestVolumeById(orderId) + + orderSnapshot := &FilledVolumeFeeSnapshot{ + orderID: orderId, + filledVolume: volumeRecord.amountFilled, + filledFee: volumeRecord.feeFilled, + } + + return orderSnapshot, nil } -func (tp *transactionPerformer) performExchange(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performExchange(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tx, ok := transaction.(proto.Exchange) if !ok { - return errors.New("failed to convert interface to Exchange transaction") + return nil, errors.New("failed to convert interface to Exchange transaction") } so, err := tx.GetSellOrder() if err != nil { - return errors.Wrap(err, "no sell order") + return nil, errors.Wrap(err, "no sell order") } - if err := tp.increaseOrderVolume(so, tx, info); err != nil { - return err + sellOrderSnapshot, err := tp.increaseOrderVolume(so, tx, info) + if err != nil { + return nil, err } bo, err := tx.GetBuyOrder() if err != nil { - return errors.Wrap(err, "no buy order") + return nil, errors.Wrap(err, "no buy order") } - if err := tp.increaseOrderVolume(bo, tx, info); err != nil { - return err + buyOrderSnapshot, err := tp.increaseOrderVolume(bo, tx, info) + if err != nil { + return nil, err } - return nil + + var snapshot TransactionSnapshot + snapshot = append(snapshot, sellOrderSnapshot, buyOrderSnapshot) + return snapshot, nil } func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, info *performerInfo) error { From 1ddae7af9614c7a31fe893c54a54f833601f1a7b Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 26 Apr 2023 01:56:56 -0500 Subject: [PATCH 08/27] Hanled lease transactions --- pkg/state/transaction_performer.go | 101 +++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 21 deletions(-) diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 30b8553a9..42d6b5410 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -47,21 +47,21 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, assetID crypto.Dig sender := proto.MustAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) issueStaticInfoSnapshot := &StaticAssetInfoSnapshot{ - assetID: proto.AssetIDFromDigest(assetID), + assetID: assetID, issuer: sender, decimals: assetInfo.decimals, isNFT: assetInfo.isNFT(), } assetDescription := &AssetDescriptionSnapshot{ - assetID: proto.AssetIDFromDigest(assetID), + assetID: assetID, assetName: assetInfo.name, assetDescription: assetInfo.description, changeHeight: assetInfo.lastNameDescChangeHeight, } assetReissuability := &AssetReissuabilitySnapshot{ - assetID: proto.AssetIDFromDigest(assetID), + assetID: assetID, isReissuable: assetInfo.reissuable, } @@ -124,7 +124,7 @@ func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performe } assetReissuability := &AssetReissuabilitySnapshot{ - assetID: proto.AssetIDFromDigest(tx.AssetID), + assetID: tx.AssetID, totalQuantity: newestTokenInfo.quantity, isReissuable: change.reissuable, } @@ -165,7 +165,7 @@ func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo) } assetReissuability := &AssetReissuabilitySnapshot{ - assetID: proto.AssetIDFromDigest(tx.AssetID), + assetID: tx.AssetID, totalQuantity: newestTokenInfo.quantity, isReissuable: newestTokenInfo.reissuable, } @@ -247,16 +247,16 @@ func (tp *transactionPerformer) performExchange(transaction proto.Transaction, i return snapshot, nil } -func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, info *performerInfo) error { +func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, info *performerInfo) (TransactionSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { - return err + return nil, err } var recipientAddr *proto.WavesAddress if addr := tx.Recipient.Address(); addr == nil { recipientAddr, err = tp.stor.aliases.newestAddrByAlias(tx.Recipient.Alias().Alias) if err != nil { - return errors.Errorf("invalid alias: %v\n", err) + return nil, errors.Errorf("invalid alias: %v\n", err) } } else { recipientAddr = addr @@ -271,46 +271,105 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, RecipientAlias: tx.Recipient.Alias(), } if err := tp.stor.leases.addLeasing(*id, l, info.blockID); err != nil { - return errors.Wrap(err, "failed to add leasing") + return nil, errors.Wrap(err, "failed to add leasing") } - return nil + leaseStatusSnapshot := &LeaseStatusSnapshot{ + leaseID: *id, + isActive: true, + } + + // TODO check if the balance will be updated immediately after the leasing + senderBalanceProfile, err := tp.stor.balances.wavesBalance(senderAddr.ID()) + if err != nil { + return nil, errors.Wrap(err, "failed to receive sender's waves balance") + } + senderLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ + address: senderAddr, + leaseIn: senderBalanceProfile.leaseIn, + leaseOut: senderBalanceProfile.leaseOut, + } + + receiverBalanceProfile, err := tp.stor.balances.wavesBalance(recipientAddr.ID()) + if err != nil { + return nil, errors.Wrap(err, "failed to receive recipient's waves balance") + } + recipientLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ + address: *recipientAddr, + leaseIn: receiverBalanceProfile.leaseIn, + leaseOut: receiverBalanceProfile.leaseOut, + } + var snapshot TransactionSnapshot + snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) + return snapshot, nil } -func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseWithSig) if !ok { - return errors.New("failed to convert interface to LeaseWithSig transaction") + return nil, errors.New("failed to convert interface to LeaseWithSig transaction") } return tp.performLease(&tx.Lease, tx.ID, info) } -func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseWithProofs) if !ok { - return errors.New("failed to convert interface to LeaseWithProofs transaction") + return nil, errors.New("failed to convert interface to LeaseWithProofs transaction") } return tp.performLease(&tx.Lease, tx.ID, info) } -func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID *crypto.Digest, info *performerInfo) error { +func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID *crypto.Digest, info *performerInfo) (TransactionSnapshot, error) { if err := tp.stor.leases.cancelLeasing(tx.LeaseID, info.blockID, info.height, txID); err != nil { - return errors.Wrap(err, "failed to cancel leasing") + return nil, errors.Wrap(err, "failed to cancel leasing") } - return nil + leaseStatusSnapshot := &LeaseStatusSnapshot{ + leaseID: tx.LeaseID, + isActive: false, + } + + leasingInfo, err := tp.stor.leases.leasingInfo(tx.LeaseID) + if err != nil { + return nil, errors.Wrap(err, "failed to receiver leasing info") + } + + // TODO check if the balance will be updated immediately after the leasing + senderBalanceProfile, err := tp.stor.balances.wavesBalance(leasingInfo.Sender.ID()) + if err != nil { + return nil, errors.Wrap(err, "failed to receive sender's waves balance") + } + senderLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ + address: leasingInfo.Sender, + leaseIn: senderBalanceProfile.leaseIn, + leaseOut: senderBalanceProfile.leaseOut, + } + + receiverBalanceProfile, err := tp.stor.balances.wavesBalance(leasingInfo.Recipient.ID()) + if err != nil { + return nil, errors.Wrap(err, "failed to receive recipient's waves balance") + } + recipientLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ + address: leasingInfo.Recipient, + leaseIn: receiverBalanceProfile.leaseIn, + leaseOut: receiverBalanceProfile.leaseOut, + } + var snapshot TransactionSnapshot + snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) + return snapshot, nil } -func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseCancelWithSig) if !ok { - return errors.New("failed to convert interface to LeaseCancelWithSig transaction") + return nil, errors.New("failed to convert interface to LeaseCancelWithSig transaction") } return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info) } -func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseCancelWithProofs) if !ok { - return errors.New("failed to convert interface to LeaseCancelWithProofs transaction") + return nil, errors.New("failed to convert interface to LeaseCancelWithProofs transaction") } return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info) } From e67edea4034e405f99b6d351b57c74561c5029e2 Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 10 May 2023 22:07:59 -0500 Subject: [PATCH 09/27] Finished performers --- pkg/state/transaction_performer.go | 212 +++++++++++++++++++---------- 1 file changed, 139 insertions(+), 73 deletions(-) diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 42d6b5410..cc4ee29a1 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -41,10 +41,6 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, assetID crypto.Dig }, } - if err := tp.stor.assets.issueAsset(proto.AssetIDFromDigest(assetID), assetInfo, info.blockID); err != nil { - return nil, errors.Wrap(err, "failed to issue asset") - } - sender := proto.MustAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) issueStaticInfoSnapshot := &StaticAssetInfoSnapshot{ assetID: assetID, @@ -65,6 +61,10 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, assetID crypto.Dig isReissuable: assetInfo.reissuable, } + if err := tp.stor.assets.issueAsset(proto.AssetIDFromDigest(assetID), assetInfo, info.blockID); err != nil { + return nil, errors.Wrap(err, "failed to issue asset") + } + var snapshot TransactionSnapshot snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) return snapshot, nil @@ -114,23 +114,26 @@ func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performe reissuable: tx.Reissuable, diff: int64(tx.Quantity), } - if err := tp.stor.assets.reissueAsset(proto.AssetIDFromDigest(tx.AssetID), change, info.blockID); err != nil { - return nil, errors.Wrap(err, "failed to reissue asset") - } - newestTokenInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(tx.AssetID)) + assetInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(tx.AssetID)) if err != nil { - return nil, errors.Wrap(err, "failed to pull the newest info for an asset") + return nil, err } + quantityDiff := big.NewInt(change.diff) + resQuantity := assetInfo.quantity.Add(&assetInfo.quantity, quantityDiff) assetReissuability := &AssetReissuabilitySnapshot{ assetID: tx.AssetID, - totalQuantity: newestTokenInfo.quantity, + totalQuantity: *resQuantity, isReissuable: change.reissuable, } var snapshot TransactionSnapshot snapshot = append(snapshot, assetReissuability) + + if err := tp.stor.assets.reissueAsset(proto.AssetIDFromDigest(tx.AssetID), change, info.blockID); err != nil { + return nil, errors.Wrap(err, "failed to reissue asset") + } return snapshot, nil } @@ -155,23 +158,26 @@ func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo) change := &assetBurnChange{ diff: int64(tx.Amount), } - if err := tp.stor.assets.burnAsset(proto.AssetIDFromDigest(tx.AssetID), change, info.blockID); err != nil { - return nil, errors.Wrap(err, "failed to burn asset") - } - newestTokenInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(tx.AssetID)) + assetInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(tx.AssetID)) if err != nil { - return nil, errors.Wrap(err, "failed to pull the newest info for an asset") + return nil, err } - + quantityDiff := big.NewInt(change.diff) + resQuantity := assetInfo.quantity.Sub(&assetInfo.quantity, quantityDiff) assetReissuability := &AssetReissuabilitySnapshot{ assetID: tx.AssetID, - totalQuantity: newestTokenInfo.quantity, - isReissuable: newestTokenInfo.reissuable, + totalQuantity: *resQuantity, + isReissuable: assetInfo.reissuable, } var snapshot TransactionSnapshot snapshot = append(snapshot, assetReissuability) + + if err := tp.stor.assets.burnAsset(proto.AssetIDFromDigest(tx.AssetID), change, info.blockID); err != nil { + return nil, errors.Wrap(err, "failed to burn asset") + } + return snapshot, nil } @@ -202,19 +208,25 @@ func (tp *transactionPerformer) increaseOrderVolume(order proto.Order, tx proto. } volume := tx.GetAmount() - if err := tp.stor.ordersVolumes.increaseFilledFee(orderId, fee, info.blockID); err != nil { + newestFilledFee, err := tp.stor.ordersVolumes.newestFilledFee(orderId) + if err != nil { return nil, err } - if err := tp.stor.ordersVolumes.increaseFilledAmount(orderId, volume, info.blockID); err != nil { + newestFilledAmount, err := tp.stor.ordersVolumes.newestFilledAmount(orderId) + if err != nil { return nil, err } - - volumeRecord, err := tp.stor.ordersVolumes.newestVolumeById(orderId) - orderSnapshot := &FilledVolumeFeeSnapshot{ orderID: orderId, - filledVolume: volumeRecord.amountFilled, - filledFee: volumeRecord.feeFilled, + filledFee: newestFilledFee + fee, + filledVolume: newestFilledAmount + volume, + } + + if err := tp.stor.ordersVolumes.increaseFilledFee(orderId, fee, info.blockID); err != nil { + return nil, err + } + if err := tp.stor.ordersVolumes.increaseFilledAmount(orderId, volume, info.blockID); err != nil { + return nil, err } return orderSnapshot, nil @@ -270,15 +282,12 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, Status: LeaseActive, RecipientAlias: tx.Recipient.Alias(), } - if err := tp.stor.leases.addLeasing(*id, l, info.blockID); err != nil { - return nil, errors.Wrap(err, "failed to add leasing") - } + leaseStatusSnapshot := &LeaseStatusSnapshot{ leaseID: *id, isActive: true, } - // TODO check if the balance will be updated immediately after the leasing senderBalanceProfile, err := tp.stor.balances.wavesBalance(senderAddr.ID()) if err != nil { return nil, errors.Wrap(err, "failed to receive sender's waves balance") @@ -286,7 +295,7 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, senderLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ address: senderAddr, leaseIn: senderBalanceProfile.leaseIn, - leaseOut: senderBalanceProfile.leaseOut, + leaseOut: senderBalanceProfile.leaseOut + int64(tx.Amount), } receiverBalanceProfile, err := tp.stor.balances.wavesBalance(recipientAddr.ID()) @@ -295,9 +304,14 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, } recipientLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ address: *recipientAddr, - leaseIn: receiverBalanceProfile.leaseIn, + leaseIn: receiverBalanceProfile.leaseIn + int64(tx.Amount), leaseOut: receiverBalanceProfile.leaseOut, } + + if err := tp.stor.leases.addLeasing(*id, l, info.blockID); err != nil { + return nil, errors.Wrap(err, "failed to add leasing") + } + var snapshot TransactionSnapshot snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) return snapshot, nil @@ -374,130 +388,172 @@ func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.T return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info) } -func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info *performerInfo) error { +func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info *performerInfo) (TransactionSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { - return err + return nil, err } + // Save alias to aliases storage. inf := &aliasInfo{ stolen: tp.stor.aliases.exists(tx.Alias.Alias), addr: senderAddr, } + + aliasSnapshot := &AliasSnapshot{ + address: senderAddr, + alias: tx.Alias, + } + var snapshot TransactionSnapshot + snapshot = append(snapshot, aliasSnapshot) + if err := tp.stor.aliases.createAlias(tx.Alias.Alias, inf, info.blockID); err != nil { - return err + return nil, err } - return nil + return snapshot, nil } -func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.CreateAliasWithSig) if !ok { - return errors.New("failed to convert interface to CreateAliasWithSig transaction") + return nil, errors.New("failed to convert interface to CreateAliasWithSig transaction") } return tp.performCreateAlias(&tx.CreateAlias, info) } -func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.CreateAliasWithProofs) if !ok { - return errors.New("failed to convert interface to CreateAliasWithProofs transaction") + return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") } return tp.performCreateAlias(&tx.CreateAlias, info) } -func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.DataWithProofs) if !ok { - return errors.New("failed to convert interface to DataWithProofs transaction") + return nil, errors.New("failed to convert interface to DataWithProofs transaction") } senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { - return err + return nil, err } + + dataEntriesSnapshot := &DataEntriesSnapshot{ + address: senderAddr, + dataEntries: tx.Entries, + } + var snapshot TransactionSnapshot + snapshot = append(snapshot, dataEntriesSnapshot) + for _, entry := range tx.Entries { if err := tp.stor.accountsDataStor.appendEntry(senderAddr, entry, info.blockID); err != nil { - return err + return nil, err } } - return nil + return snapshot, nil } -func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.SponsorshipWithProofs) if !ok { - return errors.New("failed to convert interface to SponsorshipWithProofs transaction") + return nil, errors.New("failed to convert interface to SponsorshipWithProofs transaction") + } + sponsorshipSnapshot := &SponsorshipSnapshot{ + assetID: tx.AssetID, + minSponsoredFee: tx.MinAssetFee, } + var snapshot TransactionSnapshot + snapshot = append(snapshot, sponsorshipSnapshot) + if err := tp.stor.sponsoredAssets.sponsorAsset(tx.AssetID, tx.MinAssetFee, info.blockID); err != nil { - return errors.Wrap(err, "failed to sponsor asset") + return nil, errors.Wrap(err, "failed to sponsor asset") } - return nil + return snapshot, nil } -func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.SetScriptWithProofs) if !ok { - return errors.New("failed to convert interface to SetScriptWithProofs transaction") + return nil, errors.New("failed to convert interface to SetScriptWithProofs transaction") } senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { - return err + return nil, err + } + sponsorshipSnapshot := &AccountScriptSnapshot{ + address: senderAddr, + script: tx.Script, } + var snapshot TransactionSnapshot + snapshot = append(snapshot, sponsorshipSnapshot) + if err := tp.stor.scriptsStorage.setAccountScript(senderAddr, tx.Script, tx.SenderPK, info.blockID); err != nil { - return errors.Wrap(err, "failed to set account script") + return nil, errors.Wrap(err, "failed to set account script") } - return nil + return snapshot, nil } -func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.SetAssetScriptWithProofs) if !ok { - return errors.New("failed to convert interface to SetAssetScriptWithProofs transaction") + return nil, errors.New("failed to convert interface to SetAssetScriptWithProofs transaction") } + + sponsorshipSnapshot := &AssetScriptSnapshot{ + assetID: tx.AssetID, + script: tx.Script, + } + var snapshot TransactionSnapshot + snapshot = append(snapshot, sponsorshipSnapshot) + if err := tp.stor.scriptsStorage.setAssetScript(tx.AssetID, tx.Script, tx.SenderPK, info.blockID); err != nil { - return errors.Wrap(err, "failed to set asset script") + return nil, errors.Wrap(err, "failed to set asset script") } - return nil + return snapshot, nil } -func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { if _, ok := transaction.(*proto.InvokeScriptWithProofs); !ok { - return errors.New("failed to convert interface to InvokeScriptWithProofs transaction") + return nil, errors.New("failed to convert interface to InvokeScriptWithProofs transaction") } if err := tp.stor.commitUncertain(info.blockID); err != nil { - return errors.Wrap(err, "failed to commit invoke changes") + return nil, errors.Wrap(err, "failed to commit invoke changes") } - return nil + // TODO + return nil, nil } -func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { if _, ok := transaction.(*proto.InvokeExpressionTransactionWithProofs); !ok { - return errors.New("failed to convert interface to InvokeExpressionWithProofs transaction") + return nil, errors.New("failed to convert interface to InvokeExpressionWithProofs transaction") } if err := tp.stor.commitUncertain(info.blockID); err != nil { - return errors.Wrap(err, "failed to commit invoke changes") + return nil, errors.Wrap(err, "failed to commit invoke changes") } - return nil + // TODO + return nil, nil } -func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { ethTx, ok := transaction.(*proto.EthereumTransaction) if !ok { - return errors.New("failed to convert interface to EthereumTransaction transaction") + return nil, errors.New("failed to convert interface to EthereumTransaction transaction") } if _, ok := ethTx.TxKind.(*proto.EthereumInvokeScriptTxKind); ok { if err := tp.stor.commitUncertain(info.blockID); err != nil { - return errors.Wrap(err, "failed to commit invoke changes") + return nil, errors.Wrap(err, "failed to commit invoke changes") } } // nothing to do for proto.EthereumTransferWavesTxKind and proto.EthereumTransferAssetsErc20TxKind - return nil + // TODO + return nil, nil } -func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.UpdateAssetInfoWithProofs) if !ok { - return errors.New("failed to convert interface to UpdateAssetInfoWithProofs transaction") + return nil, errors.New("failed to convert interface to UpdateAssetInfoWithProofs transaction") } blockHeight := info.height + 1 ch := &assetInfoChange{ @@ -505,8 +561,18 @@ func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction pro newDescription: tx.Description, newHeight: blockHeight, } + + sponsorshipSnapshot := &AssetDescriptionSnapshot{ + assetID: tx.AssetID, + assetName: tx.Name, + assetDescription: tx.Description, + changeHeight: blockHeight, + } + var snapshot TransactionSnapshot + snapshot = append(snapshot, sponsorshipSnapshot) + if err := tp.stor.assets.updateAssetInfo(tx.AssetID, ch, info.blockID); err != nil { - return errors.Wrap(err, "failed to update asset info") + return nil, errors.Wrap(err, "failed to update asset info") } - return nil + return snapshot, nil } From a590cbb7a09e06c97b82b14e0fc5c5317bf50a5b Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 22 May 2023 01:39:16 -0500 Subject: [PATCH 10/27] Added snapshots for all types of transactions --- pkg/state/appender.go | 68 +++-- pkg/state/invoke_applier.go | 77 ++--- pkg/state/invoke_applier_test.go | 10 +- pkg/state/state.go | 5 + pkg/state/transaction_handler.go | 15 +- pkg/state/transaction_performer.go | 438 +++++++++++++++++++++++++---- 6 files changed, 490 insertions(+), 123 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index f21bda374..23eb9bb19 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -326,7 +326,7 @@ func (a *txAppender) saveTransactionIdByAddresses(addresses []proto.WavesAddress return nil } -func (a *txAppender) commitTxApplication(tx proto.Transaction, params *appendTxParams, res *applicationResult) (TransactionSnapshot, error) { +func (a *txAppender) commitTxApplication(tx proto.Transaction, params *appendTxParams, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { // Add transaction ID to recent IDs. txID, err := tx.GetID(a.settings.AddressSchemeCharacter) if err != nil { @@ -334,29 +334,33 @@ func (a *txAppender) commitTxApplication(tx proto.Transaction, params *appendTxP } a.recentTxIds[string(txID)] = empty // Update script runs. - a.totalScriptsRuns += res.totalScriptsRuns + a.totalScriptsRuns += applicationRes.totalScriptsRuns // Update complexity. a.sc.addRecentTxComplexity() // Save balance diff. - if err := a.diffStor.saveTxDiff(res.changes.diff); err != nil { + // TODO get balances snapshots + if err := a.diffStor.saveTxDiff(applicationRes.changes.diff); err != nil { return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to save balance diff: %v", err)) } - // Perform state changes. + currentMinerAddress := proto.MustAddressFromPublicKey(a.settings.AddressSchemeCharacter, params.currentMinerPK) + var snapshot TransactionSnapshot - if res.status { + if applicationRes.status { // We only perform tx in case it has not failed. performerInfo := &performerInfo{ - height: params.checkerInfo.height, - blockID: params.checkerInfo.blockID, + height: params.checkerInfo.height, + blockID: params.checkerInfo.blockID, + currentMinerAddress: currentMinerAddress, } - snapshot, err := a.txHandler.performTx(tx, performerInfo) + // TODO other snapshots + snapshot, err = a.txHandler.performTx(tx, performerInfo, invocationRes, applicationRes) if err != nil { return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to perform: %v", err)) } } if params.validatingUtx { // Save transaction to in-mem storage. - if err := a.rw.writeTransactionToMem(tx, !res.status); err != nil { + if err := a.rw.writeTransactionToMem(tx, !applicationRes.status); err != nil { return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to write transaction to in mem stor: %v", err)) } } else { @@ -365,7 +369,7 @@ func (a *txAppender) commitTxApplication(tx proto.Transaction, params *appendTxP return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to count miner fee: %v", err)) } // Save transaction to storage. - if err := a.rw.writeTransaction(tx, !res.status); err != nil { + if err := a.rw.writeTransaction(tx, !applicationRes.status); err != nil { return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to write transaction to storage: %v", err)) } } @@ -411,18 +415,20 @@ type appendTxParams struct { consensusImprovementsActivated bool invokeExpressionActivated bool // TODO: check feature naming validatingUtx bool // if validatingUtx == false then chans MUST be initialized with non nil value + currentMinerPK crypto.PublicKey + previousMinerPK crypto.PublicKey } -func (a *txAppender) handleInvokeOrExchangeTransaction(tx proto.Transaction, fallibleInfo *fallibleValidationParams) (*applicationResult, error) { - applicationRes, err := a.handleFallible(tx, fallibleInfo) +func (a *txAppender) handleInvokeOrExchangeTransaction(tx proto.Transaction, fallibleInfo *fallibleValidationParams) (*invocationResult, *applicationResult, error) { + invocationRes, applicationRes, err := a.handleFallible(tx, fallibleInfo) if err != nil { msg := "fallible validation failed" if txID, err2 := tx.GetID(a.settings.AddressSchemeCharacter); err2 == nil { msg = fmt.Sprintf("fallible validation failed for transaction '%s'", base58.Encode(txID)) } - return nil, errs.Extend(err, msg) + return nil, nil, errs.Extend(err, msg) } - return applicationRes, nil + return invocationRes, applicationRes, nil } func (a *txAppender) handleDefaultTransaction(tx proto.Transaction, params *appendTxParams, accountHasVerifierScript bool) (*applicationResult, error) { @@ -476,13 +482,14 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro // Check tx against state, check tx scripts, calculate balance changes. var applicationRes *applicationResult + var invocationResult *invocationResult needToValidateBalanceDiff := false switch tx.GetTypeInfo().Type { case proto.InvokeScriptTransaction, proto.InvokeExpressionTransaction, proto.ExchangeTransaction: // Invoke and Exchange transactions should be handled differently. // They may fail, and will be saved to blockchain anyway. fallibleInfo := &fallibleValidationParams{appendTxParams: params, senderScripted: accountHasVerifierScript, senderAddress: senderAddr} - applicationRes, err = a.handleInvokeOrExchangeTransaction(tx, fallibleInfo) + invocationResult, applicationRes, err = a.handleInvokeOrExchangeTransaction(tx, fallibleInfo) if err != nil { return errors.Errorf("failed to handle invoke or exchange transaction, %v", err) } @@ -514,7 +521,7 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro senderScripted: accountHasVerifierScript, senderAddress: senderAddr, } - applicationRes, err = a.handleInvokeOrExchangeTransaction(tx, fallibleInfo) + invocationResult, applicationRes, err = a.handleInvokeOrExchangeTransaction(tx, fallibleInfo) if err != nil { return errors.Errorf( "failed to handle ethereum invoke script transaction (type %s) with id %s, on height %d: %v", @@ -550,11 +557,15 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro return errs.Extend(err, "get transaction id") } - snapshot, err := a.commitTxApplication(tx, params, applicationRes) + // invocationResult may be empty if it was not an Invoke Transaction + snapshot, err := a.commitTxApplication(tx, params, invocationResult, applicationRes) if err != nil { zap.S().Errorf("failed to commit transaction (id %s) after successful validation; this should NEVER happen", base58.Encode(txID)) return err } + { + snapshot = snapshot + } // Store additional data for API: transaction by address. if !params.validatingUtx && a.buildApiData { if err := a.saveTransactionIdByAddresses(applicationRes.changes.addresses(), txID, blockID); err != nil { @@ -632,6 +643,8 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { consensusImprovementsActivated: consensusImprovementsActivated, invokeExpressionActivated: invokeExpressionActivated, validatingUtx: false, + currentMinerPK: params.block.GeneratorPublicKey, + previousMinerPK: params.parent.GeneratorPublicKey, } if err := a.appendTx(tx, appendTxArgs); err != nil { return err @@ -668,7 +681,7 @@ type applicationResult struct { changes txBalanceChanges } -func (a *txAppender) handleInvoke(tx proto.Transaction, info *fallibleValidationParams) (*applicationResult, error) { +func (a *txAppender) handleInvoke(tx proto.Transaction, info *fallibleValidationParams) (*invocationResult, *applicationResult, error) { var ID crypto.Digest switch t := tx.(type) { case *proto.InvokeScriptWithProofs: @@ -680,17 +693,17 @@ func (a *txAppender) handleInvoke(tx proto.Transaction, info *fallibleValidation case *proto.EthereumInvokeScriptTxKind: ID = *t.ID default: - return nil, errors.Errorf("unexpected ethereum tx kind (%T)", tx) + return nil, nil, errors.Errorf("unexpected ethereum tx kind (%T)", tx) } default: - return nil, errors.Errorf("failed to handle invoke: wrong type of transaction (%T)", tx) + return nil, nil, errors.Errorf("failed to handle invoke: wrong type of transaction (%T)", tx) } - res, err := a.ia.applyInvokeScript(tx, info) + invocationRes, applicationRes, err := a.ia.applyInvokeScript(tx, info) if err != nil { zap.S().Debugf("failed to apply InvokeScript transaction %s to state: %v", ID.String(), err) - return nil, err + return nil, nil, err } - return res, nil + return invocationRes, applicationRes, nil } func (a *txAppender) countExchangeScriptsRuns(scriptsRuns uint64) (uint64, error) { @@ -797,19 +810,20 @@ func (a *txAppender) handleExchange(tx proto.Transaction, info *fallibleValidati return &applicationResult{true, scriptsRuns, successfulChanges}, nil } -func (a *txAppender) handleFallible(tx proto.Transaction, info *fallibleValidationParams) (*applicationResult, error) { +func (a *txAppender) handleFallible(tx proto.Transaction, info *fallibleValidationParams) (*invocationResult, *applicationResult, error) { if info.acceptFailed { if err := a.checkTxFees(tx, info); err != nil { - return nil, err + return nil, nil, err } } switch tx.GetTypeInfo().Type { case proto.InvokeScriptTransaction, proto.InvokeExpressionTransaction, proto.EthereumMetamaskTransaction: return a.handleInvoke(tx, info) case proto.ExchangeTransaction: - return a.handleExchange(tx, info) + applicationRes, err := a.handleExchange(tx, info) + return nil, applicationRes, err } - return nil, errors.New("transaction is not fallible") + return nil, nil, errors.New("transaction is not fallible") } // For UTX validation. diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index 13489fdb4..b370fcc95 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -728,7 +728,7 @@ func (ia *invokeApplier) fallibleValidation(tx proto.Transaction, info *addlInvo // If the transaction does not fail, changes are committed (moved from uncertain to normal storage) // later in performInvokeScriptWithProofs(). // If the transaction fails, performInvokeScriptWithProofs() is not called and changes are discarded later using dropUncertain(). -func (ia *invokeApplier) applyInvokeScript(tx proto.Transaction, info *fallibleValidationParams) (*applicationResult, error) { +func (ia *invokeApplier) applyInvokeScript(tx proto.Transaction, info *fallibleValidationParams) (*invocationResult, *applicationResult, error) { // In defer we should clean all the temp changes invoke does to state. defer func() { ia.invokeDiffStor.invokeDiffsStor.reset() @@ -747,34 +747,34 @@ func (ia *invokeApplier) applyInvokeScript(tx proto.Transaction, info *fallibleV var err error scriptAddr, err = recipientToAddress(transaction.ScriptRecipient, ia.stor.aliases) if err != nil { - return nil, errors.Wrap(err, "recipientToAddress() failed") + return nil, nil, errors.Wrap(err, "recipientToAddress() failed") } paymentsLength = len(transaction.Payments) txID = *transaction.ID sender, err = proto.NewAddressFromPublicKey(ia.settings.AddressSchemeCharacter, transaction.SenderPK) if err != nil { - return nil, errors.Wrapf(err, "failed to apply script invocation") + return nil, nil, errors.Wrapf(err, "failed to apply script invocation") } tree, err = ia.stor.scriptsStorage.newestScriptByAddr(*scriptAddr) if err != nil { - return nil, errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptAddr.String()) + return nil, nil, errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptAddr.String()) } si, err := ia.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptAddr.ID()) if err != nil { - return nil, errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptAddr.String()) + return nil, nil, errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptAddr.String()) } scriptPK = si.PK case *proto.InvokeExpressionTransactionWithProofs: addr, err := proto.NewAddressFromPublicKey(ia.settings.AddressSchemeCharacter, transaction.SenderPK) if err != nil { - return nil, errors.Wrap(err, "recipientToAddress() failed") + return nil, nil, errors.Wrap(err, "recipientToAddress() failed") } sender = addr scriptAddr = &addr tree, err = serialization.Parse(transaction.Expression) if err != nil { - return nil, errors.Wrap(err, "failed to parse decoded invoke expression into tree") + return nil, nil, errors.Wrap(err, "failed to parse decoded invoke expression into tree") } txID = *transaction.ID scriptPK = transaction.SenderPK @@ -783,27 +783,27 @@ func (ia *invokeApplier) applyInvokeScript(tx proto.Transaction, info *fallibleV var err error scriptAddr, err = transaction.WavesAddressTo(ia.settings.AddressSchemeCharacter) if err != nil { - return nil, err + return nil, nil, err } decodedData := transaction.TxKind.DecodedData() paymentsLength = len(decodedData.Payments) txID = *transaction.ID sender, err = transaction.WavesAddressFrom(ia.settings.AddressSchemeCharacter) if err != nil { - return nil, errors.Wrapf(err, "failed to apply script invocation") + return nil, nil, errors.Wrapf(err, "failed to apply script invocation") } tree, err = ia.stor.scriptsStorage.newestScriptByAddr(*scriptAddr) if err != nil { - return nil, errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptAddr.String()) + return nil, nil, errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptAddr.String()) } si, err := ia.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptAddr.ID()) if err != nil { - return nil, errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptAddr.String()) + return nil, nil, errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptAddr.String()) } scriptPK = si.PK default: - return nil, errors.Errorf("failed to apply an invoke script: unexpected type of transaction (%T)", tx) + return nil, nil, errors.Errorf("failed to apply an invoke script: unexpected type of transaction (%T)", tx) } // If BlockV5 feature is not activated, we never accept failed transactions. @@ -812,32 +812,32 @@ func (ia *invokeApplier) applyInvokeScript(tx proto.Transaction, info *fallibleV if info.senderScripted { if err := ia.sc.callAccountScriptWithTx(tx, info.appendTxParams); err != nil { // Never accept invokes with failed script on transaction sender. - return nil, err + return nil, nil, err } } // Basic checks against state. paymentSmartAssets, err := ia.txHandler.checkTx(tx, info.checkerInfo) if err != nil { - return nil, err + return nil, nil, err } // Check that the script's library supports multiple payments. // We don't have to check feature activation because we've done it before. if paymentsLength >= 2 && tree.LibVersion < ast.LibV4 { - return nil, errors.Errorf("multiple payments is not allowed for RIDE library version %d", tree.LibVersion) + return nil, nil, errors.Errorf("multiple payments is not allowed for RIDE library version %d", tree.LibVersion) } // Refuse payments to DApp itself since activation of BlockV5 (acceptFailed) and for DApps with StdLib V4. disableSelfTransfers := info.acceptFailed && tree.LibVersion >= 4 if disableSelfTransfers && paymentsLength > 0 { if sender == *scriptAddr { - return nil, errors.New("paying to DApp itself is forbidden since RIDE V4") + return nil, nil, errors.New("paying to DApp itself is forbidden since RIDE V4") } } // Basic differ for InvokeScript creates only fee and payment diff. // Create changes for both failed and successful scenarios. failedChanges, err := ia.blockDiffer.createFailedTransactionDiff(tx, info.block, newDifferInfo(info.blockInfo)) if err != nil { - return nil, err + return nil, nil, err } // Call script function. @@ -848,14 +848,15 @@ func (ia *invokeApplier) applyInvokeScript(tx proto.Transaction, info *fallibleV isCheap := int(ia.sc.recentTxComplexity) <= FailFreeInvokeComplexity if info.rideV6Activated { if !info.acceptFailed || isCheap { - return nil, errors.Wrapf( + return nil, nil, errors.Wrapf( err, "transaction rejected with spent complexity %d and following call stack:\n%s", ride.EvaluationErrorSpentComplexity(err), strings.Join(ride.EvaluationErrorCallStack(err), "\n"), ) } - res := &invocationResult{failed: true, code: proto.DAppError, text: err.Error(), changes: failedChanges} - return ia.handleInvocationResult(txID, info, res) + invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error(), changes: failedChanges} + applicationRes, err := ia.handleInvocationResult(txID, info, invocationRes) + return invocationRes, applicationRes, err } // Before RideV6 activation in the following cases the transaction is rejected: // 1) Failing of transactions is not activated yet, reject everything @@ -866,31 +867,35 @@ func (ia *invokeApplier) applyInvokeScript(tx proto.Transaction, info *fallibleV // Usual script error produced by user code or system functions. // We reject transaction if spent complexity is less than limit. if !info.acceptFailed || isCheap { // Reject transaction if no failed transactions or the transaction is cheap - return nil, errors.Wrapf( + return nil, nil, errors.Wrapf( err, "transaction rejected with spent complexity %d and following call stack:\n%s", ride.EvaluationErrorSpentComplexity(err), strings.Join(ride.EvaluationErrorCallStack(err), "\n"), ) } - res := &invocationResult{failed: true, code: proto.DAppError, text: err.Error(), changes: failedChanges} - return ia.handleInvocationResult(txID, info, res) + + invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error(), changes: failedChanges} + applicationRes, err := ia.handleInvocationResult(txID, info, invocationRes) + return invocationRes, applicationRes, err case ride.InternalInvocationError: // Special script error produced by internal script invocation or application of results. // Reject transaction after certain height rejectOnInvocationError := info.checkerInfo.height >= ia.settings.InternalInvokeCorrectFailRejectBehaviourAfterHeight if !info.acceptFailed || rejectOnInvocationError || isCheap { - return nil, errors.Wrapf( + return nil, nil, errors.Wrapf( err, "transaction rejected with spent complexity %d and following call stack:\n%s", ride.EvaluationErrorSpentComplexity(err), strings.Join(ride.EvaluationErrorCallStack(err), "\n"), ) } - res := &invocationResult{failed: true, code: proto.DAppError, text: err.Error(), changes: failedChanges} - return ia.handleInvocationResult(txID, info, res) + + invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error(), changes: failedChanges} + applicationRes, err := ia.handleInvocationResult(txID, info, invocationRes) + return invocationRes, applicationRes, err case ride.Undefined, ride.EvaluationFailure: // Unhandled or evaluator error - return nil, errors.Wrapf(err, "invocation of transaction '%s' failed", txID.String()) + return nil, nil, errors.Wrapf(err, "invocation of transaction '%s' failed", txID.String()) default: - return nil, errors.Wrapf(err, "invocation of transaction '%s' failed", txID.String()) + return nil, nil, errors.Wrapf(err, "invocation of transaction '%s' failed", txID.String()) } } var scriptRuns uint64 = 0 @@ -898,7 +903,7 @@ func (ia *invokeApplier) applyInvokeScript(tx proto.Transaction, info *fallibleV if !info.rideV5Activated { actionScriptRuns, err := ia.countActionScriptRuns(r.ScriptActions()) if err != nil { - return nil, errors.Wrap(err, "failed to countActionScriptRuns") + return nil, nil, errors.Wrap(err, "failed to countActionScriptRuns") } scriptRuns += uint64(len(paymentSmartAssets)) + actionScriptRuns } @@ -907,7 +912,7 @@ func (ia *invokeApplier) applyInvokeScript(tx proto.Transaction, info *fallibleV if info.rideV5Activated { treeEstimation, err := ia.stor.scriptsComplexity.newestScriptComplexityByAddr(info.senderAddress, info.checkerInfo.estimatorVersion()) if err != nil { - return nil, errors.Wrap(err, "invoke failed to get verifier complexity") + return nil, nil, errors.Wrap(err, "invoke failed to get verifier complexity") } if treeEstimation.Verifier > FreeVerifierComplexity { scriptRuns++ @@ -916,7 +921,7 @@ func (ia *invokeApplier) applyInvokeScript(tx proto.Transaction, info *fallibleV scriptRuns++ } } - var res *invocationResult + var invocationRes *invocationResult code, changes, err := ia.fallibleValidation(tx, &addlInvokeInfo{ fallibleValidationParams: info, scriptAddr: scriptAddr, @@ -934,9 +939,9 @@ func (ia *invokeApplier) applyInvokeScript(tx proto.Transaction, info *fallibleV if !info.acceptFailed || (ia.sc.recentTxComplexity <= FailFreeInvokeComplexity && info.checkerInfo.height >= ia.settings.InternalInvokeCorrectFailRejectBehaviourAfterHeight) { - return nil, err + return nil, nil, err } - res = &invocationResult{ + invocationRes = &invocationResult{ failed: true, code: code, text: err.Error(), @@ -945,14 +950,16 @@ func (ia *invokeApplier) applyInvokeScript(tx proto.Transaction, info *fallibleV changes: changes, } } else { - res = &invocationResult{ + invocationRes = &invocationResult{ failed: false, scriptRuns: scriptRuns, actions: r.ScriptActions(), changes: changes, } } - return ia.handleInvocationResult(txID, info, res) + + applicationRes, err := ia.handleInvocationResult(txID, info, invocationRes) + return invocationRes, applicationRes, err } type invocationResult struct { diff --git a/pkg/state/invoke_applier_test.go b/pkg/state/invoke_applier_test.go index 974eab836..e9e3d9175 100644 --- a/pkg/state/invoke_applier_test.go +++ b/pkg/state/invoke_applier_test.go @@ -123,15 +123,15 @@ func (to *invokeApplierTestObjects) applyAndSaveInvoke(t *testing.T, tx *proto.I to.state.appender.ia.sc.resetComplexity() }() - res, err := to.state.appender.ia.applyInvokeScript(tx, info) + _, applicationRes, err := to.state.appender.ia.applyInvokeScript(tx, info) require.NoError(t, err) - err = to.state.appender.diffStor.saveTxDiff(res.changes.diff) + err = to.state.appender.diffStor.saveTxDiff(applicationRes.changes.diff) assert.NoError(t, err) - if res.status { + if applicationRes.status { err = to.state.stor.commitUncertain(info.checkerInfo.blockID) assert.NoError(t, err) } - return res + return applicationRes } func createGeneratedAsset(t *testing.T) (crypto.Digest, string) { @@ -189,7 +189,7 @@ func (id *invokeApplierTestData) applyTest(t *testing.T, to *invokeApplierTestOb tx := createInvokeScriptWithProofs(t, id.payments, id.fc, feeAsset, invokeFee) if id.errorRes { - _, err := to.state.appender.ia.applyInvokeScript(tx, id.info) + _, _, err := to.state.appender.ia.applyInvokeScript(tx, id.info) assert.Error(t, err) return } diff --git a/pkg/state/state.go b/pkg/state/state.go index 875846371..580aebb21 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -1005,6 +1005,11 @@ func (s *stateManager) addRewardVote(block *proto.Block, height uint64) error { return s.stor.monetaryPolicy.vote(block.RewardVote, height, activation, block.BlockID()) } +// rewards and 60% of the fee to the previous miner +func (s *stateManager) createInitialBlockSnapshot(block *proto.Block, height uint64, previousMinerPK proto.WavesAddress) { + +} + func (s *stateManager) addNewBlock(block, parent *proto.Block, chans *verifierChans, height uint64) error { blockHeight := height + 1 // Add score. diff --git a/pkg/state/transaction_handler.go b/pkg/state/transaction_handler.go index 6f1ae9eb6..28bcd40c4 100644 --- a/pkg/state/transaction_handler.go +++ b/pkg/state/transaction_handler.go @@ -8,7 +8,7 @@ import ( ) type txCheckFunc func(proto.Transaction, *checkerInfo) ([]crypto.Digest, error) -type txPerformFunc func(proto.Transaction, *performerInfo) (TransactionSnapshot, error) +type txPerformFunc func(proto.Transaction, *performerInfo, *invocationResult, *applicationResult) (TransactionSnapshot, error) type txCreateDiffFunc func(proto.Transaction, *differInfo) (txBalanceChanges, error) type txCountFeeFunc func(proto.Transaction, *feeDistribution) error @@ -31,19 +31,20 @@ type transactionHandler struct { } // TODO: see TODO on GetTypeInfo() in proto/transactions.go. +// performer builds snapshots func buildHandles(tc *transactionChecker, tp *transactionPerformer, td *transactionDiffer, tf *transactionFeeCounter) handles { return handles{ proto.TransactionTypeInfo{Type: proto.GenesisTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkGenesis, nil, td.createDiffGenesis, nil, + tc.checkGenesis, tp.performGenesis, td.createDiffGenesis, nil, }, proto.TransactionTypeInfo{Type: proto.PaymentTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkPayment, nil, td.createDiffPayment, tf.minerFeePayment, + tc.checkPayment, tp.performPayment, td.createDiffPayment, tf.minerFeePayment, }, proto.TransactionTypeInfo{Type: proto.TransferTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkTransferWithSig, nil, td.createDiffTransferWithSig, tf.minerFeeTransferWithSig, + tc.checkTransferWithSig, tp.performTransferWithSig, td.createDiffTransferWithSig, tf.minerFeeTransferWithSig, }, proto.TransactionTypeInfo{Type: proto.TransferTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkTransferWithProofs, nil, td.createDiffTransferWithProofs, tf.minerFeeTransferWithProofs, + tc.checkTransferWithProofs, tp.performTransferWithProofs, td.createDiffTransferWithProofs, tf.minerFeeTransferWithProofs, }, proto.TransactionTypeInfo{Type: proto.IssueTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ tc.checkIssueWithSig, tp.performIssueWithSig, td.createDiffIssueWithSig, tf.minerFeeIssueWithSig, @@ -154,7 +155,7 @@ func (h *transactionHandler) checkTx(tx proto.Transaction, info *checkerInfo) ([ return funcs.check(tx, info) } -func (h *transactionHandler) performTx(tx proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (h *transactionHandler) performTx(tx proto.Transaction, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tv := tx.GetTypeInfo() funcs, ok := h.funcs[tv] if !ok { @@ -165,7 +166,7 @@ func (h *transactionHandler) performTx(tx proto.Transaction, info *performerInfo return nil, nil } - return funcs.perform(tx, info) + return funcs.perform(tx, info, invocationRes, applicationRes) } func (h *transactionHandler) createDiffTx(tx proto.Transaction, info *differInfo) (txBalanceChanges, error) { diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index cc4ee29a1..fafd230ba 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -10,8 +10,9 @@ import ( ) type performerInfo struct { - height uint64 - blockID proto.BlockID + height uint64 + blockID proto.BlockID + currentMinerAddress proto.WavesAddress } type transactionPerformer struct { @@ -19,11 +20,200 @@ type transactionPerformer struct { settings *settings.BlockchainSettings } +type assetBalanceDiff struct { + asset proto.AssetID + amount int64 +} + +type addressWavesBalanceDiff map[proto.WavesAddress]balanceDiff +type addressAssetBalanceDiff map[proto.WavesAddress]assetBalanceDiff + +func addressBalanceDiffFromTxDiff(diff txDiff, scheme proto.Scheme) (addressWavesBalanceDiff, addressAssetBalanceDiff, error) { + addrWavesBalanceDiff := make(addressWavesBalanceDiff) + addrAssetBalanceDiff := make(addressAssetBalanceDiff) + for balanceKeyString, diffAmount := range diff { + + // construct address from key + wavesBalanceKey := &wavesBalanceKey{} + err := wavesBalanceKey.unmarshal([]byte(balanceKeyString)) + if err != nil { + assetBalanceKey := &assetBalanceKey{} + err := assetBalanceKey.unmarshal([]byte(balanceKeyString)) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to convert balance key to asset balance key") + } + asset := assetBalanceKey.asset + address, err := assetBalanceKey.address.ToWavesAddress(scheme) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to convert address id to waves address") + } + addrAssetBalanceDiff[address] = assetBalanceDiff{asset: asset, amount: diffAmount.balance} + continue + } + address, err := wavesBalanceKey.address.ToWavesAddress(scheme) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to convert address id to waves address") + } + addrWavesBalanceDiff[address] = diffAmount + } + return addrWavesBalanceDiff, addrAssetBalanceDiff, nil +} + +func constructBalanceDiffFromMinerFee(txFee uint64, currentMinerAddress proto.WavesAddress) addressWavesBalanceDiff { + addrBalanceDiff := make(addressWavesBalanceDiff) + feeForMiner := calculateCurrentBlockTxFee(txFee, true) + addrBalanceDiff[currentMinerAddress] = balanceDiff{balance: int64(feeForMiner)} + return addrBalanceDiff +} + +func (firstAddressBalanceDiff addressWavesBalanceDiff) mergeWithAnotherDiff(secondDiff addressWavesBalanceDiff) error { + for address, diffBalance := range secondDiff { + if _, ok := firstAddressBalanceDiff[address]; ok { + oldBalance := firstAddressBalanceDiff[address] + err := oldBalance.addCommon(&diffBalance) + if err != nil { + return errors.Wrap(err, "failed to merge two balance diffs") + } + } + } + return nil +} + func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings.BlockchainSettings) (*transactionPerformer, error) { return &transactionPerformer{stor, settings}, nil } -func (tp *transactionPerformer) performIssue(tx *proto.Issue, assetID crypto.Digest, info *performerInfo) (TransactionSnapshot, error) { +// from txDiff and fees. no validation needed at this point +func (tp *transactionPerformer) constructWavesBalanceSnapshotFromDiff(diff addressWavesBalanceDiff) (*WavesBalancesSnapshot, error) { + var wavesBalances []balanceWaves + // add miner address to the diff + + for wavesAddress, diffAmount := range diff { + + fullBalance, err := tp.stor.balances.wavesBalance(wavesAddress.ID()) + if err != nil { + return nil, errors.Wrap(err, "failed to receive sender's waves balance") + } + newBalance := balanceWaves{ + address: wavesAddress, + balance: uint64(int64(fullBalance.balance) + diffAmount.balance), + } + wavesBalances = append(wavesBalances, newBalance) + } + return &WavesBalancesSnapshot{wavesBalances: wavesBalances}, nil +} + +func (tp *transactionPerformer) constructAssetBalanceSnapshotFromDiff(diff addressAssetBalanceDiff) (*AssetBalancesSnapshot, error) { + var assetBalances []balanceAsset + // add miner address to the diff + + for wavesAddress, diffAmount := range diff { + balance, err := tp.stor.balances.assetBalance(wavesAddress.ID(), diffAmount.asset) + if err != nil { + return nil, errors.Wrap(err, "failed to receive sender's waves balance") + } + assetInfo, err := tp.stor.assets.newestAssetInfo(diffAmount.asset) + if err != nil { + return nil, errors.Wrap(err, "failed to get newest asset info") + } + newBalance := balanceAsset{ + address: wavesAddress, + assetID: diffAmount.asset.Digest(assetInfo.tail), + balance: uint64(int64(balance) + diffAmount.amount), + } + assetBalances = append(assetBalances, newBalance) + } + return &AssetBalancesSnapshot{assetBalances: assetBalances}, nil +} + +func (tp *transactionPerformer) constructBalancesSnapshotFromDiff(diff txDiff) (*WavesBalancesSnapshot, *AssetBalancesSnapshot, error) { + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + wavesBalanceSnapshot, err := tp.constructWavesBalanceSnapshotFromDiff(addrWavesBalanceDiff) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to construct waves balance snapshot") + } + if len(addrAssetBalanceDiff) == 0 { + return wavesBalanceSnapshot, nil, nil + } + + assetBalanceSnapshot, err := tp.constructAssetBalanceSnapshotFromDiff(addrAssetBalanceDiff) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to construct asset balance snapshot") + } + return wavesBalanceSnapshot, assetBalanceSnapshot, nil +} + +func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { + _, ok := transaction.(*proto.Genesis) + if !ok { + return nil, errors.New("failed to convert interface to IssueWithSig transaction") + } + var snapshot TransactionSnapshot + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + snapshot = append(snapshot, wavesBalanceSnapshot) + + if assetBalanceSnapshot != nil { + snapshot = append(snapshot, assetBalanceSnapshot) + } + return snapshot, nil +} + +func (tp *transactionPerformer) performPayment(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { + _, ok := transaction.(*proto.Payment) + if !ok { + return nil, errors.New("failed to convert interface to IssueWithSig transaction") + } + var snapshot TransactionSnapshot + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + snapshot = append(snapshot, wavesBalanceSnapshot) + + if assetBalanceSnapshot != nil { + snapshot = append(snapshot, assetBalanceSnapshot) + } + return snapshot, nil +} + +func (tp *transactionPerformer) performTransfer(applicationRes *applicationResult) (TransactionSnapshot, error) { + + var snapshot TransactionSnapshot + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + snapshot = append(snapshot, wavesBalanceSnapshot) + + if assetBalanceSnapshot != nil { + snapshot = append(snapshot, assetBalanceSnapshot) + } + return snapshot, nil +} + +func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { + _, ok := transaction.(*proto.TransferWithSig) + if !ok { + return nil, errors.New("failed to convert interface to IssueWithSig transaction") + } + return tp.performTransfer(applicationRes) +} + +func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { + _, ok := transaction.(*proto.TransferWithProofs) + if !ok { + return nil, errors.New("failed to convert interface to IssueWithSig transaction") + } + return tp.performTransfer(applicationRes) +} + +func (tp *transactionPerformer) performIssue(tx *proto.Issue, assetID crypto.Digest, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { blockHeight := info.height + 1 // Create new asset. assetInfo := &assetInfo{ @@ -42,6 +232,7 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, assetID crypto.Dig } sender := proto.MustAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) + var snapshot TransactionSnapshot issueStaticInfoSnapshot := &StaticAssetInfoSnapshot{ assetID: assetID, issuer: sender, @@ -60,17 +251,24 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, assetID crypto.Dig assetID: assetID, isReissuable: assetInfo.reissuable, } + snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + snapshot = append(snapshot, wavesBalanceSnapshot) + + if assetBalanceSnapshot != nil { + snapshot = append(snapshot, assetBalanceSnapshot) + } if err := tp.stor.assets.issueAsset(proto.AssetIDFromDigest(assetID), assetInfo, info.blockID); err != nil { return nil, errors.Wrap(err, "failed to issue asset") } - - var snapshot TransactionSnapshot - snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) return snapshot, nil } -func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.IssueWithSig) if !ok { return nil, errors.New("failed to convert interface to IssueWithSig transaction") @@ -86,10 +284,10 @@ func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transactio if err := tp.stor.scriptsStorage.setAssetScript(assetID, proto.Script{}, tx.SenderPK, info.blockID); err != nil { return nil, err } - return tp.performIssue(&tx.Issue, assetID, info) + return tp.performIssue(&tx.Issue, assetID, info, applicationRes) } -func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.IssueWithProofs) if !ok { return nil, errors.New("failed to convert interface to IssueWithProofs transaction") @@ -105,10 +303,10 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac if err := tp.stor.scriptsStorage.setAssetScript(assetID, tx.Script, tx.SenderPK, info.blockID); err != nil { return nil, err } - return tp.performIssue(&tx.Issue, assetID, info) + return tp.performIssue(&tx.Issue, assetID, info, applicationRes) } -func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { // Modify asset. change := &assetReissueChange{ reissuable: tx.Reissuable, @@ -131,29 +329,38 @@ func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performe var snapshot TransactionSnapshot snapshot = append(snapshot, assetReissuability) + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + snapshot = append(snapshot, wavesBalanceSnapshot) + + if assetBalanceSnapshot != nil { + snapshot = append(snapshot, assetBalanceSnapshot) + } if err := tp.stor.assets.reissueAsset(proto.AssetIDFromDigest(tx.AssetID), change, info.blockID); err != nil { return nil, errors.Wrap(err, "failed to reissue asset") } return snapshot, nil } -func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.ReissueWithSig) if !ok { return nil, errors.New("failed to convert interface to ReissueWithSig transaction") } - return tp.performReissue(&tx.Reissue, info) + return tp.performReissue(&tx.Reissue, info, applicationRes) } -func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.ReissueWithProofs) if !ok { return nil, errors.New("failed to convert interface to ReissueWithProofs transaction") } - return tp.performReissue(&tx.Reissue, info) + return tp.performReissue(&tx.Reissue, info, applicationRes) } -func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { // Modify asset. change := &assetBurnChange{ diff: int64(tx.Amount), @@ -174,6 +381,15 @@ func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo) var snapshot TransactionSnapshot snapshot = append(snapshot, assetReissuability) + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + snapshot = append(snapshot, wavesBalanceSnapshot) + + if assetBalanceSnapshot != nil { + snapshot = append(snapshot, assetBalanceSnapshot) + } if err := tp.stor.assets.burnAsset(proto.AssetIDFromDigest(tx.AssetID), change, info.blockID); err != nil { return nil, errors.Wrap(err, "failed to burn asset") } @@ -181,20 +397,20 @@ func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo) return snapshot, nil } -func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.BurnWithSig) if !ok { return nil, errors.New("failed to convert interface to BurnWithSig transaction") } - return tp.performBurn(&tx.Burn, info) + return tp.performBurn(&tx.Burn, info, applicationRes) } -func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.BurnWithProofs) if !ok { return nil, errors.New("failed to convert interface to BurnWithProofs transaction") } - return tp.performBurn(&tx.Burn, info) + return tp.performBurn(&tx.Burn, info, applicationRes) } func (tp *transactionPerformer) increaseOrderVolume(order proto.Order, tx proto.Exchange, info *performerInfo) (*FilledVolumeFeeSnapshot, error) { @@ -232,7 +448,7 @@ func (tp *transactionPerformer) increaseOrderVolume(order proto.Order, tx proto. return orderSnapshot, nil } -func (tp *transactionPerformer) performExchange(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performExchange(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(proto.Exchange) if !ok { return nil, errors.New("failed to convert interface to Exchange transaction") @@ -256,10 +472,20 @@ func (tp *transactionPerformer) performExchange(transaction proto.Transaction, i var snapshot TransactionSnapshot snapshot = append(snapshot, sellOrderSnapshot, buyOrderSnapshot) + + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + snapshot = append(snapshot, wavesBalanceSnapshot) + + if assetBalanceSnapshot != nil { + snapshot = append(snapshot, assetBalanceSnapshot) + } return snapshot, nil } -func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { return nil, err @@ -282,7 +508,6 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, Status: LeaseActive, RecipientAlias: tx.Recipient.Alias(), } - leaseStatusSnapshot := &LeaseStatusSnapshot{ leaseID: *id, isActive: true, @@ -308,32 +533,41 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, leaseOut: receiverBalanceProfile.leaseOut, } + var snapshot TransactionSnapshot + snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) + + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + snapshot = append(snapshot, wavesBalanceSnapshot) + + if assetBalanceSnapshot != nil { + snapshot = append(snapshot, assetBalanceSnapshot) + } if err := tp.stor.leases.addLeasing(*id, l, info.blockID); err != nil { return nil, errors.Wrap(err, "failed to add leasing") } - - var snapshot TransactionSnapshot - snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) return snapshot, nil } -func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseWithSig) if !ok { return nil, errors.New("failed to convert interface to LeaseWithSig transaction") } - return tp.performLease(&tx.Lease, tx.ID, info) + return tp.performLease(&tx.Lease, tx.ID, info, applicationRes) } -func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseWithProofs) if !ok { return nil, errors.New("failed to convert interface to LeaseWithProofs transaction") } - return tp.performLease(&tx.Lease, tx.ID, info) + return tp.performLease(&tx.Lease, tx.ID, info, applicationRes) } -func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID *crypto.Digest, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID *crypto.Digest, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { if err := tp.stor.leases.cancelLeasing(tx.LeaseID, info.blockID, info.height, txID); err != nil { return nil, errors.Wrap(err, "failed to cancel leasing") } @@ -367,28 +601,39 @@ func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID * leaseIn: receiverBalanceProfile.leaseIn, leaseOut: receiverBalanceProfile.leaseOut, } + var snapshot TransactionSnapshot snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) + + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + snapshot = append(snapshot, wavesBalanceSnapshot) + + if assetBalanceSnapshot != nil { + snapshot = append(snapshot, assetBalanceSnapshot) + } return snapshot, nil } -func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseCancelWithSig) if !ok { return nil, errors.New("failed to convert interface to LeaseCancelWithSig transaction") } - return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info) + return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info, applicationRes) } -func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseCancelWithProofs) if !ok { return nil, errors.New("failed to convert interface to LeaseCancelWithProofs transaction") } - return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info) + return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info, applicationRes) } -func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { return nil, err @@ -406,6 +651,15 @@ func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info * } var snapshot TransactionSnapshot snapshot = append(snapshot, aliasSnapshot) + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + snapshot = append(snapshot, wavesBalanceSnapshot) + + if assetBalanceSnapshot != nil { + snapshot = append(snapshot, assetBalanceSnapshot) + } if err := tp.stor.aliases.createAlias(tx.Alias.Alias, inf, info.blockID); err != nil { return nil, err @@ -413,23 +667,23 @@ func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info * return snapshot, nil } -func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.CreateAliasWithSig) if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithSig transaction") } - return tp.performCreateAlias(&tx.CreateAlias, info) + return tp.performCreateAlias(&tx.CreateAlias, info, applicationRes) } -func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.CreateAliasWithProofs) if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") } - return tp.performCreateAlias(&tx.CreateAlias, info) + return tp.performCreateAlias(&tx.CreateAlias, info, applicationRes) } -func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.DataWithProofs) if !ok { return nil, errors.New("failed to convert interface to DataWithProofs transaction") @@ -443,9 +697,20 @@ func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transact address: senderAddr, dataEntries: tx.Entries, } + var snapshot TransactionSnapshot snapshot = append(snapshot, dataEntriesSnapshot) + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + snapshot = append(snapshot, wavesBalanceSnapshot) + + if assetBalanceSnapshot != nil { + snapshot = append(snapshot, assetBalanceSnapshot) + } + for _, entry := range tx.Entries { if err := tp.stor.accountsDataStor.appendEntry(senderAddr, entry, info.blockID); err != nil { return nil, err @@ -454,7 +719,7 @@ func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transact return snapshot, nil } -func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.SponsorshipWithProofs) if !ok { return nil, errors.New("failed to convert interface to SponsorshipWithProofs transaction") @@ -466,13 +731,23 @@ func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.T var snapshot TransactionSnapshot snapshot = append(snapshot, sponsorshipSnapshot) + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + snapshot = append(snapshot, wavesBalanceSnapshot) + + if assetBalanceSnapshot != nil { + snapshot = append(snapshot, assetBalanceSnapshot) + } + if err := tp.stor.sponsoredAssets.sponsorAsset(tx.AssetID, tx.MinAssetFee, info.blockID); err != nil { return nil, errors.Wrap(err, "failed to sponsor asset") } return snapshot, nil } -func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.SetScriptWithProofs) if !ok { return nil, errors.New("failed to convert interface to SetScriptWithProofs transaction") @@ -488,13 +763,23 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra var snapshot TransactionSnapshot snapshot = append(snapshot, sponsorshipSnapshot) + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + snapshot = append(snapshot, wavesBalanceSnapshot) + + if assetBalanceSnapshot != nil { + snapshot = append(snapshot, assetBalanceSnapshot) + } + if err := tp.stor.scriptsStorage.setAccountScript(senderAddr, tx.Script, tx.SenderPK, info.blockID); err != nil { return nil, errors.Wrap(err, "failed to set account script") } return snapshot, nil } -func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.SetAssetScriptWithProofs) if !ok { return nil, errors.New("failed to convert interface to SetAssetScriptWithProofs transaction") @@ -507,13 +792,23 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot var snapshot TransactionSnapshot snapshot = append(snapshot, sponsorshipSnapshot) + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + snapshot = append(snapshot, wavesBalanceSnapshot) + + if assetBalanceSnapshot != nil { + snapshot = append(snapshot, assetBalanceSnapshot) + } + if err := tp.stor.scriptsStorage.setAssetScript(tx.AssetID, tx.Script, tx.SenderPK, info.blockID); err != nil { return nil, errors.Wrap(err, "failed to set asset script") } return snapshot, nil } -func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { if _, ok := transaction.(*proto.InvokeScriptWithProofs); !ok { return nil, errors.New("failed to convert interface to InvokeScriptWithProofs transaction") } @@ -521,10 +816,36 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. return nil, errors.Wrap(err, "failed to commit invoke changes") } // TODO + for _, action := range invocationRes.actions { + + switch a := action.(type) { + case *proto.DataEntryScriptAction: + + case *proto.AttachedPaymentScriptAction: + + case *proto.TransferScriptAction: + + case *proto.SponsorshipScriptAction: + + case *proto.IssueScriptAction: + + case *proto.ReissueScriptAction: + + case *proto.BurnScriptAction: + + case *proto.LeaseScriptAction: + + case *proto.LeaseCancelScriptAction: + + default: + return nil, errors.Errorf("unknown script action type %T", a) + } + } + return nil, nil } -func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { if _, ok := transaction.(*proto.InvokeExpressionTransactionWithProofs); !ok { return nil, errors.New("failed to convert interface to InvokeExpressionWithProofs transaction") } @@ -535,7 +856,7 @@ func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction pr return nil, nil } -func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { ethTx, ok := transaction.(*proto.EthereumTransaction) if !ok { return nil, errors.New("failed to convert interface to EthereumTransaction transaction") @@ -545,12 +866,21 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction return nil, errors.Wrap(err, "failed to commit invoke changes") } } + var snapshot TransactionSnapshot + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + snapshot = append(snapshot, wavesBalanceSnapshot) + + if assetBalanceSnapshot != nil { + snapshot = append(snapshot, assetBalanceSnapshot) + } // nothing to do for proto.EthereumTransferWavesTxKind and proto.EthereumTransferAssetsErc20TxKind - // TODO return nil, nil } -func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.UpdateAssetInfoWithProofs) if !ok { return nil, errors.New("failed to convert interface to UpdateAssetInfoWithProofs transaction") @@ -571,6 +901,16 @@ func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction pro var snapshot TransactionSnapshot snapshot = append(snapshot, sponsorshipSnapshot) + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + snapshot = append(snapshot, wavesBalanceSnapshot) + + if assetBalanceSnapshot != nil { + snapshot = append(snapshot, assetBalanceSnapshot) + } + if err := tp.stor.assets.updateAssetInfo(tx.AssetID, ch, info.blockID); err != nil { return nil, errors.Wrap(err, "failed to update asset info") } From 42f26e664fdf7e3e324602e1d0dec0d1588ae129 Mon Sep 17 00:00:00 2001 From: esuwu Date: Tue, 23 May 2023 00:17:52 -0500 Subject: [PATCH 11/27] Fixed types after merging --- pkg/state/transaction_performer.go | 325 ++++++++++++++++------------- 1 file changed, 180 insertions(+), 145 deletions(-) diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 30b6cbb53..47fd554f4 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -78,8 +78,8 @@ func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings } // from txDiff and fees. no validation needed at this point -func (tp *transactionPerformer) constructWavesBalanceSnapshotFromDiff(diff addressWavesBalanceDiff) (*WavesBalancesSnapshot, error) { - var wavesBalances []balanceWaves +func (tp *transactionPerformer) constructWavesBalanceSnapshotFromDiff(diff addressWavesBalanceDiff) ([]WavesBalanceSnapshot, error) { + var wavesBalances []WavesBalanceSnapshot // add miner address to the diff for wavesAddress, diffAmount := range diff { @@ -88,17 +88,17 @@ func (tp *transactionPerformer) constructWavesBalanceSnapshotFromDiff(diff addre if err != nil { return nil, errors.Wrap(err, "failed to receive sender's waves balance") } - newBalance := balanceWaves{ - address: wavesAddress, - balance: uint64(int64(fullBalance.balance) + diffAmount.balance), + newBalance := WavesBalanceSnapshot{ + Address: wavesAddress, + Balance: uint64(int64(fullBalance.balance) + diffAmount.balance), } wavesBalances = append(wavesBalances, newBalance) } - return &WavesBalancesSnapshot{wavesBalances: wavesBalances}, nil + return wavesBalances, nil } -func (tp *transactionPerformer) constructAssetBalanceSnapshotFromDiff(diff addressAssetBalanceDiff) (*AssetBalancesSnapshot, error) { - var assetBalances []balanceAsset +func (tp *transactionPerformer) constructAssetBalanceSnapshotFromDiff(diff addressAssetBalanceDiff) ([]AssetBalanceSnapshot, error) { + var assetBalances []AssetBalanceSnapshot // add miner address to the diff for wavesAddress, diffAmount := range diff { @@ -110,17 +110,17 @@ func (tp *transactionPerformer) constructAssetBalanceSnapshotFromDiff(diff addre if err != nil { return nil, errors.Wrap(err, "failed to get newest asset info") } - newBalance := balanceAsset{ - address: wavesAddress, - assetID: diffAmount.asset.Digest(assetInfo.tail), - balance: uint64(int64(balance) + diffAmount.amount), + newBalance := AssetBalanceSnapshot{ + Address: wavesAddress, + AssetID: diffAmount.asset.Digest(assetInfo.tail), + Balance: uint64(int64(balance) + diffAmount.amount), } assetBalances = append(assetBalances, newBalance) } - return &AssetBalancesSnapshot{assetBalances: assetBalances}, nil + return assetBalances, nil } -func (tp *transactionPerformer) constructBalancesSnapshotFromDiff(diff txDiff) (*WavesBalancesSnapshot, *AssetBalancesSnapshot, error) { +func (tp *transactionPerformer) constructBalancesSnapshotFromDiff(diff txDiff) ([]WavesBalanceSnapshot, []AssetBalanceSnapshot, error) { addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(diff, tp.settings.AddressSchemeCharacter) if err != nil { return nil, nil, errors.Wrap(err, "failed to create balance diff from tx diff") @@ -151,11 +151,13 @@ func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, in if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - snapshot = append(snapshot, wavesBalanceSnapshot) - - if assetBalanceSnapshot != nil { - snapshot = append(snapshot, assetBalanceSnapshot) + for _, wb := range wavesBalanceSnapshot { + snapshot = append(snapshot, &wb) + } + for _, ab := range assetBalanceSnapshot { + snapshot = append(snapshot, &ab) } + } return snapshot, nil @@ -172,11 +174,13 @@ func (tp *transactionPerformer) performPayment(transaction proto.Transaction, in if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - snapshot = append(snapshot, wavesBalanceSnapshot) - - if assetBalanceSnapshot != nil { - snapshot = append(snapshot, assetBalanceSnapshot) + for _, wb := range wavesBalanceSnapshot { + snapshot = append(snapshot, &wb) } + for _, ab := range assetBalanceSnapshot { + snapshot = append(snapshot, &ab) + } + } return snapshot, nil @@ -190,11 +194,13 @@ func (tp *transactionPerformer) performTransfer(applicationRes *applicationResul if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - snapshot = append(snapshot, wavesBalanceSnapshot) - - if assetBalanceSnapshot != nil { - snapshot = append(snapshot, assetBalanceSnapshot) + for _, wb := range wavesBalanceSnapshot { + snapshot = append(snapshot, &wb) } + for _, ab := range assetBalanceSnapshot { + snapshot = append(snapshot, &ab) + } + } return snapshot, nil @@ -216,7 +222,7 @@ func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Tran return tp.performTransfer(applicationRes) } -func (tp *transactionPerformer) performIssue(tx *proto.Issue, assetID crypto.Digest, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest, assetID crypto.Digest, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { blockHeight := info.height + 1 // Create new asset. assetInfo := &assetInfo{ @@ -236,25 +242,26 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, assetID crypto.Dig }, } - sender := proto.MustAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) var snapshot TransactionSnapshot issueStaticInfoSnapshot := &StaticAssetInfoSnapshot{ - assetID: assetID, - issuer: sender, - decimals: int8(assetInfo.decimals), - isNFT: assetInfo.isNFT(), + AssetID: assetID, + IssuerPublicKey: tx.SenderPK, + SourceTransactionID: txID, + Decimals: assetInfo.decimals, + IsNFT: assetInfo.isNFT(), } assetDescription := &AssetDescriptionSnapshot{ - assetID: assetID, - assetName: assetInfo.name, - assetDescription: assetInfo.description, - changeHeight: assetInfo.lastNameDescChangeHeight, + AssetID: assetID, + AssetName: assetInfo.name, + AssetDescription: assetInfo.description, + ChangeHeight: assetInfo.lastNameDescChangeHeight, } - assetReissuability := &AssetReissuabilitySnapshot{ - assetID: assetID, - isReissuable: assetInfo.reissuable, + assetReissuability := &AssetVolumeSnapshot{ + AssetID: assetID, + IsReissuable: assetInfo.reissuable, + TotalQuantity: *big.NewInt(int64(tx.Quantity)), } snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) if applicationRes != nil { @@ -262,10 +269,11 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, assetID crypto.Dig if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - snapshot = append(snapshot, wavesBalanceSnapshot) - - if assetBalanceSnapshot != nil { - snapshot = append(snapshot, assetBalanceSnapshot) + for _, wb := range wavesBalanceSnapshot { + snapshot = append(snapshot, &wb) + } + for _, ab := range assetBalanceSnapshot { + snapshot = append(snapshot, &ab) } } @@ -291,7 +299,7 @@ func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transactio if err := tp.stor.scriptsStorage.setAssetScript(assetID, proto.Script{}, tx.SenderPK, info.blockID); err != nil { return nil, err } - return tp.performIssue(&tx.Issue, assetID, info, applicationRes) + return tp.performIssue(&tx.Issue, assetID, assetID, info, applicationRes) } func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { @@ -310,7 +318,7 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac if err := tp.stor.scriptsStorage.setAssetScript(assetID, tx.Script, tx.SenderPK, info.blockID); err != nil { return nil, err } - return tp.performIssue(&tx.Issue, assetID, info, applicationRes) + return tp.performIssue(&tx.Issue, assetID, assetID, info, applicationRes) } func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { @@ -327,10 +335,10 @@ func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performe quantityDiff := big.NewInt(change.diff) resQuantity := assetInfo.quantity.Add(&assetInfo.quantity, quantityDiff) - assetReissuability := &AssetReissuabilitySnapshot{ - assetID: tx.AssetID, - totalQuantity: *resQuantity, - isReissuable: change.reissuable, + assetReissuability := &AssetVolumeSnapshot{ + AssetID: tx.AssetID, + TotalQuantity: *resQuantity, + IsReissuable: change.reissuable, } var snapshot TransactionSnapshot @@ -341,10 +349,11 @@ func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performe if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - snapshot = append(snapshot, wavesBalanceSnapshot) - - if assetBalanceSnapshot != nil { - snapshot = append(snapshot, assetBalanceSnapshot) + for _, wb := range wavesBalanceSnapshot { + snapshot = append(snapshot, &wb) + } + for _, ab := range assetBalanceSnapshot { + snapshot = append(snapshot, &ab) } } @@ -382,10 +391,10 @@ func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, } quantityDiff := big.NewInt(change.diff) resQuantity := assetInfo.quantity.Sub(&assetInfo.quantity, quantityDiff) - assetReissuability := &AssetReissuabilitySnapshot{ - assetID: tx.AssetID, - totalQuantity: *resQuantity, - isReissuable: assetInfo.reissuable, + assetReissuability := &AssetVolumeSnapshot{ + AssetID: tx.AssetID, + TotalQuantity: *resQuantity, + IsReissuable: assetInfo.reissuable, } var snapshot TransactionSnapshot @@ -396,10 +405,11 @@ func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - snapshot = append(snapshot, wavesBalanceSnapshot) - - if assetBalanceSnapshot != nil { - snapshot = append(snapshot, assetBalanceSnapshot) + for _, wb := range wavesBalanceSnapshot { + snapshot = append(snapshot, &wb) + } + for _, ab := range assetBalanceSnapshot { + snapshot = append(snapshot, &ab) } } @@ -445,10 +455,14 @@ func (tp *transactionPerformer) increaseOrderVolume(order proto.Order, tx proto. if err != nil { return nil, err } + orderIdDigset, err := crypto.NewDigestFromBytes(orderId) + if err != nil { + return nil, errors.Wrap(err, "failed to construct digest from order id bytes") + } orderSnapshot := &FilledVolumeFeeSnapshot{ - orderID: orderId, - filledFee: newestFilledFee + fee, - filledVolume: newestFilledAmount + volume, + OrderID: orderIdDigset, + FilledFee: newestFilledFee + fee, + FilledVolume: newestFilledAmount + volume, } if err := tp.stor.ordersVolumes.increaseFilledFee(orderId, fee, info.blockID); err != nil { @@ -491,10 +505,11 @@ func (tp *transactionPerformer) performExchange(transaction proto.Transaction, i if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - snapshot = append(snapshot, wavesBalanceSnapshot) - - if assetBalanceSnapshot != nil { - snapshot = append(snapshot, assetBalanceSnapshot) + for _, wb := range wavesBalanceSnapshot { + snapshot = append(snapshot, &wb) + } + for _, ab := range assetBalanceSnapshot { + snapshot = append(snapshot, &ab) } } return snapshot, nil @@ -523,9 +538,14 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, Status: LeaseActive, RecipientAlias: tx.Recipient.Alias(), } - leaseStatusSnapshot := &LeaseStatusSnapshot{ - leaseID: *id, - isActive: true, + leaseStatusSnapshot := &LeaseStateSnapshot{ + LeaseID: *id, + Status: l.Status, + Amount: l.Amount, + Sender: l.Sender, + Recipient: l.Recipient, + OriginTransactionID: *id, + Height: l.Height, } senderBalanceProfile, err := tp.stor.balances.wavesBalance(senderAddr.ID()) @@ -533,9 +553,9 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, return nil, errors.Wrap(err, "failed to receive sender's waves balance") } senderLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ - address: senderAddr, - leaseIn: senderBalanceProfile.leaseIn, - leaseOut: senderBalanceProfile.leaseOut + int64(tx.Amount), + Address: senderAddr, + LeaseIn: uint64(senderBalanceProfile.leaseIn), + LeaseOut: uint64(senderBalanceProfile.leaseOut + int64(tx.Amount)), } receiverBalanceProfile, err := tp.stor.balances.wavesBalance(recipientAddr.ID()) @@ -543,9 +563,9 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, return nil, errors.Wrap(err, "failed to receive recipient's waves balance") } recipientLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ - address: recipientAddr, - leaseIn: receiverBalanceProfile.leaseIn + int64(tx.Amount), - leaseOut: receiverBalanceProfile.leaseOut, + Address: recipientAddr, + LeaseIn: uint64(receiverBalanceProfile.leaseIn + int64(tx.Amount)), + LeaseOut: uint64(receiverBalanceProfile.leaseOut), } var snapshot TransactionSnapshot @@ -555,10 +575,11 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - snapshot = append(snapshot, wavesBalanceSnapshot) - - if assetBalanceSnapshot != nil { - snapshot = append(snapshot, assetBalanceSnapshot) + for _, wb := range wavesBalanceSnapshot { + snapshot = append(snapshot, &wb) + } + for _, ab := range assetBalanceSnapshot { + snapshot = append(snapshot, &ab) } } @@ -585,28 +606,33 @@ func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transac } func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID *crypto.Digest, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { - if err := tp.stor.leases.cancelLeasing(tx.LeaseID, info.blockID, info.height, txID); err != nil { - return nil, errors.Wrap(err, "failed to cancel leasing") - } - leaseStatusSnapshot := &LeaseStatusSnapshot{ - leaseID: tx.LeaseID, - isActive: false, - } - leasingInfo, err := tp.stor.leases.leasingInfo(tx.LeaseID) if err != nil { return nil, errors.Wrap(err, "failed to receiver leasing info") } + if err := tp.stor.leases.cancelLeasing(tx.LeaseID, info.blockID, info.height, txID); err != nil { + return nil, errors.Wrap(err, "failed to cancel leasing") + } + leaseStatusSnapshot := &LeaseStateSnapshot{ + LeaseID: tx.LeaseID, + Status: LeaseCanceled, + Amount: leasingInfo.Amount, + Sender: leasingInfo.Sender, + Recipient: leasingInfo.Recipient, + OriginTransactionID: *txID, + Height: leasingInfo.Height, + } + // TODO check if the balance will be updated immediately after the leasing senderBalanceProfile, err := tp.stor.balances.wavesBalance(leasingInfo.Sender.ID()) if err != nil { return nil, errors.Wrap(err, "failed to receive sender's waves balance") } senderLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ - address: leasingInfo.Sender, - leaseIn: senderBalanceProfile.leaseIn, - leaseOut: senderBalanceProfile.leaseOut, + Address: leasingInfo.Sender, + LeaseIn: uint64(senderBalanceProfile.leaseIn), + LeaseOut: uint64(senderBalanceProfile.leaseOut), } receiverBalanceProfile, err := tp.stor.balances.wavesBalance(leasingInfo.Recipient.ID()) @@ -614,9 +640,9 @@ func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID * return nil, errors.Wrap(err, "failed to receive recipient's waves balance") } recipientLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ - address: leasingInfo.Recipient, - leaseIn: receiverBalanceProfile.leaseIn, - leaseOut: receiverBalanceProfile.leaseOut, + Address: leasingInfo.Recipient, + LeaseIn: uint64(receiverBalanceProfile.leaseIn), + LeaseOut: uint64(receiverBalanceProfile.leaseOut), } var snapshot TransactionSnapshot @@ -626,10 +652,11 @@ func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID * if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - snapshot = append(snapshot, wavesBalanceSnapshot) - - if assetBalanceSnapshot != nil { - snapshot = append(snapshot, assetBalanceSnapshot) + for _, wb := range wavesBalanceSnapshot { + snapshot = append(snapshot, &wb) + } + for _, ab := range assetBalanceSnapshot { + snapshot = append(snapshot, &ab) } } return snapshot, nil @@ -658,8 +685,8 @@ func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info * } aliasSnapshot := &AliasSnapshot{ - address: senderAddr, - alias: tx.Alias, + Address: senderAddr, + Alias: tx.Alias, } var snapshot TransactionSnapshot snapshot = append(snapshot, aliasSnapshot) @@ -668,10 +695,11 @@ func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info * if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - snapshot = append(snapshot, wavesBalanceSnapshot) - - if assetBalanceSnapshot != nil { - snapshot = append(snapshot, assetBalanceSnapshot) + for _, wb := range wavesBalanceSnapshot { + snapshot = append(snapshot, &wb) + } + for _, ab := range assetBalanceSnapshot { + snapshot = append(snapshot, &ab) } } @@ -708,8 +736,8 @@ func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transact } dataEntriesSnapshot := &DataEntriesSnapshot{ - address: senderAddr, - dataEntries: tx.Entries, + Address: senderAddr, + DataEntries: tx.Entries, } var snapshot TransactionSnapshot @@ -719,10 +747,11 @@ func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transact if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - snapshot = append(snapshot, wavesBalanceSnapshot) - - if assetBalanceSnapshot != nil { - snapshot = append(snapshot, assetBalanceSnapshot) + for _, wb := range wavesBalanceSnapshot { + snapshot = append(snapshot, &wb) + } + for _, ab := range assetBalanceSnapshot { + snapshot = append(snapshot, &ab) } } @@ -740,8 +769,8 @@ func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.T return nil, errors.New("failed to convert interface to SponsorshipWithProofs transaction") } sponsorshipSnapshot := &SponsorshipSnapshot{ - assetID: tx.AssetID, - minSponsoredFee: tx.MinAssetFee, + AssetID: tx.AssetID, + MinSponsoredFee: tx.MinAssetFee, } var snapshot TransactionSnapshot snapshot = append(snapshot, sponsorshipSnapshot) @@ -750,10 +779,11 @@ func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.T if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - snapshot = append(snapshot, wavesBalanceSnapshot) - - if assetBalanceSnapshot != nil { - snapshot = append(snapshot, assetBalanceSnapshot) + for _, wb := range wavesBalanceSnapshot { + snapshot = append(snapshot, &wb) + } + for _, ab := range assetBalanceSnapshot { + snapshot = append(snapshot, &ab) } } @@ -775,21 +805,22 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra if err != nil { return nil, err } + sponsorshipSnapshot := &AccountScriptSnapshot{ + SenderPublicKey: tx.SenderPK, + Script: tx.Script, + VerifierComplexity: 0, // TODO fix it + } + snapshot = append(snapshot, sponsorshipSnapshot) if applicationRes != nil { - sponsorshipSnapshot := &AccountScriptSnapshot{ - address: senderAddr, - script: tx.Script, - } - snapshot = append(snapshot, sponsorshipSnapshot) - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - snapshot = append(snapshot, wavesBalanceSnapshot) - - if assetBalanceSnapshot != nil { - snapshot = append(snapshot, assetBalanceSnapshot) + for _, wb := range wavesBalanceSnapshot { + snapshot = append(snapshot, &wb) + } + for _, ab := range assetBalanceSnapshot { + snapshot = append(snapshot, &ab) } } @@ -807,8 +838,9 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot var snapshot TransactionSnapshot sponsorshipSnapshot := &AssetScriptSnapshot{ - assetID: tx.AssetID, - script: tx.Script, + AssetID: tx.AssetID, + Script: tx.Script, + Complexity: 0, // TDODO fix it } snapshot = append(snapshot, sponsorshipSnapshot) @@ -817,10 +849,11 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - snapshot = append(snapshot, wavesBalanceSnapshot) - - if assetBalanceSnapshot != nil { - snapshot = append(snapshot, assetBalanceSnapshot) + for _, wb := range wavesBalanceSnapshot { + snapshot = append(snapshot, &wb) + } + for _, ab := range assetBalanceSnapshot { + snapshot = append(snapshot, &ab) } } @@ -895,10 +928,11 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - snapshot = append(snapshot, wavesBalanceSnapshot) - - if assetBalanceSnapshot != nil { - snapshot = append(snapshot, assetBalanceSnapshot) + for _, wb := range wavesBalanceSnapshot { + snapshot = append(snapshot, &wb) + } + for _, ab := range assetBalanceSnapshot { + snapshot = append(snapshot, &ab) } } @@ -919,10 +953,10 @@ func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction pro } sponsorshipSnapshot := &AssetDescriptionSnapshot{ - assetID: tx.AssetID, - assetName: tx.Name, - assetDescription: tx.Description, - changeHeight: blockHeight, + AssetID: tx.AssetID, + AssetName: tx.Name, + AssetDescription: tx.Description, + ChangeHeight: blockHeight, } var snapshot TransactionSnapshot snapshot = append(snapshot, sponsorshipSnapshot) @@ -931,10 +965,11 @@ func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction pro if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - snapshot = append(snapshot, wavesBalanceSnapshot) - - if assetBalanceSnapshot != nil { - snapshot = append(snapshot, assetBalanceSnapshot) + for _, wb := range wavesBalanceSnapshot { + snapshot = append(snapshot, &wb) + } + for _, ab := range assetBalanceSnapshot { + snapshot = append(snapshot, &ab) } } From 7b8438ef531dbc3f5dcaab596b0c78147ac0139a Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 24 May 2023 00:01:45 -0500 Subject: [PATCH 12/27] Fixed issue snapshot mistake --- pkg/state/appender.go | 2 +- pkg/state/transaction_performer.go | 125 +++++++++++++++++++++++------ 2 files changed, 103 insertions(+), 24 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index eb9de1e53..2a856b296 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -562,7 +562,7 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro zap.S().Errorf("failed to commit transaction (id %s) after successful validation; this should NEVER happen", base58.Encode(txID)) return err } - { + if len(snapshot) > 1000 { zap.S().Debug(snapshot) } // Store additional data for API: transaction by address. diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 47fd554f4..0b03e4116 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -106,7 +106,7 @@ func (tp *transactionPerformer) constructAssetBalanceSnapshotFromDiff(diff addre if err != nil { return nil, errors.Wrap(err, "failed to receive sender's waves balance") } - assetInfo, err := tp.stor.assets.newestAssetInfo(diffAmount.asset) + assetInfo, err := tp.stor.assets.assetInfo(diffAmount.asset) if err != nil { return nil, errors.Wrap(err, "failed to get newest asset info") } @@ -120,11 +120,7 @@ func (tp *transactionPerformer) constructAssetBalanceSnapshotFromDiff(diff addre return assetBalances, nil } -func (tp *transactionPerformer) constructBalancesSnapshotFromDiff(diff txDiff) ([]WavesBalanceSnapshot, []AssetBalanceSnapshot, error) { - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(diff, tp.settings.AddressSchemeCharacter) - if err != nil { - return nil, nil, errors.Wrap(err, "failed to create balance diff from tx diff") - } +func (tp *transactionPerformer) constructBalancesSnapshotFromDiff(addrWavesBalanceDiff addressWavesBalanceDiff, addrAssetBalanceDiff addressAssetBalanceDiff) ([]WavesBalanceSnapshot, []AssetBalanceSnapshot, error) { wavesBalanceSnapshot, err := tp.constructWavesBalanceSnapshotFromDiff(addrWavesBalanceDiff) if err != nil { return nil, nil, errors.Wrap(err, "failed to construct waves balance snapshot") @@ -147,7 +143,11 @@ func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, in } var snapshot TransactionSnapshot if applicationRes != nil { - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -170,7 +170,11 @@ func (tp *transactionPerformer) performPayment(transaction proto.Transaction, in } var snapshot TransactionSnapshot if applicationRes != nil { - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -190,7 +194,11 @@ func (tp *transactionPerformer) performTransfer(applicationRes *applicationResul var snapshot TransactionSnapshot if applicationRes != nil { - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -263,9 +271,28 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest IsReissuable: assetInfo.reissuable, TotalQuantity: *big.NewInt(int64(tx.Quantity)), } + snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) if applicationRes != nil { - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + // Remove the just issues snapshot from the diff, because it's not in the storage yet, so can't be processed with constructBalancesSnapshotFromDiff + var specialAssetSnapshot *AssetBalanceSnapshot + for addr, diff := range addrAssetBalanceDiff { + if diff.asset == proto.AssetIDFromDigest(assetID) { + // remove the element from the array + delete(addrAssetBalanceDiff, addr) + specialAssetSnapshot = &AssetBalanceSnapshot{ + Address: addr, + AssetID: assetID, + Balance: uint64(diff.amount), + } + } + } + + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -275,11 +302,16 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest for _, ab := range assetBalanceSnapshot { snapshot = append(snapshot, &ab) } + if specialAssetSnapshot != nil { + snapshot = append(snapshot, specialAssetSnapshot) + } + } if err := tp.stor.assets.issueAsset(proto.AssetIDFromDigest(assetID), assetInfo, info.blockID); err != nil { return nil, errors.Wrap(err, "failed to issue asset") } + return snapshot, nil } @@ -345,7 +377,11 @@ func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performe snapshot = append(snapshot, assetReissuability) if applicationRes != nil { - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -401,7 +437,11 @@ func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, snapshot = append(snapshot, assetReissuability) if applicationRes != nil { - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -501,7 +541,11 @@ func (tp *transactionPerformer) performExchange(transaction proto.Transaction, i snapshot = append(snapshot, sellOrderSnapshot, buyOrderSnapshot) if applicationRes != nil { - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -571,7 +615,11 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, var snapshot TransactionSnapshot snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) if applicationRes != nil { - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -648,7 +696,11 @@ func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID * var snapshot TransactionSnapshot snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) if applicationRes != nil { - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -691,7 +743,11 @@ func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info * var snapshot TransactionSnapshot snapshot = append(snapshot, aliasSnapshot) if applicationRes != nil { - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -743,7 +799,11 @@ func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transact var snapshot TransactionSnapshot snapshot = append(snapshot, dataEntriesSnapshot) if applicationRes != nil { - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -775,7 +835,11 @@ func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.T var snapshot TransactionSnapshot snapshot = append(snapshot, sponsorshipSnapshot) if applicationRes != nil { - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -785,7 +849,6 @@ func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.T for _, ab := range assetBalanceSnapshot { snapshot = append(snapshot, &ab) } - } if err := tp.stor.sponsoredAssets.sponsorAsset(tx.AssetID, tx.MinAssetFee, info.blockID); err != nil { @@ -812,7 +875,11 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra } snapshot = append(snapshot, sponsorshipSnapshot) if applicationRes != nil { - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -845,7 +912,11 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot snapshot = append(snapshot, sponsorshipSnapshot) if applicationRes != nil { - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -924,7 +995,11 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction } var snapshot TransactionSnapshot if applicationRes != nil { - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -961,7 +1036,11 @@ func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction pro var snapshot TransactionSnapshot snapshot = append(snapshot, sponsorshipSnapshot) if applicationRes != nil { - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(applicationRes.changes.diff) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } From 8c4a181656c9d5ba0aa2f6da0614d56dea398e99 Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 24 May 2023 03:14:29 -0500 Subject: [PATCH 13/27] Added rewards snapshot in append block --- pkg/state/appender.go | 39 +++++++++++++++++++++++++++++++--- pkg/state/block_differ.go | 2 +- pkg/state/block_differ_test.go | 22 +++++++++---------- pkg/state/state.go | 5 ----- 4 files changed, 48 insertions(+), 20 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 2a856b296..cc6100979 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -562,6 +562,7 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro zap.S().Errorf("failed to commit transaction (id %s) after successful validation; this should NEVER happen", base58.Encode(txID)) return err } + // a temporary dummy for linters if len(snapshot) > 1000 { zap.S().Debug(snapshot) } @@ -574,6 +575,29 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro return nil } +// rewards and 60% of the fee to the previous miner +func (a *txAppender) createInitialBlockSnapshot(minerAndRewardDiff txDiff) (TransactionSnapshot, error) { + addrWavesBalanceDiff, _, err := addressBalanceDiffFromTxDiff(minerAndRewardDiff, a.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + // add miner address to the diff + var snapshot TransactionSnapshot + for wavesAddress, diffAmount := range addrWavesBalanceDiff { + + fullBalance, err := a.stor.balances.wavesBalance(wavesAddress.ID()) + if err != nil { + return nil, errors.Wrap(err, "failed to receive sender's waves balance") + } + newBalance := &WavesBalanceSnapshot{ + Address: wavesAddress, + Balance: uint64(int64(fullBalance.balance) + diffAmount.balance), + } + snapshot = append(snapshot, newBalance) + } + return snapshot, nil +} + func (a *txAppender) appendBlock(params *appendBlockParams) error { // Reset block complexity counter. defer func() { @@ -609,12 +633,21 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { // Create miner balance diff. // This adds 60% of prev block fees as very first balance diff of the current block // in case NG is activated, or empty diff otherwise. - minerDiff, err := a.blockDiffer.createMinerDiff(params.block, hasParent) + minerAndRewardDiff, err := a.blockDiffer.createMinerAndRewardDiff(params.block, hasParent) if err != nil { return err } + // create the initial snapshot + initialSnapshot, err := a.createInitialBlockSnapshot(minerAndRewardDiff) + if err != nil { + return errors.Wrap(err, "failed to create initial snapshot") + } + // a temporary dummy for linters + if len(initialSnapshot) > 100 { + zap.S().Debug(initialSnapshot) + } // Save miner diff first. - if err := a.diffStor.saveTxDiff(minerDiff); err != nil { + if err := a.diffStor.saveTxDiff(minerAndRewardDiff); err != nil { return err } blockInfo, err := a.currentBlockInfo() @@ -661,7 +694,7 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { } } // Save fee distribution of this block. - // This will be needed for createMinerDiff() of next block due to NG. + // This will be needed for createMinerAndRewardDiff() of next block due to NG. if err := a.blockDiffer.saveCurFeeDistr(params.block); err != nil { return err } diff --git a/pkg/state/block_differ.go b/pkg/state/block_differ.go index d06ffa7af..ed2b39fb7 100644 --- a/pkg/state/block_differ.go +++ b/pkg/state/block_differ.go @@ -169,7 +169,7 @@ func (d *blockDiffer) saveCurFeeDistr(block *proto.BlockHeader) error { return nil } -func (d *blockDiffer) createMinerDiff(block *proto.BlockHeader, hasParent bool) (txDiff, error) { +func (d *blockDiffer) createMinerAndRewardDiff(block *proto.BlockHeader, hasParent bool) (txDiff, error) { var err error var minerDiff txDiff var minerAddr proto.WavesAddress diff --git a/pkg/state/block_differ_test.go b/pkg/state/block_differ_test.go index 48dc5ac1c..e35564d18 100644 --- a/pkg/state/block_differ_test.go +++ b/pkg/state/block_differ_test.go @@ -55,8 +55,8 @@ func TestCreateBlockDiffWithoutNg(t *testing.T) { to := createBlockDiffer(t) block, _ := genBlocks(t, to) - minerDiff, err := to.blockDiffer.createMinerDiff(&block.BlockHeader, true) - require.NoError(t, err, "createMinerDiff() failed") + minerDiff, err := to.blockDiffer.createMinerAndRewardDiff(&block.BlockHeader, true) + require.NoError(t, err, "createMinerAndRewardDiff() failed") // Empty miner diff before NG activation. assert.Equal(t, txDiff{}, minerDiff) } @@ -83,8 +83,8 @@ func TestCreateBlockDiffNg(t *testing.T) { parentFeeNextBlock := parentFeeTotal - parentFeePrevBlock // Create diff from child block. - minerDiff, err := to.blockDiffer.createMinerDiff(&child.BlockHeader, true) - require.NoError(t, err, "createMinerDiff() failed") + minerDiff, err := to.blockDiffer.createMinerAndRewardDiff(&child.BlockHeader, true) + require.NoError(t, err, "createMinerAndRewardDiff() failed") // Verify child block miner's diff. correctMinerAssetBalanceDiff := newBalanceDiff(parentFeeNextBlock, 0, 0, false) correctMinerAssetBalanceDiff.blockID = child.BlockID() @@ -121,15 +121,15 @@ func TestCreateBlockDiffSponsorship(t *testing.T) { } err = to.blockDiffer.saveCurFeeDistr(&parent.BlockHeader) require.NoError(t, err, "saveCurFeeDistr() failed") - _, err = to.blockDiffer.createMinerDiff(&parent.BlockHeader, false) - require.NoError(t, err, "createMinerDiff() failed") + _, err = to.blockDiffer.createMinerAndRewardDiff(&parent.BlockHeader, false) + require.NoError(t, err, "createMinerAndRewardDiff() failed") parentFeeTotal := int64(txs[0].GetFee() * FeeUnit / assetCost) parentFeePrevBlock := parentFeeTotal / 5 * 2 parentFeeNextBlock := parentFeeTotal - parentFeePrevBlock // Create diff from child block. - minerDiff, err := to.blockDiffer.createMinerDiff(&child.BlockHeader, true) - require.NoError(t, err, "createMinerDiff() failed") + minerDiff, err := to.blockDiffer.createMinerAndRewardDiff(&child.BlockHeader, true) + require.NoError(t, err, "createMinerAndRewardDiff() failed") // Verify child block miner's diff. correctMinerWavesBalanceDiff := newBalanceDiff(parentFeeNextBlock, 0, 0, false) correctMinerWavesBalanceDiff.blockID = child.BlockID() @@ -184,7 +184,7 @@ func TestCreateBlockDiffWithReward(t *testing.T) { // Second block block2 := genBlockWithSingleTransaction(t, block1.BlockID(), block1.GenSignature, to) to.stor.addBlock(t, block2.BlockID()) - minerDiff, err := to.blockDiffer.createMinerDiff(&block2.BlockHeader, true) + minerDiff, err := to.blockDiffer.createMinerAndRewardDiff(&block2.BlockHeader, true) require.NoError(t, err) fee := defaultFee - defaultFee/5*2 @@ -223,7 +223,7 @@ func TestBlockRewardDistributionWithTwoAddresses(t *testing.T) { // Second block block2 := genBlockWithSingleTransaction(t, block1.BlockID(), block1.GenSignature, to) to.stor.addBlock(t, block2.BlockID()) - minerDiff, err := to.blockDiffer.createMinerDiff(&block2.BlockHeader, true) + minerDiff, err := to.blockDiffer.createMinerAndRewardDiff(&block2.BlockHeader, true) require.NoError(t, err) fee := int64(defaultFee - defaultFee/5*2) @@ -270,7 +270,7 @@ func TestBlockRewardDistributionWithOneAddress(t *testing.T) { // Second block block2 := genBlockWithSingleTransaction(t, block1.BlockID(), block1.GenSignature, to) to.stor.addBlock(t, block2.BlockID()) - minerDiff, err := to.blockDiffer.createMinerDiff(&block2.BlockHeader, true) + minerDiff, err := to.blockDiffer.createMinerAndRewardDiff(&block2.BlockHeader, true) require.NoError(t, err) fee := defaultFee - defaultFee/5*2 diff --git a/pkg/state/state.go b/pkg/state/state.go index 5cfc346f8..891c13951 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -1029,11 +1029,6 @@ func (s *stateManager) addRewardVote(block *proto.Block, height uint64) error { return s.stor.monetaryPolicy.vote(block.RewardVote, height, activation, block.BlockID()) } -// rewards and 60% of the fee to the previous miner -//func (s *stateManager) createInitialBlockSnapshot(block *proto.Block, height uint64, previousMinerPK proto.WavesAddress) { -// -//} - func (s *stateManager) addNewBlock(block, parent *proto.Block, chans *verifierChans, height uint64) error { blockHeight := height + 1 // Add score. From d7d8585e1126b9749ffa3bd194bd56a9a664c1a0 Mon Sep 17 00:00:00 2001 From: esuwu Date: Sun, 28 May 2023 00:27:34 -0500 Subject: [PATCH 14/27] Changed functions to newest --- pkg/state/transaction_performer.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 0b03e4116..d9ebf58b5 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -102,11 +102,11 @@ func (tp *transactionPerformer) constructAssetBalanceSnapshotFromDiff(diff addre // add miner address to the diff for wavesAddress, diffAmount := range diff { - balance, err := tp.stor.balances.assetBalance(wavesAddress.ID(), diffAmount.asset) + balance, err := tp.stor.balances.newestAssetBalance(wavesAddress.ID(), diffAmount.asset) if err != nil { return nil, errors.Wrap(err, "failed to receive sender's waves balance") } - assetInfo, err := tp.stor.assets.assetInfo(diffAmount.asset) + assetInfo, err := tp.stor.assets.newestAssetInfo(diffAmount.asset) if err != nil { return nil, errors.Wrap(err, "failed to get newest asset info") } From b783632a0bd18c6dd9eb4a0cdf8fa9fa9c73ad3e Mon Sep 17 00:00:00 2001 From: esuwu Date: Sat, 3 Jun 2023 19:49:41 -0500 Subject: [PATCH 15/27] Added snapshots from actions --- pkg/state/transaction_performer.go | 505 +++++++++++++++++++++-------- 1 file changed, 378 insertions(+), 127 deletions(-) diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index d9ebf58b5..0436e382a 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -21,13 +21,13 @@ type transactionPerformer struct { settings *settings.BlockchainSettings } -type assetBalanceDiff struct { - asset proto.AssetID - amount int64 +type assetBalanceDiffKey struct { + address proto.WavesAddress + asset proto.AssetID } type addressWavesBalanceDiff map[proto.WavesAddress]balanceDiff -type addressAssetBalanceDiff map[proto.WavesAddress]assetBalanceDiff +type addressAssetBalanceDiff map[assetBalanceDiffKey]int64 func addressBalanceDiffFromTxDiff(diff txDiff, scheme proto.Scheme) (addressWavesBalanceDiff, addressAssetBalanceDiff, error) { addrWavesBalanceDiff := make(addressWavesBalanceDiff) @@ -48,7 +48,8 @@ func addressBalanceDiffFromTxDiff(diff txDiff, scheme proto.Scheme) (addressWave if err != nil { return nil, nil, errors.Wrap(err, "failed to convert address id to waves address") } - addrAssetBalanceDiff[address] = assetBalanceDiff{asset: asset, amount: diffAmount.balance} + assetBalKey := assetBalanceDiffKey{address: address, asset: asset} + addrAssetBalanceDiff[assetBalKey] = diffAmount.balance continue } address, err := wavesBalanceKey.address.ToWavesAddress(scheme) @@ -101,19 +102,19 @@ func (tp *transactionPerformer) constructAssetBalanceSnapshotFromDiff(diff addre var assetBalances []AssetBalanceSnapshot // add miner address to the diff - for wavesAddress, diffAmount := range diff { - balance, err := tp.stor.balances.newestAssetBalance(wavesAddress.ID(), diffAmount.asset) + for key, diffAmount := range diff { + balance, err := tp.stor.balances.newestAssetBalance(key.address.ID(), key.asset) if err != nil { return nil, errors.Wrap(err, "failed to receive sender's waves balance") } - assetInfo, err := tp.stor.assets.newestAssetInfo(diffAmount.asset) + assetInfo, err := tp.stor.assets.newestAssetInfo(key.asset) if err != nil { return nil, errors.Wrap(err, "failed to get newest asset info") } newBalance := AssetBalanceSnapshot{ - Address: wavesAddress, - AssetID: diffAmount.asset.Digest(assetInfo.tail), - Balance: uint64(int64(balance) + diffAmount.amount), + Address: key.address, + AssetID: key.asset.Digest(assetInfo.tail), + Balance: uint64(int64(balance) + diffAmount), } assetBalances = append(assetBalances, newBalance) } @@ -230,6 +231,30 @@ func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Tran return tp.performTransfer(applicationRes) } +func generateIssueSnapshots(assetID crypto.Digest, txID crypto.Digest, senderPK crypto.PublicKey, assetInfo assetInfo) (*StaticAssetInfoSnapshot, *AssetDescriptionSnapshot, *AssetVolumeSnapshot) { + issueStaticInfoSnapshot := &StaticAssetInfoSnapshot{ + AssetID: assetID, + IssuerPublicKey: senderPK, + SourceTransactionID: txID, + Decimals: assetInfo.decimals, + IsNFT: assetInfo.isNFT(), + } + + assetDescription := &AssetDescriptionSnapshot{ + AssetID: assetID, + AssetName: assetInfo.name, + AssetDescription: assetInfo.description, + ChangeHeight: assetInfo.lastNameDescChangeHeight, + } + + assetReissuability := &AssetVolumeSnapshot{ + AssetID: assetID, + IsReissuable: assetInfo.reissuable, + TotalQuantity: assetInfo.quantity, + } + return issueStaticInfoSnapshot, assetDescription, assetReissuability +} + func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest, assetID crypto.Digest, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { blockHeight := info.height + 1 // Create new asset. @@ -251,26 +276,8 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest } var snapshot TransactionSnapshot - issueStaticInfoSnapshot := &StaticAssetInfoSnapshot{ - AssetID: assetID, - IssuerPublicKey: tx.SenderPK, - SourceTransactionID: txID, - Decimals: assetInfo.decimals, - IsNFT: assetInfo.isNFT(), - } - - assetDescription := &AssetDescriptionSnapshot{ - AssetID: assetID, - AssetName: assetInfo.name, - AssetDescription: assetInfo.description, - ChangeHeight: assetInfo.lastNameDescChangeHeight, - } - - assetReissuability := &AssetVolumeSnapshot{ - AssetID: assetID, - IsReissuable: assetInfo.reissuable, - TotalQuantity: *big.NewInt(int64(tx.Quantity)), - } + issueStaticInfoSnapshot, assetDescription, assetReissuability := generateIssueSnapshots(assetID, txID, + tx.SenderPK, *assetInfo) snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) if applicationRes != nil { @@ -280,14 +287,15 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest } // Remove the just issues snapshot from the diff, because it's not in the storage yet, so can't be processed with constructBalancesSnapshotFromDiff var specialAssetSnapshot *AssetBalanceSnapshot - for addr, diff := range addrAssetBalanceDiff { - if diff.asset == proto.AssetIDFromDigest(assetID) { + for key, diffAmount := range addrAssetBalanceDiff { + if key.asset == proto.AssetIDFromDigest(assetID) { // remove the element from the array - delete(addrAssetBalanceDiff, addr) + + delete(addrAssetBalanceDiff, key) specialAssetSnapshot = &AssetBalanceSnapshot{ - Address: addr, + Address: key.address, AssetID: assetID, - Balance: uint64(diff.amount), + Balance: uint64(diffAmount), } } } @@ -353,6 +361,7 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac return tp.performIssue(&tx.Issue, assetID, assetID, info, applicationRes) } +// TODO change balance of asset's owner func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { // Modify asset. change := &assetReissueChange{ @@ -415,6 +424,7 @@ func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Trans return tp.performReissue(&tx.Reissue, info, applicationRes) } +// TODO change balance of asset's owner func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { // Modify asset. change := &assetBurnChange{ @@ -559,6 +569,41 @@ func (tp *transactionPerformer) performExchange(transaction proto.Transaction, i return snapshot, nil } +func (tp *transactionPerformer) generateLeaseSnapshots(leaseID crypto.Digest, l leasing, originalTxID crypto.Digest, + senderAddress proto.WavesAddress, receiverAddress proto.WavesAddress, amount int64) (*LeaseStateSnapshot, *LeaseBalanceSnapshot, *LeaseBalanceSnapshot, error) { + leaseStatusSnapshot := &LeaseStateSnapshot{ + LeaseID: leaseID, + Status: l.Status, + Amount: l.Amount, + Sender: l.Sender, + Recipient: l.Recipient, + OriginTransactionID: originalTxID, + Height: l.Height, + } + + senderBalanceProfile, err := tp.stor.balances.wavesBalance(senderAddress.ID()) + if err != nil { + return nil, nil, nil, errors.Wrap(err, "failed to receive sender's waves balance") + } + senderLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ + Address: senderAddress, + LeaseIn: uint64(senderBalanceProfile.leaseIn), + LeaseOut: uint64(senderBalanceProfile.leaseOut + amount), + } + + receiverBalanceProfile, err := tp.stor.balances.wavesBalance(receiverAddress.ID()) + if err != nil { + return nil, nil, nil, errors.Wrap(err, "failed to receive recipient's waves balance") + } + recipientLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ + Address: receiverAddress, + LeaseIn: uint64(receiverBalanceProfile.leaseIn + amount), + LeaseOut: uint64(receiverBalanceProfile.leaseOut), + } + + return leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, nil +} + func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { @@ -582,36 +627,11 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, Status: LeaseActive, RecipientAlias: tx.Recipient.Alias(), } - leaseStatusSnapshot := &LeaseStateSnapshot{ - LeaseID: *id, - Status: l.Status, - Amount: l.Amount, - Sender: l.Sender, - Recipient: l.Recipient, - OriginTransactionID: *id, - Height: l.Height, - } - - senderBalanceProfile, err := tp.stor.balances.wavesBalance(senderAddr.ID()) + var amount = int64(tx.Amount) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseSnapshots(*id, *l, *id, senderAddr, recipientAddr, amount) if err != nil { - return nil, errors.Wrap(err, "failed to receive sender's waves balance") + return nil, errors.Wrap(err, "failed to generate snapshots for a lease transaction") } - senderLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ - Address: senderAddr, - LeaseIn: uint64(senderBalanceProfile.leaseIn), - LeaseOut: uint64(senderBalanceProfile.leaseOut + int64(tx.Amount)), - } - - receiverBalanceProfile, err := tp.stor.balances.wavesBalance(recipientAddr.ID()) - if err != nil { - return nil, errors.Wrap(err, "failed to receive recipient's waves balance") - } - recipientLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ - Address: recipientAddr, - LeaseIn: uint64(receiverBalanceProfile.leaseIn + int64(tx.Amount)), - LeaseOut: uint64(receiverBalanceProfile.leaseOut), - } - var snapshot TransactionSnapshot snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) if applicationRes != nil { @@ -659,40 +679,11 @@ func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID * return nil, errors.Wrap(err, "failed to receiver leasing info") } - if err := tp.stor.leases.cancelLeasing(tx.LeaseID, info.blockID, info.height, txID); err != nil { - return nil, errors.Wrap(err, "failed to cancel leasing") - } - leaseStatusSnapshot := &LeaseStateSnapshot{ - LeaseID: tx.LeaseID, - Status: LeaseCanceled, - Amount: leasingInfo.Amount, - Sender: leasingInfo.Sender, - Recipient: leasingInfo.Recipient, - OriginTransactionID: *txID, - Height: leasingInfo.Height, - } - - // TODO check if the balance will be updated immediately after the leasing - senderBalanceProfile, err := tp.stor.balances.wavesBalance(leasingInfo.Sender.ID()) - if err != nil { - return nil, errors.Wrap(err, "failed to receive sender's waves balance") - } - senderLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ - Address: leasingInfo.Sender, - LeaseIn: uint64(senderBalanceProfile.leaseIn), - LeaseOut: uint64(senderBalanceProfile.leaseOut), - } - - receiverBalanceProfile, err := tp.stor.balances.wavesBalance(leasingInfo.Recipient.ID()) + var amount = -int64(leasingInfo.Amount) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseSnapshots(tx.LeaseID, *leasingInfo, *txID, leasingInfo.Sender, leasingInfo.Recipient, amount) if err != nil { - return nil, errors.Wrap(err, "failed to receive recipient's waves balance") + return nil, errors.Wrap(err, "failed to generate snapshots for a lease cancel transaction") } - recipientLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ - Address: leasingInfo.Recipient, - LeaseIn: uint64(receiverBalanceProfile.leaseIn), - LeaseOut: uint64(receiverBalanceProfile.leaseOut), - } - var snapshot TransactionSnapshot snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) if applicationRes != nil { @@ -711,6 +702,10 @@ func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID * snapshot = append(snapshot, &ab) } } + + if err := tp.stor.leases.cancelLeasing(tx.LeaseID, info.blockID, info.height, txID); err != nil { + return nil, errors.Wrap(err, "failed to cancel leasing") + } return snapshot, nil } @@ -829,6 +824,7 @@ func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.T return nil, errors.New("failed to convert interface to SponsorshipWithProofs transaction") } sponsorshipSnapshot := &SponsorshipSnapshot{ + AssetID: tx.AssetID, MinSponsoredFee: tx.MinAssetFee, } @@ -934,42 +930,290 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot return snapshot, nil } -func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { - if _, ok := transaction.(*proto.InvokeScriptWithProofs); !ok { - return nil, errors.New("failed to convert interface to InvokeScriptWithProofs transaction") +func addToWavesBalanceDiff(addrWavesBalanceDiff addressWavesBalanceDiff, + senderAddress proto.WavesAddress, + recipientAddress proto.WavesAddress, + amount int64) { + if _, ok := addrWavesBalanceDiff[senderAddress]; ok { + prevBalance := addrWavesBalanceDiff[senderAddress] + prevBalance.balance -= amount + addrWavesBalanceDiff[senderAddress] = prevBalance + } else { + addrWavesBalanceDiff[senderAddress] = balanceDiff{balance: amount} } - if err := tp.stor.commitUncertain(info.blockID); err != nil { - return nil, errors.Wrap(err, "failed to commit invoke changes") + + if _, ok := addrWavesBalanceDiff[recipientAddress]; ok { + prevRecipientBalance := addrWavesBalanceDiff[recipientAddress] + prevRecipientBalance.balance += amount + addrWavesBalanceDiff[recipientAddress] = prevRecipientBalance + } else { + addrWavesBalanceDiff[recipientAddress] = balanceDiff{balance: amount} } - // TODO - if applicationRes != nil { +} + +// subtracts the amount from the sender's balance and add it to the recipient's balane +func addSenderRecipientToAssetBalanceDiff(addrAssetBalanceDiff addressAssetBalanceDiff, + senderAddress proto.WavesAddress, + recipientAddress proto.WavesAddress, + asset proto.AssetID, + amount int64) { + keySender := assetBalanceDiffKey{address: senderAddress, asset: asset} + keyRecipient := assetBalanceDiffKey{address: recipientAddress, asset: asset} + + if _, ok := addrAssetBalanceDiff[keySender]; ok { + prevSenderBalance := addrAssetBalanceDiff[keySender] + prevSenderBalance -= amount + addrAssetBalanceDiff[keySender] = prevSenderBalance + } else { + addrAssetBalanceDiff[keySender] = amount + } + + if _, ok := addrAssetBalanceDiff[keyRecipient]; ok { + prevRecipientBalance := addrAssetBalanceDiff[keyRecipient] + prevRecipientBalance += amount + addrAssetBalanceDiff[keyRecipient] = prevRecipientBalance + } else { + addrAssetBalanceDiff[keyRecipient] = amount + } +} + +// adds/subtracts the amount to the sender balance +func addSenderToAssetBalanceDiff(addrAssetBalanceDiff addressAssetBalanceDiff, + senderAddress proto.WavesAddress, + asset proto.AssetID, + amount int64) { + keySender := assetBalanceDiffKey{address: senderAddress, asset: asset} + + if _, ok := addrAssetBalanceDiff[keySender]; ok { + prevSenderBalance := addrAssetBalanceDiff[keySender] + prevSenderBalance += amount + addrAssetBalanceDiff[keySender] = prevSenderBalance + } else { + addrAssetBalanceDiff[keySender] = amount + } + +} + +func (tp *transactionPerformer) generateInvokeSnapshot(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { + + blockHeight := info.height + 1 + + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + var snapshot TransactionSnapshot + var dataEntries = make(map[proto.WavesAddress]proto.DataEntries) + if invocationRes != nil { + for _, action := range invocationRes.actions { switch a := action.(type) { case *proto.DataEntryScriptAction: + senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + if err != nil { + return nil, err + } + // construct the map first and create the snapshot later for convenience + if _, ok := dataEntries[senderAddr]; ok { + entries := dataEntries[senderAddr] + entries = append(entries, a.Entry) + dataEntries[senderAddr] = entries + } else { + dataEntries[senderAddr] = proto.DataEntries{a.Entry} + } case *proto.AttachedPaymentScriptAction: - + senderAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + if err != nil { + return nil, errors.Wrap(err, "failed to get an address from a public key") + } + recipientAddress, err := recipientToAddress(a.Recipient, tp.stor.aliases) + if err != nil { + return nil, errors.Wrap(err, "failed to apply attached payment") + } + // No balance validation done below + if a.Asset.Present { // Update asset balance + addSenderRecipientToAssetBalanceDiff(addrAssetBalanceDiff, senderAddress, recipientAddress, proto.AssetIDFromDigest(a.Asset.ID), a.Amount) + } else { // Update Waves balance + addToWavesBalanceDiff(addrWavesBalanceDiff, senderAddress, recipientAddress, a.Amount) + } case *proto.TransferScriptAction: - + senderAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + if err != nil { + return nil, errors.Wrap(err, "failed to get an address from a public key") + } + recipientAddress, err := recipientToAddress(a.Recipient, tp.stor.aliases) + if err != nil { + return nil, errors.Wrap(err, "failed to apply attached payment") + } + // No balance validation done below + if a.Asset.Present { // Update asset balance + addSenderRecipientToAssetBalanceDiff(addrAssetBalanceDiff, senderAddress, recipientAddress, proto.AssetIDFromDigest(a.Asset.ID), a.Amount) + } else { // Update Waves balance + addToWavesBalanceDiff(addrWavesBalanceDiff, senderAddress, recipientAddress, a.Amount) + } case *proto.SponsorshipScriptAction: - + sponsorshipSnapshot := &SponsorshipSnapshot{ + AssetID: a.AssetID, + MinSponsoredFee: uint64(a.MinFee), + } + snapshot = append(snapshot, sponsorshipSnapshot) case *proto.IssueScriptAction: + assetInfo := assetInfo{ + assetConstInfo: assetConstInfo{ + tail: proto.DigestTail(a.ID), + issuer: *a.Sender, + decimals: uint8(a.Decimals), + issueHeight: blockHeight, + issueSequenceInBlock: info.stateActionsCounter.NextIssueActionNumber(), + }, + assetChangeableInfo: assetChangeableInfo{ + quantity: *big.NewInt(a.Quantity), + name: a.Name, + description: a.Description, + lastNameDescChangeHeight: blockHeight, + reissuable: a.Reissuable, + }, + } + issuerAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + if err != nil { + return nil, errors.Wrap(err, "failed to get an address from a public key") + } + + issueStaticInfoSnapshot, assetDescription, assetReissuability := generateIssueSnapshots(a.ID, txID, *a.Sender, assetInfo) + snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) + + addSenderToAssetBalanceDiff(addrAssetBalanceDiff, issuerAddress, proto.AssetIDFromDigest(a.ID), a.Quantity) case *proto.ReissueScriptAction: + assetInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(a.AssetID)) + if err != nil { + return nil, err + } + quantityDiff := big.NewInt(a.Quantity) + resQuantity := assetInfo.quantity.Add(&assetInfo.quantity, quantityDiff) + assetReissuability := &AssetVolumeSnapshot{ + AssetID: a.AssetID, + TotalQuantity: *resQuantity, + IsReissuable: a.Reissuable, + } + + issueAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + if err != nil { + return nil, errors.Wrap(err, "failed to get an address from a public key") + } + addSenderToAssetBalanceDiff(addrAssetBalanceDiff, issueAddress, proto.AssetIDFromDigest(a.AssetID), a.Quantity) + snapshot = append(snapshot, assetReissuability) + case *proto.BurnScriptAction: + assetInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(a.AssetID)) + if err != nil { + return nil, err + } + quantityDiff := big.NewInt(a.Quantity) + resQuantity := assetInfo.quantity.Sub(&assetInfo.quantity, quantityDiff) + assetReissuability := &AssetVolumeSnapshot{ + AssetID: a.AssetID, + TotalQuantity: *resQuantity, + IsReissuable: assetInfo.reissuable, + } + issueAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + if err != nil { + return nil, errors.Wrap(err, "failed to get an address from a public key") + } + addSenderToAssetBalanceDiff(addrAssetBalanceDiff, issueAddress, proto.AssetIDFromDigest(a.AssetID), -a.Quantity) + snapshot = append(snapshot, assetReissuability) case *proto.LeaseScriptAction: - + senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + if err != nil { + return nil, err + } + var recipientAddr proto.WavesAddress + if addr := a.Recipient.Address(); addr == nil { + recipientAddr, err = tp.stor.aliases.newestAddrByAlias(a.Recipient.Alias().Alias) + if err != nil { + return nil, errors.Errorf("invalid alias: %v\n", err) + } + } else { + recipientAddr = *addr + } + l := &leasing{ + Sender: senderAddr, + Recipient: recipientAddr, + Amount: uint64(a.Amount), + Height: info.height, + Status: LeaseActive, + RecipientAlias: a.Recipient.Alias(), + } + var amount = int64(l.Amount) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseSnapshots(a.ID, *l, txID, senderAddr, recipientAddr, amount) + if err != nil { + return nil, errors.Wrap(err, "failed to generate snapshots for a lease action") + } + snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) case *proto.LeaseCancelScriptAction: + l, err := tp.stor.leases.leasingInfo(a.LeaseID) + if err != nil { + return nil, errors.Wrap(err, "failed to receiver leasing info") + } + var amount = -int64(l.Amount) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseSnapshots(a.LeaseID, *l, txID, l.Sender, l.Recipient, amount) + if err != nil { + return nil, errors.Wrap(err, "failed to generate snapshots for a lease cancel action") + } + snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) default: return nil, errors.Errorf("unknown script action type %T", a) } } + + for address, entries := range dataEntries { + dataEntrySnapshot := &DataEntriesSnapshot{Address: address, DataEntries: entries} + snapshot = append(snapshot, dataEntrySnapshot) + } + + } + + wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + for _, wb := range wavesBalanceSnapshot { + snapshot = append(snapshot, &wb) + } + for _, ab := range assetBalanceSnapshot { + snapshot = append(snapshot, &ab) } - return nil, nil + + return snapshot, nil +} + +func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { + if _, ok := transaction.(*proto.InvokeScriptWithProofs); !ok { + return nil, errors.New("failed to convert interface to InvokeScriptWithProofs transaction") + } + if err := tp.stor.commitUncertain(info.blockID); err != nil { + return nil, errors.Wrap(err, "failed to commit invoke changes") + } + txIDBytes, err := transaction.GetID(tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Errorf("failed to get transaction ID: %v\n", err) + } + txID, err := crypto.NewDigestFromBytes(txIDBytes) + if err != nil { + return nil, err + } + + snapshot, err := tp.generateInvokeSnapshot(txID, info, invocationRes, applicationRes) + if err != nil { + return nil, errors.Wrap(err, "failed to generate a snapshot for an invoke transaction") + } + + return snapshot, nil } func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { @@ -979,8 +1223,20 @@ func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction pr if err := tp.stor.commitUncertain(info.blockID); err != nil { return nil, errors.Wrap(err, "failed to commit invoke changes") } - // TODO - return nil, nil + txIDBytes, err := transaction.GetID(tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Errorf("failed to get transaction ID: %v\n", err) + } + txID, err := crypto.NewDigestFromBytes(txIDBytes) + if err != nil { + return nil, err + } + snapshot, err := tp.generateInvokeSnapshot(txID, info, invocationRes, applicationRes) + if err != nil { + return nil, errors.Wrap(err, "failed to generate a snapshot for an invoke transaction") + } + + return snapshot, nil } func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { @@ -993,25 +1249,20 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction return nil, errors.Wrap(err, "failed to commit invoke changes") } } - var snapshot TransactionSnapshot - if applicationRes != nil { - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) - if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") - } - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) - if err != nil { - return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") - } - for _, wb := range wavesBalanceSnapshot { - snapshot = append(snapshot, &wb) - } - for _, ab := range assetBalanceSnapshot { - snapshot = append(snapshot, &ab) - } + txIDBytes, err := transaction.GetID(tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Errorf("failed to get transaction ID: %v\n", err) + } + txID, err := crypto.NewDigestFromBytes(txIDBytes) + if err != nil { + return nil, err + } + + snapshot, err := tp.generateInvokeSnapshot(txID, info, invocationRes, applicationRes) + if err != nil { + return nil, errors.Wrap(err, "failed to generate a snapshot for an invoke transaction") } - // nothing to do for proto.EthereumTransferWavesTxKind and proto.EthereumTransferAssetsErc20TxKind return snapshot, nil } From 9665d45a15f36f48bef7c466ce0f62c864769c46 Mon Sep 17 00:00:00 2001 From: esuwu Date: Sat, 3 Jun 2023 19:56:27 -0500 Subject: [PATCH 16/27] Removed todos --- pkg/state/transaction_performer.go | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 0436e382a..f1218b125 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -61,19 +61,6 @@ func addressBalanceDiffFromTxDiff(diff txDiff, scheme proto.Scheme) (addressWave return addrWavesBalanceDiff, addrAssetBalanceDiff, nil } -//func (firstAddressBalanceDiff addressWavesBalanceDiff) mergeWithAnotherDiff(secondDiff addressWavesBalanceDiff) error { -// for address, diffBalance := range secondDiff { -// if _, ok := firstAddressBalanceDiff[address]; ok { -// oldBalance := firstAddressBalanceDiff[address] -// err := oldBalance.addCommon(&diffBalance) -// if err != nil { -// return errors.Wrap(err, "failed to merge two balance diffs") -// } -// } -// } -// return nil -//} - func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings.BlockchainSettings) (*transactionPerformer, error) { return &transactionPerformer{stor, settings}, nil } @@ -361,7 +348,6 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac return tp.performIssue(&tx.Issue, assetID, assetID, info, applicationRes) } -// TODO change balance of asset's owner func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { // Modify asset. change := &assetReissueChange{ @@ -424,7 +410,6 @@ func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Trans return tp.performReissue(&tx.Reissue, info, applicationRes) } -// TODO change balance of asset's owner func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { // Modify asset. change := &assetBurnChange{ From 62fbfaf4819c09d92625b1e83511adfe0bfa7b69 Mon Sep 17 00:00:00 2001 From: esuwu Date: Sat, 3 Jun 2023 19:57:39 -0500 Subject: [PATCH 17/27] Deleted useless code --- pkg/state/snapshots.go | 224 ----------------------------------------- 1 file changed, 224 deletions(-) delete mode 100644 pkg/state/snapshots.go diff --git a/pkg/state/snapshots.go b/pkg/state/snapshots.go deleted file mode 100644 index 7dca1b339..000000000 --- a/pkg/state/snapshots.go +++ /dev/null @@ -1,224 +0,0 @@ -package state - -//import ( -// "github.com/wavesplatform/gowaves/pkg/proto" -//) -// -//func (s *SnapshotManager) TxSnapshotFromTx(tx proto.Transaction, scheme proto.Scheme) (TransactionSnapshot, error) { -// var snapshots []AtomicSnapshot -// -// switch tx.GetTypeInfo().Type { -// case proto.GenesisTransaction: // 1 -// genesisTx, ok := tx.(*proto.Genesis) -// if !ok { -// // ... -// } -// wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ -// {address: &genesisTx.Recipient, balance: genesisTx.Amount}}, -// } -// snapshots = append(snapshots, wavesBalancesSnapshot) -// return snapshots, nil -// case proto.PaymentTransaction: // 2 -// paymentTx, ok := tx.(*proto.Payment) -// if !ok { -// // ... -// } -// senderAddress, err := proto.NewAddressFromPublicKey(scheme, paymentTx.SenderPK) -// if err != nil { -// //... -// } -// senderBalance, err := s.wavesBalanceByAddress(senderAddress) -// if err != nil { -// //... -// } -// recipientBalance, err := s.wavesBalanceByAddress(paymentTx.Recipient) -// if err != nil { -// //... -// } -// -// -// wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ -// {address: &senderAddress, balance: senderBalance - paymentTx.Amount - paymentTx.Fee}, -// {address: &paymentTx.Recipient, balance: recipientBalance + paymentTx.Amount}}, -// } -// snapshots = append(snapshots, wavesBalancesSnapshot) -// return snapshots, nil -// case proto.IssueTransaction: // 3 -// var issue proto.Issue -// switch i := tx.(type) { -// case *proto.IssueWithSig: -// issue = i.Issue -// case *proto.IssueWithProofs: -// issue = i.Issue -// default: -// // return err -// } -// senderAddress, err := proto.NewAddressFromPublicKey(scheme, issue.SenderPK) -// if err != nil { -// //... -// } -// senderBalance, err := s.wavesBalanceByAddress(senderAddress) -// if err != nil { -// //... -// } -// wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ -// {address: &senderAddress, balance: senderBalance - issue.Fee}}, -// } -// -// assetsSnapshot := &AssetDescriptionSnapshot{ -// assetID: proto.AssetID{}, -// assetName: &issue.Name, -// assetDescription: issue.Description, -// changeHeight: 0, -// } -// -// snapshots = append(snapshots, wavesBalancesSnapshot, assetsSnapshot) -// return snapshots, nil -// case proto.TransferTransaction: // 4 -// var transfer proto.Transfer -// switch t := tx.(type) { -// case *proto.TransferWithSig: -// transfer = t.Transfer -// case *proto.TransferWithProofs: -// transfer = t.Transfer -// default: -// // return err -// } -// senderAddress, err := proto.NewAddressFromPublicKey(scheme, transfer.SenderPK) -// if err != nil { -// //... -// } -// recipientAddress := transfer.Recipient.Address() -// assetBalancesSnapshot, wavesBalancesSnapshot, err := s.optionalAssetBalanceSnapshotTransfer(senderAddress, *recipientAddress, transfer.AmountAsset, transfer.Amount, transfer.FeeAsset, transfer.Fee) -// if err != nil { -// //... -// } -// if assetBalancesSnapshot != nil { -// snapshots = append(snapshots, assetBalancesSnapshot) -// } -// if wavesBalancesSnapshot != nil { -// snapshots = append(snapshots, wavesBalancesSnapshot) -// } -// return snapshots, nil -// case proto.ReissueTransaction: // 5 -// var reissue proto.Reissue -// switch t := tx.(type) { -// case *proto.ReissueWithSig: -// reissue = t.Reissue -// case *proto.ReissueWithProofs: -// reissue = t.Reissue -// default: -// // return err -// } -// assetInfo, err := s.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(reissue.AssetID)) -// if err != nil { -// // ... -// } -// senderAddress, err := proto.NewAddressFromPublicKey(scheme, reissue.SenderPK) -// if err != nil { -// //... -// } -// senderBalance, err := s.wavesBalanceByAddress(senderAddress) -// if err != nil { -// //... -// } -// wavesBalancesSnapshot := &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ -// {address: &senderAddress, balance: senderBalance - reissue.Fee}}, -// } -// snapshots = append(snapshots, wavesBalancesSnapshot) -// // TODO can you make an asset reissuable again? -// if assetInfo.reissuable != reissue.Reissuable { -// assetReissuabilitySnapshot := &AssetReissuabilitySnapshot{ -// assetID: proto.AssetIDFromDigest(reissue.AssetID), -// isReissuable: reissue.Reissuable, -// } -// snapshots = append(snapshots, assetReissuabilitySnapshot) -// } -// return snapshots, nil -// case proto.BurnTransaction: // 6 -// -// case proto.ExchangeTransaction: // 7 -// -// case proto.LeaseTransaction: // 8 -// -// case proto.LeaseCancelTransaction: // 9 -// -// case proto.CreateAliasTransaction: // 10 -// -// case proto.MassTransferTransaction: // 11 -// case proto.DataTransaction: // 12 -// case proto.SetScriptTransaction: // 13 -// case proto.SponsorshipTransaction: // 14 -// case proto.SetAssetScriptTransaction: // 15 -// case proto.InvokeScriptTransaction: // 16 -// case proto.UpdateAssetInfoTransaction: // 17 -// case proto.EthereumMetamaskTransaction: // 18 -// } -// return snapshots, nil -//} -// -//func (s SnapshotManager) optionalAssetBalanceSnapshotTransfer(sender proto.WavesAddress, recipient proto.WavesAddress, amountAsset proto.OptionalAsset, -// amount uint64, feeAsset proto.OptionalAsset, fee uint64) (*AssetBalancesSnapshot, *WavesBalancesSnapshot, error) { -// -// if amountAsset.Present { -// senderAssetBalance, err := s.stor.balances.assetBalance(sender.ID(), proto.AssetIDFromDigest(amountAsset.ID)) -// if err != nil { -// //... -// } -// recipientAssetBalance, err := s.stor.balances.assetBalance(recipient.ID(), proto.AssetIDFromDigest(amountAsset.ID)) -// if err != nil { -// //... -// } -// if feeAsset.Present { -// return &AssetBalancesSnapshot{assetBalances: []balanceAsset{ -// {address: sender, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: senderAssetBalance - amount - fee}, -// {address: recipient, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: recipientAssetBalance + amount}, -// }}, nil, nil -// } -// -// senderWavesBalance, err := s.stor.balances.wavesBalance(sender.ID()) -// if err != nil { -// //... -// } -// return &AssetBalancesSnapshot{assetBalances: []balanceAsset{ -// {address: sender, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: senderAssetBalance - amount}, -// {address: recipient, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: recipientAssetBalance + amount}, -// }}, &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ -// {address: sender, balance: senderWavesBalance.balance - fee}, -// }}, nil -// } -// -// senderWavesBalance, err := s.stor.balances.wavesBalance(sender.ID()) -// if err != nil { -// //... -// } -// recipientWavesBalance, err := s.stor.balances.wavesBalance(recipient.ID()) -// if err != nil { -// //... -// } -// if feeAsset.Present { -// senderAssetBalance, err := s.stor.balances.assetBalance(sender.ID(), proto.AssetIDFromDigest(amountAsset.ID)) -// if err != nil { -// //... -// } -// return &AssetBalancesSnapshot{assetBalances: []balanceAsset{ -// {address: sender, assetID: proto.AssetIDFromDigest(feeAsset.ID), balance: senderAssetBalance - fee}, -// }}, &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ -// {address: sender, balance: senderWavesBalance.balance - amount}, -// {address: recipient, balance: recipientWavesBalance.balance + amount}, -// }}, nil -// } -// -// return nil, &WavesBalancesSnapshot{wavesBalances: []balanceWaves{ -// {address: sender, balance: senderWavesBalance.balance - fee - amount}, -// {address: recipient, balance: senderWavesBalance.balance + amount}, -// }}, nil -//} -// -//func (s *SnapshotManager) wavesBalanceByAddress(address proto.WavesAddress) (uint64, error) { -// recipientWavesBalanceProfile, err := s.stor.balances.wavesBalance(address.ID()) -// if err != nil { -// //... -// } -// return recipientWavesBalanceProfile.balance, nil -//} From ba901974964a9a3c6ae9173de1a717c673adeb7e Mon Sep 17 00:00:00 2001 From: esuwu Date: Tue, 6 Jun 2023 18:04:26 -0500 Subject: [PATCH 18/27] Fixed a mistake with leasing cancel --- pkg/state/transaction_performer.go | 6 +++--- pkg/state/transaction_snapshot_test.go | 29 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 pkg/state/transaction_snapshot_test.go diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index f1218b125..9410873e2 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -72,7 +72,7 @@ func (tp *transactionPerformer) constructWavesBalanceSnapshotFromDiff(diff addre for wavesAddress, diffAmount := range diff { - fullBalance, err := tp.stor.balances.wavesBalance(wavesAddress.ID()) + fullBalance, err := tp.stor.balances.newestWavesBalance(wavesAddress.ID()) if err != nil { return nil, errors.Wrap(err, "failed to receive sender's waves balance") } @@ -566,7 +566,7 @@ func (tp *transactionPerformer) generateLeaseSnapshots(leaseID crypto.Digest, l Height: l.Height, } - senderBalanceProfile, err := tp.stor.balances.wavesBalance(senderAddress.ID()) + senderBalanceProfile, err := tp.stor.balances.newestWavesBalance(senderAddress.ID()) if err != nil { return nil, nil, nil, errors.Wrap(err, "failed to receive sender's waves balance") } @@ -576,7 +576,7 @@ func (tp *transactionPerformer) generateLeaseSnapshots(leaseID crypto.Digest, l LeaseOut: uint64(senderBalanceProfile.leaseOut + amount), } - receiverBalanceProfile, err := tp.stor.balances.wavesBalance(receiverAddress.ID()) + receiverBalanceProfile, err := tp.stor.balances.newestWavesBalance(receiverAddress.ID()) if err != nil { return nil, nil, nil, errors.Wrap(err, "failed to receive recipient's waves balance") } diff --git a/pkg/state/transaction_snapshot_test.go b/pkg/state/transaction_snapshot_test.go new file mode 100644 index 000000000..15fc43a02 --- /dev/null +++ b/pkg/state/transaction_snapshot_test.go @@ -0,0 +1,29 @@ +package state + +import ( + "github.com/stretchr/testify/assert" + "github.com/wavesplatform/gowaves/pkg/proto" + "github.com/wavesplatform/gowaves/pkg/settings" + "testing" +) + +// TODO send only txBalanceChanges to perfomer +func TestIssueTransactionSnapshot(t *testing.T) { + to := createDifferTestObjects(t) + + to.stor.addBlock(t, blockID0) + to.stor.activateFeature(t, int16(settings.NG)) + err := to.stor.entities.balances.setWavesBalance(testGlobal.senderInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, blockID0) + assert.NoError(t, err, "failed to sign issue tx") + tx := proto.NewUnsignedIssueWithSig(testGlobal.senderInfo.pk, "asset0", "description", defaultQuantity, defaultDecimals, true, defaultTimestamp, uint64(1000*FeeUnit)) + err = tx.Sign(proto.TestNetScheme, testGlobal.senderInfo.sk) + assert.NoError(t, err, "failed to sign issue tx") + + ch, err := to.td.createDiffIssueWithSig(tx, defaultDifferInfo()) + assert.NoError(t, err, "createDiffIssueWithSig() failed") + applicationRes := &applicationResult{true, 0, ch} + transactionSnapshot, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(), nil, applicationRes) + assert.NoError(t, err, "performIssueWithProofs() failed") + to.stor.flush(t) + assert.NotNil(t, transactionSnapshot) +} From a19d710e70aba4760c26f77f1706c0e2917afced Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 14 Jun 2023 15:11:19 -0500 Subject: [PATCH 19/27] Added tests for issue and reissue transactions --- pkg/state/transaction_performer.go | 333 +++++++++---------------- pkg/state/transaction_snapshot_test.go | 161 +++++++++++- 2 files changed, 277 insertions(+), 217 deletions(-) diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 9410873e2..3bef9d3e4 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -124,6 +124,27 @@ func (tp *transactionPerformer) constructBalancesSnapshotFromDiff(addrWavesBalan return wavesBalanceSnapshot, assetBalanceSnapshot, nil } +func (tp *transactionPerformer) transactionSnapshotFromTransactionBalanceDiff(applicationRes *applicationResult) (TransactionSnapshot, error) { + var transactionSnapshot TransactionSnapshot + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + wavesBalancesSnapshot, assetBalancesSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + for _, wb := range wavesBalancesSnapshot { + p := wb + transactionSnapshot = append(transactionSnapshot, &p) + } + for _, ab := range assetBalancesSnapshot { + p := ab + transactionSnapshot = append(transactionSnapshot, &p) + } + return transactionSnapshot, nil +} + func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { _, ok := transaction.(*proto.Genesis) if !ok { @@ -131,21 +152,11 @@ func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, in } var snapshot TransactionSnapshot if applicationRes != nil { - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + var err error + snapshot, err = tp.transactionSnapshotFromTransactionBalanceDiff(applicationRes) if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) - if err != nil { - return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") - } - for _, wb := range wavesBalanceSnapshot { - snapshot = append(snapshot, &wb) - } - for _, ab := range assetBalanceSnapshot { - snapshot = append(snapshot, &ab) - } - } return snapshot, nil @@ -158,21 +169,11 @@ func (tp *transactionPerformer) performPayment(transaction proto.Transaction, in } var snapshot TransactionSnapshot if applicationRes != nil { - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + var err error + snapshot, err = tp.transactionSnapshotFromTransactionBalanceDiff(applicationRes) if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) - if err != nil { - return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") - } - for _, wb := range wavesBalanceSnapshot { - snapshot = append(snapshot, &wb) - } - for _, ab := range assetBalanceSnapshot { - snapshot = append(snapshot, &ab) - } - } return snapshot, nil @@ -182,21 +183,11 @@ func (tp *transactionPerformer) performTransfer(applicationRes *applicationResul var snapshot TransactionSnapshot if applicationRes != nil { - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + var err error + snapshot, err = tp.transactionSnapshotFromTransactionBalanceDiff(applicationRes) if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") - } - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) - if err != nil { - return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } - for _, wb := range wavesBalanceSnapshot { - snapshot = append(snapshot, &wb) - } - for _, ab := range assetBalanceSnapshot { - snapshot = append(snapshot, &ab) - } - } return snapshot, nil @@ -287,15 +278,17 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest } } - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) + wavesBalancesSnapshot, assetBalancesSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - for _, wb := range wavesBalanceSnapshot { - snapshot = append(snapshot, &wb) + for _, wb := range wavesBalancesSnapshot { + p := wb + snapshot = append(snapshot, &p) } - for _, ab := range assetBalanceSnapshot { - snapshot = append(snapshot, &ab) + for _, ab := range assetBalancesSnapshot { + p := ab + snapshot = append(snapshot, &p) } if specialAssetSnapshot != nil { snapshot = append(snapshot, specialAssetSnapshot) @@ -362,30 +355,21 @@ func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performe quantityDiff := big.NewInt(change.diff) resQuantity := assetInfo.quantity.Add(&assetInfo.quantity, quantityDiff) - assetReissuability := &AssetVolumeSnapshot{ - AssetID: tx.AssetID, - TotalQuantity: *resQuantity, - IsReissuable: change.reissuable, - } var snapshot TransactionSnapshot - snapshot = append(snapshot, assetReissuability) if applicationRes != nil { - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) - if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") - } - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) + var err error + snapshot, err = tp.transactionSnapshotFromTransactionBalanceDiff(applicationRes) if err != nil { - return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } - for _, wb := range wavesBalanceSnapshot { - snapshot = append(snapshot, &wb) - } - for _, ab := range assetBalanceSnapshot { - snapshot = append(snapshot, &ab) + assetReissuability := &AssetVolumeSnapshot{ + AssetID: tx.AssetID, + TotalQuantity: *resQuantity, + IsReissuable: change.reissuable, } + snapshot = append(snapshot, assetReissuability) } if err := tp.stor.assets.reissueAsset(proto.AssetIDFromDigest(tx.AssetID), change, info.blockID); err != nil { @@ -422,30 +406,22 @@ func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, } quantityDiff := big.NewInt(change.diff) resQuantity := assetInfo.quantity.Sub(&assetInfo.quantity, quantityDiff) - assetReissuability := &AssetVolumeSnapshot{ - AssetID: tx.AssetID, - TotalQuantity: *resQuantity, - IsReissuable: assetInfo.reissuable, - } var snapshot TransactionSnapshot - snapshot = append(snapshot, assetReissuability) if applicationRes != nil { - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + var err error + snapshot, err = tp.transactionSnapshotFromTransactionBalanceDiff(applicationRes) if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") - } - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) - if err != nil { - return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") - } - for _, wb := range wavesBalanceSnapshot { - snapshot = append(snapshot, &wb) + return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } - for _, ab := range assetBalanceSnapshot { - snapshot = append(snapshot, &ab) + assetReissuability := &AssetVolumeSnapshot{ + AssetID: tx.AssetID, + TotalQuantity: *resQuantity, + IsReissuable: assetInfo.reissuable, } + snapshot = append(snapshot, assetReissuability) + } if err := tp.stor.assets.burnAsset(proto.AssetIDFromDigest(tx.AssetID), change, info.blockID); err != nil { @@ -533,24 +509,15 @@ func (tp *transactionPerformer) performExchange(transaction proto.Transaction, i } var snapshot TransactionSnapshot - snapshot = append(snapshot, sellOrderSnapshot, buyOrderSnapshot) - if applicationRes != nil { - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + var err error + snapshot, err = tp.transactionSnapshotFromTransactionBalanceDiff(applicationRes) if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") - } - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) - if err != nil { - return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") - } - for _, wb := range wavesBalanceSnapshot { - snapshot = append(snapshot, &wb) - } - for _, ab := range assetBalanceSnapshot { - snapshot = append(snapshot, &ab) + return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } } + snapshot = append(snapshot, sellOrderSnapshot, buyOrderSnapshot) + return snapshot, nil } @@ -612,28 +579,21 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, Status: LeaseActive, RecipientAlias: tx.Recipient.Alias(), } - var amount = int64(tx.Amount) - leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseSnapshots(*id, *l, *id, senderAddr, recipientAddr, amount) - if err != nil { - return nil, errors.Wrap(err, "failed to generate snapshots for a lease transaction") - } var snapshot TransactionSnapshot - snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) if applicationRes != nil { - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + var err error + snapshot, err = tp.transactionSnapshotFromTransactionBalanceDiff(applicationRes) if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) + var amount = int64(tx.Amount) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseSnapshots(*id, *l, *id, senderAddr, recipientAddr, amount) if err != nil { - return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") - } - for _, wb := range wavesBalanceSnapshot { - snapshot = append(snapshot, &wb) - } - for _, ab := range assetBalanceSnapshot { - snapshot = append(snapshot, &ab) + return nil, errors.Wrap(err, "failed to generate snapshots for a lease transaction") } + + snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) + } if err := tp.stor.leases.addLeasing(*id, l, info.blockID); err != nil { @@ -659,34 +619,25 @@ func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transac } func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID *crypto.Digest, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { - leasingInfo, err := tp.stor.leases.leasingInfo(tx.LeaseID) + leasingInfo, err := tp.stor.leases.newestLeasingInfo(tx.LeaseID) if err != nil { return nil, errors.Wrap(err, "failed to receiver leasing info") } + var snapshot TransactionSnapshot + if applicationRes != nil { + var err error + snapshot, err = tp.transactionSnapshotFromTransactionBalanceDiff(applicationRes) + if err != nil { + return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") + } + } var amount = -int64(leasingInfo.Amount) leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseSnapshots(tx.LeaseID, *leasingInfo, *txID, leasingInfo.Sender, leasingInfo.Recipient, amount) if err != nil { return nil, errors.Wrap(err, "failed to generate snapshots for a lease cancel transaction") } - var snapshot TransactionSnapshot snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) - if applicationRes != nil { - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) - if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") - } - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) - if err != nil { - return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") - } - for _, wb := range wavesBalanceSnapshot { - snapshot = append(snapshot, &wb) - } - for _, ab := range assetBalanceSnapshot { - snapshot = append(snapshot, &ab) - } - } if err := tp.stor.leases.cancelLeasing(tx.LeaseID, info.blockID, info.height, txID); err != nil { return nil, errors.Wrap(err, "failed to cancel leasing") @@ -716,27 +667,19 @@ func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info * return nil, err } - aliasSnapshot := &AliasSnapshot{ - Address: senderAddr, - Alias: tx.Alias, - } var snapshot TransactionSnapshot - snapshot = append(snapshot, aliasSnapshot) if applicationRes != nil { - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + var err error + snapshot, err = tp.transactionSnapshotFromTransactionBalanceDiff(applicationRes) if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) - if err != nil { - return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") - } - for _, wb := range wavesBalanceSnapshot { - snapshot = append(snapshot, &wb) - } - for _, ab := range assetBalanceSnapshot { - snapshot = append(snapshot, &ab) + aliasSnapshot := &AliasSnapshot{ + Address: senderAddr, + Alias: tx.Alias, } + snapshot = append(snapshot, aliasSnapshot) + } if err := tp.stor.aliases.createAlias(tx.Alias.Alias, senderAddr, info.blockID); err != nil { @@ -771,29 +714,19 @@ func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transact return nil, err } - dataEntriesSnapshot := &DataEntriesSnapshot{ - Address: senderAddr, - DataEntries: tx.Entries, - } - var snapshot TransactionSnapshot - snapshot = append(snapshot, dataEntriesSnapshot) if applicationRes != nil { - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) - if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") - } - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) + var err error + snapshot, err = tp.transactionSnapshotFromTransactionBalanceDiff(applicationRes) if err != nil { - return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") - } - for _, wb := range wavesBalanceSnapshot { - snapshot = append(snapshot, &wb) - } - for _, ab := range assetBalanceSnapshot { - snapshot = append(snapshot, &ab) + return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } } + dataEntriesSnapshot := &DataEntriesSnapshot{ + Address: senderAddr, + DataEntries: tx.Entries, + } + snapshot = append(snapshot, dataEntriesSnapshot) for _, entry := range tx.Entries { if err := tp.stor.accountsDataStor.appendEntry(senderAddr, entry, info.blockID); err != nil { @@ -808,28 +741,21 @@ func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.T if !ok { return nil, errors.New("failed to convert interface to SponsorshipWithProofs transaction") } - sponsorshipSnapshot := &SponsorshipSnapshot{ - AssetID: tx.AssetID, - MinSponsoredFee: tx.MinAssetFee, - } var snapshot TransactionSnapshot - snapshot = append(snapshot, sponsorshipSnapshot) if applicationRes != nil { - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) - if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") - } - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) + var err error + snapshot, err = tp.transactionSnapshotFromTransactionBalanceDiff(applicationRes) if err != nil { - return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } - for _, wb := range wavesBalanceSnapshot { - snapshot = append(snapshot, &wb) - } - for _, ab := range assetBalanceSnapshot { - snapshot = append(snapshot, &ab) + + sponsorshipSnapshot := &SponsorshipSnapshot{ + AssetID: tx.AssetID, + MinSponsoredFee: tx.MinAssetFee, } + + snapshot = append(snapshot, sponsorshipSnapshot) } if err := tp.stor.sponsoredAssets.sponsorAsset(tx.AssetID, tx.MinAssetFee, info.blockID); err != nil { @@ -843,33 +769,25 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra if !ok { return nil, errors.New("failed to convert interface to SetScriptWithProofs transaction") } - var snapshot TransactionSnapshot - senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { return nil, err } - sponsorshipSnapshot := &AccountScriptSnapshot{ - SenderPublicKey: tx.SenderPK, - Script: tx.Script, - VerifierComplexity: 0, // TODO fix it - } - snapshot = append(snapshot, sponsorshipSnapshot) + var snapshot TransactionSnapshot + if applicationRes != nil { - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + var err error + snapshot, err = tp.transactionSnapshotFromTransactionBalanceDiff(applicationRes) if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") - } - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) - if err != nil { - return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } - for _, wb := range wavesBalanceSnapshot { - snapshot = append(snapshot, &wb) - } - for _, ab := range assetBalanceSnapshot { - snapshot = append(snapshot, &ab) + + sponsorshipSnapshot := &AccountScriptSnapshot{ + SenderPublicKey: tx.SenderPK, + Script: tx.Script, + VerifierComplexity: 0, // TODO fix it } + snapshot = append(snapshot, sponsorshipSnapshot) } if err := tp.stor.scriptsStorage.setAccountScript(senderAddr, tx.Script, tx.SenderPK, info.blockID); err != nil { @@ -885,6 +803,14 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot } var snapshot TransactionSnapshot + + if applicationRes != nil { + var err error + snapshot, err = tp.transactionSnapshotFromTransactionBalanceDiff(applicationRes) + if err != nil { + return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") + } + } sponsorshipSnapshot := &AssetScriptSnapshot{ AssetID: tx.AssetID, Script: tx.Script, @@ -892,23 +818,6 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot } snapshot = append(snapshot, sponsorshipSnapshot) - if applicationRes != nil { - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) - if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") - } - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) - if err != nil { - return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") - } - for _, wb := range wavesBalanceSnapshot { - snapshot = append(snapshot, &wb) - } - for _, ab := range assetBalanceSnapshot { - snapshot = append(snapshot, &ab) - } - } - if err := tp.stor.scriptsStorage.setAssetScript(tx.AssetID, tx.Script, tx.SenderPK, info.blockID); err != nil { return nil, errors.Wrap(err, "failed to set asset script") } diff --git a/pkg/state/transaction_snapshot_test.go b/pkg/state/transaction_snapshot_test.go index 15fc43a02..0ec1348ee 100644 --- a/pkg/state/transaction_snapshot_test.go +++ b/pkg/state/transaction_snapshot_test.go @@ -1,22 +1,73 @@ package state import ( + "encoding/json" + "fmt" "github.com/stretchr/testify/assert" "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/settings" + "math/big" "testing" ) +func defaultAssetInfoTransfer(tail [12]byte, reissuable bool, amount int64) *assetInfo { + return &assetInfo{ + assetConstInfo: assetConstInfo{ + tail: tail, + issuer: testGlobal.issuerInfo.pk, + decimals: 2, + }, + assetChangeableInfo: assetChangeableInfo{ + quantity: *big.NewInt(amount), + name: "asset", + description: "description", + lastNameDescChangeHeight: 1, + reissuable: reissuable, + }, + } +} + +func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { + to := createDifferTestObjects(t) + + to.stor.addBlock(t, blockID0) + to.stor.activateFeature(t, int16(settings.NG)) + + err := to.stor.entities.balances.setWavesBalance(testGlobal.issuerInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, blockID0) + assert.NoError(t, err, "failed to set waves balance") + + tx := proto.NewUnsignedTransferWithSig(testGlobal.issuerInfo.pk, proto.NewOptionalAssetWaves(), proto.NewOptionalAssetWaves(), defaultTimestamp, defaultAmount*1000*2, uint64(FeeUnit), testGlobal.recipientInfo.Recipient(), nil) + err = tx.Sign(proto.TestNetScheme, testGlobal.issuerInfo.sk) + assert.NoError(t, err, "failed to sign transfer tx") + + ch, err := to.td.createDiffTransferWithSig(tx, defaultDifferInfo()) + assert.NoError(t, err, "createDiffTransferWithSig() failed") + applicationRes := &applicationResult{true, 0, ch} + transactionSnapshot, err := to.tp.performTransferWithSig(tx, defaultPerformerInfo(), nil, applicationRes) + + for _, s := range transactionSnapshot { + b, _ := json.Marshal(s) + fmt.Println(string(b)) + } + + assert.NoError(t, err, "performIssueWithProofs() failed") + to.stor.flush(t) + assert.NotNil(t, transactionSnapshot) +} + // TODO send only txBalanceChanges to perfomer -func TestIssueTransactionSnapshot(t *testing.T) { +func TestDefaultIssueTransactionSnapshot(t *testing.T) { to := createDifferTestObjects(t) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) - err := to.stor.entities.balances.setWavesBalance(testGlobal.senderInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, blockID0) - assert.NoError(t, err, "failed to sign issue tx") - tx := proto.NewUnsignedIssueWithSig(testGlobal.senderInfo.pk, "asset0", "description", defaultQuantity, defaultDecimals, true, defaultTimestamp, uint64(1000*FeeUnit)) - err = tx.Sign(proto.TestNetScheme, testGlobal.senderInfo.sk) + err := to.stor.entities.balances.setWavesBalance(testGlobal.issuerInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, blockID0) + assert.NoError(t, err, "failed to set waves balance") + err = to.stor.entities.balances.setAssetBalance(testGlobal.issuerInfo.addr.ID(), proto.AssetIDFromDigest(testGlobal.asset0.assetID), 1000000000, blockID0) + assert.NoError(t, err, "failed to set waves balance") + + tx := proto.NewUnsignedIssueWithSig(testGlobal.issuerInfo.pk, "asset0", "description", defaultQuantity, defaultDecimals, true, defaultTimestamp, uint64(1*FeeUnit)) + err = tx.Sign(proto.TestNetScheme, testGlobal.issuerInfo.sk) assert.NoError(t, err, "failed to sign issue tx") ch, err := to.td.createDiffIssueWithSig(tx, defaultDifferInfo()) @@ -24,6 +75,106 @@ func TestIssueTransactionSnapshot(t *testing.T) { applicationRes := &applicationResult{true, 0, ch} transactionSnapshot, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(), nil, applicationRes) assert.NoError(t, err, "performIssueWithProofs() failed") + for _, s := range transactionSnapshot { + b, _ := json.Marshal(s) + fmt.Println(string(b)) + } + fmt.Println(tx.ID.String()) + expectedSnapshot := TransactionSnapshot{ + &StaticAssetInfoSnapshot{ + AssetID: *tx.ID, + SourceTransactionID: *tx.ID, + IssuerPublicKey: testGlobal.issuerInfo.pk, + Decimals: defaultDecimals, + IsNFT: false}, + &AssetDescriptionSnapshot{ + AssetID: *tx.ID, + AssetName: "asset0", + AssetDescription: "description", + ChangeHeight: 1, + }, + &AssetVolumeSnapshot{ + AssetID: *tx.ID, + TotalQuantity: *big.NewInt(int64(defaultQuantity)), + IsReissuable: true, + }, + &WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &WavesBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + Balance: 299900000, + }, + &AssetBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + AssetID: *tx.ID, + Balance: 1000, + }, + } + + assert.Equal(t, expectedSnapshot, transactionSnapshot) + to.stor.flush(t) +} + +func TestDefaultReissueSnapshot(t *testing.T) { + to := createDifferTestObjects(t) + + to.stor.addBlock(t, blockID0) + to.stor.activateFeature(t, int16(settings.NG)) + err := to.stor.entities.assets.issueAsset(proto.AssetIDFromDigest(testGlobal.asset0.assetID), defaultAssetInfo(proto.DigestTail(testGlobal.asset0.assetID), true), blockID0) + assert.NoError(t, err, "failed to issue asset") + err = to.stor.entities.balances.setWavesBalance(testGlobal.issuerInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, blockID0) + assert.NoError(t, err, "failed to set waves balance") + err = to.stor.entities.balances.setAssetBalance(testGlobal.issuerInfo.addr.ID(), proto.AssetIDFromDigest(testGlobal.asset0.assetID), 1000, blockID0) + assert.NoError(t, err, "failed to set waves balance") + + tx := proto.NewUnsignedReissueWithSig(testGlobal.issuerInfo.pk, testGlobal.asset0.assetID, 50, false, defaultTimestamp, uint64(FeeUnit)) + err = tx.Sign(proto.TestNetScheme, testGlobal.issuerInfo.sk) + assert.NoError(t, err, "failed to sign transfer tx") + + ch, err := to.td.createDiffReissueWithSig(tx, defaultDifferInfo()) + assert.NoError(t, err, "createDiffTransferWithSig() failed") + applicationRes := &applicationResult{true, 0, ch} + transactionSnapshot, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(), nil, applicationRes) + + for _, s := range transactionSnapshot { + b, _ := json.Marshal(s) + fmt.Println(string(b)) + } + assert.NoError(t, err, "performIssueWithProofs() failed") + to.stor.flush(t) + assert.NotNil(t, transactionSnapshot) +} + +func TestDefaultBurnSnapshot(t *testing.T) { + to := createDifferTestObjects(t) + + to.stor.addBlock(t, blockID0) + to.stor.activateFeature(t, int16(settings.NG)) + err := to.stor.entities.assets.issueAsset(proto.AssetIDFromDigest(testGlobal.asset0.assetID), defaultAssetInfo(proto.DigestTail(testGlobal.asset0.assetID), true), blockID0) + //fmt.Println(testGlobal.issuerInfo.addr.String()) + //fmt.Println(testGlobal.issuerInfo.pk.String()) + assert.NoError(t, err, "failed to issue asset") + err = to.stor.entities.balances.setWavesBalance(testGlobal.issuerInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, blockID0) + assert.NoError(t, err, "failed to set waves balance") + err = to.stor.entities.balances.setAssetBalance(testGlobal.issuerInfo.addr.ID(), proto.AssetIDFromDigest(testGlobal.asset0.assetID), 1000000000, blockID0) + assert.NoError(t, err, "failed to set waves balance") + + tx := proto.NewUnsignedBurnWithSig(testGlobal.issuerInfo.pk, testGlobal.asset0.assetID, 50, defaultTimestamp, uint64(1000*FeeUnit)) + err = tx.Sign(proto.TestNetScheme, testGlobal.issuerInfo.sk) + assert.NoError(t, err, "failed to sign transfer tx") + fmt.Println(testGlobal.asset0.assetID) + ch, err := to.td.createDiffBurnWithSig(tx, defaultDifferInfo()) + assert.NoError(t, err, "createDiffTransferWithSig() failed") + applicationRes := &applicationResult{true, 0, ch} + transactionSnapshot, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(), nil, applicationRes) + + for _, s := range transactionSnapshot { + b, _ := json.Marshal(s) + fmt.Println(string(b)) + } + assert.NoError(t, err, "performIssueWithProofs() failed") to.stor.flush(t) assert.NotNil(t, transactionSnapshot) } From ddbaa2fd9ecb49cedc50785606490cb66b3aa3a4 Mon Sep 17 00:00:00 2001 From: esuwu Date: Thu, 15 Jun 2023 01:54:34 -0500 Subject: [PATCH 20/27] Fixed tests --- pkg/state/transaction_snapshot_test.go | 175 +++++++++++++++++++------ 1 file changed, 136 insertions(+), 39 deletions(-) diff --git a/pkg/state/transaction_snapshot_test.go b/pkg/state/transaction_snapshot_test.go index 0ec1348ee..d7590a4fc 100644 --- a/pkg/state/transaction_snapshot_test.go +++ b/pkg/state/transaction_snapshot_test.go @@ -2,11 +2,11 @@ package state import ( "encoding/json" - "fmt" "github.com/stretchr/testify/assert" "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/settings" "math/big" + "sort" "testing" ) @@ -44,15 +44,40 @@ func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { assert.NoError(t, err, "createDiffTransferWithSig() failed") applicationRes := &applicationResult{true, 0, ch} transactionSnapshot, err := to.tp.performTransferWithSig(tx, defaultPerformerInfo(), nil, applicationRes) - - for _, s := range transactionSnapshot { - b, _ := json.Marshal(s) - fmt.Println(string(b)) + assert.NoError(t, err, "failed to perform transfer tx") + expectedSnapshot := TransactionSnapshot{ + &WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &WavesBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + Balance: 299700000, + }, + &WavesBalanceSnapshot{ + Address: testGlobal.recipientInfo.addr, + Balance: 200000, + }, } - assert.NoError(t, err, "performIssueWithProofs() failed") + sort.Slice(expectedSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(expectedSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(expectedSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + sort.Slice(transactionSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(transactionSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(transactionSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + assert.Equal(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) - assert.NotNil(t, transactionSnapshot) } // TODO send only txBalanceChanges to perfomer @@ -63,9 +88,6 @@ func TestDefaultIssueTransactionSnapshot(t *testing.T) { to.stor.activateFeature(t, int16(settings.NG)) err := to.stor.entities.balances.setWavesBalance(testGlobal.issuerInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, blockID0) assert.NoError(t, err, "failed to set waves balance") - err = to.stor.entities.balances.setAssetBalance(testGlobal.issuerInfo.addr.ID(), proto.AssetIDFromDigest(testGlobal.asset0.assetID), 1000000000, blockID0) - assert.NoError(t, err, "failed to set waves balance") - tx := proto.NewUnsignedIssueWithSig(testGlobal.issuerInfo.pk, "asset0", "description", defaultQuantity, defaultDecimals, true, defaultTimestamp, uint64(1*FeeUnit)) err = tx.Sign(proto.TestNetScheme, testGlobal.issuerInfo.sk) assert.NoError(t, err, "failed to sign issue tx") @@ -74,12 +96,8 @@ func TestDefaultIssueTransactionSnapshot(t *testing.T) { assert.NoError(t, err, "createDiffIssueWithSig() failed") applicationRes := &applicationResult{true, 0, ch} transactionSnapshot, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(), nil, applicationRes) - assert.NoError(t, err, "performIssueWithProofs() failed") - for _, s := range transactionSnapshot { - b, _ := json.Marshal(s) - fmt.Println(string(b)) - } - fmt.Println(tx.ID.String()) + assert.NoError(t, err, "failed to perform issue tx") + expectedSnapshot := TransactionSnapshot{ &StaticAssetInfoSnapshot{ AssetID: *tx.ID, @@ -112,6 +130,21 @@ func TestDefaultIssueTransactionSnapshot(t *testing.T) { Balance: 1000, }, } + sort.Slice(expectedSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(expectedSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(expectedSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + sort.Slice(transactionSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(transactionSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(transactionSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) assert.Equal(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) @@ -122,29 +155,62 @@ func TestDefaultReissueSnapshot(t *testing.T) { to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) - err := to.stor.entities.assets.issueAsset(proto.AssetIDFromDigest(testGlobal.asset0.assetID), defaultAssetInfo(proto.DigestTail(testGlobal.asset0.assetID), true), blockID0) + err := to.stor.entities.assets.issueAsset(proto.AssetIDFromDigest(testGlobal.asset0.assetID), defaultAssetInfoTransfer(proto.DigestTail(testGlobal.asset0.assetID), true, 1000), blockID0) assert.NoError(t, err, "failed to issue asset") err = to.stor.entities.balances.setWavesBalance(testGlobal.issuerInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, blockID0) assert.NoError(t, err, "failed to set waves balance") err = to.stor.entities.balances.setAssetBalance(testGlobal.issuerInfo.addr.ID(), proto.AssetIDFromDigest(testGlobal.asset0.assetID), 1000, blockID0) assert.NoError(t, err, "failed to set waves balance") - tx := proto.NewUnsignedReissueWithSig(testGlobal.issuerInfo.pk, testGlobal.asset0.assetID, 50, false, defaultTimestamp, uint64(FeeUnit)) + tx := proto.NewUnsignedReissueWithSig(testGlobal.issuerInfo.pk, testGlobal.asset0.assetID, 50, false, defaultTimestamp, uint64(1*FeeUnit)) err = tx.Sign(proto.TestNetScheme, testGlobal.issuerInfo.sk) - assert.NoError(t, err, "failed to sign transfer tx") + assert.NoError(t, err, "failed to sign reissue tx") ch, err := to.td.createDiffReissueWithSig(tx, defaultDifferInfo()) - assert.NoError(t, err, "createDiffTransferWithSig() failed") + assert.NoError(t, err, "createDiffReissueWithSig() failed") applicationRes := &applicationResult{true, 0, ch} transactionSnapshot, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(), nil, applicationRes) + assert.NoError(t, err, "failed to perform reissue tx") - for _, s := range transactionSnapshot { - b, _ := json.Marshal(s) - fmt.Println(string(b)) + expectedSnapshot := TransactionSnapshot{ + &WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &WavesBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + Balance: 299900000, + }, + &AssetBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 1050, + }, + &AssetVolumeSnapshot{ + AssetID: testGlobal.asset0.assetID, + TotalQuantity: *big.NewInt(int64(defaultQuantity + 50)), + IsReissuable: false, + }, } - assert.NoError(t, err, "performIssueWithProofs() failed") + + sort.Slice(expectedSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(expectedSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(expectedSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + sort.Slice(transactionSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(transactionSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(transactionSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + assert.Equal(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) - assert.NotNil(t, transactionSnapshot) } func TestDefaultBurnSnapshot(t *testing.T) { @@ -152,29 +218,60 @@ func TestDefaultBurnSnapshot(t *testing.T) { to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) - err := to.stor.entities.assets.issueAsset(proto.AssetIDFromDigest(testGlobal.asset0.assetID), defaultAssetInfo(proto.DigestTail(testGlobal.asset0.assetID), true), blockID0) - //fmt.Println(testGlobal.issuerInfo.addr.String()) - //fmt.Println(testGlobal.issuerInfo.pk.String()) + err := to.stor.entities.assets.issueAsset(proto.AssetIDFromDigest(testGlobal.asset0.assetID), defaultAssetInfoTransfer(proto.DigestTail(testGlobal.asset0.assetID), true, 1000), blockID0) + assert.NoError(t, err, "failed to issue asset") err = to.stor.entities.balances.setWavesBalance(testGlobal.issuerInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, blockID0) assert.NoError(t, err, "failed to set waves balance") - err = to.stor.entities.balances.setAssetBalance(testGlobal.issuerInfo.addr.ID(), proto.AssetIDFromDigest(testGlobal.asset0.assetID), 1000000000, blockID0) - assert.NoError(t, err, "failed to set waves balance") + err = to.stor.entities.balances.setAssetBalance(testGlobal.issuerInfo.addr.ID(), proto.AssetIDFromDigest(testGlobal.asset0.assetID), 1000, blockID0) + assert.NoError(t, err, "failed to set asset balance") - tx := proto.NewUnsignedBurnWithSig(testGlobal.issuerInfo.pk, testGlobal.asset0.assetID, 50, defaultTimestamp, uint64(1000*FeeUnit)) + tx := proto.NewUnsignedBurnWithSig(testGlobal.issuerInfo.pk, testGlobal.asset0.assetID, 50, defaultTimestamp, uint64(1*FeeUnit)) err = tx.Sign(proto.TestNetScheme, testGlobal.issuerInfo.sk) - assert.NoError(t, err, "failed to sign transfer tx") - fmt.Println(testGlobal.asset0.assetID) + assert.NoError(t, err, "failed to sign burn tx") ch, err := to.td.createDiffBurnWithSig(tx, defaultDifferInfo()) - assert.NoError(t, err, "createDiffTransferWithSig() failed") + assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{true, 0, ch} transactionSnapshot, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(), nil, applicationRes) + assert.NoError(t, err, "failed to perform burn tx") - for _, s := range transactionSnapshot { - b, _ := json.Marshal(s) - fmt.Println(string(b)) + expectedSnapshot := TransactionSnapshot{ + &WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &WavesBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + Balance: 299900000, + }, + &AssetBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 950, + }, + &AssetVolumeSnapshot{ + AssetID: testGlobal.asset0.assetID, + TotalQuantity: *big.NewInt(int64(defaultQuantity - 50)), + IsReissuable: true, + }, } - assert.NoError(t, err, "performIssueWithProofs() failed") + + sort.Slice(expectedSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(expectedSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(expectedSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + sort.Slice(transactionSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(transactionSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(transactionSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + assert.Equal(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) - assert.NotNil(t, transactionSnapshot) } From d28da6a8fa8d4e83f59788230fcf17a2bee1ce27 Mon Sep 17 00:00:00 2001 From: esuwu Date: Sun, 18 Jun 2023 13:31:48 -0500 Subject: [PATCH 21/27] fixed implicit memory aliasing --- pkg/state/transaction_performer.go | 43 +++++++++++++++--------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 3bef9d3e4..57b949011 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -134,13 +134,11 @@ func (tp *transactionPerformer) transactionSnapshotFromTransactionBalanceDiff(ap if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - for _, wb := range wavesBalancesSnapshot { - p := wb - transactionSnapshot = append(transactionSnapshot, &p) + for i, _ := range wavesBalancesSnapshot { + transactionSnapshot = append(transactionSnapshot, &wavesBalancesSnapshot[i]) } - for _, ab := range assetBalancesSnapshot { - p := ab - transactionSnapshot = append(transactionSnapshot, &p) + for i, _ := range assetBalancesSnapshot { + transactionSnapshot = append(transactionSnapshot, &assetBalancesSnapshot[i]) } return transactionSnapshot, nil } @@ -282,13 +280,12 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - for _, wb := range wavesBalancesSnapshot { - p := wb - snapshot = append(snapshot, &p) + + for i, _ := range wavesBalancesSnapshot { + snapshot = append(snapshot, &wavesBalancesSnapshot[i]) } - for _, ab := range assetBalancesSnapshot { - p := ab - snapshot = append(snapshot, &p) + for i, _ := range assetBalancesSnapshot { + snapshot = append(snapshot, &assetBalancesSnapshot[i]) } if specialAssetSnapshot != nil { snapshot = append(snapshot, specialAssetSnapshot) @@ -1072,15 +1069,16 @@ func (tp *transactionPerformer) generateInvokeSnapshot(txID crypto.Digest, info } - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) + wavesBalancesSnapshot, assetBalancesSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - for _, wb := range wavesBalanceSnapshot { - snapshot = append(snapshot, &wb) + + for i, _ := range wavesBalancesSnapshot { + snapshot = append(snapshot, &wavesBalancesSnapshot[i]) } - for _, ab := range assetBalanceSnapshot { - snapshot = append(snapshot, &ab) + for i, _ := range assetBalancesSnapshot { + snapshot = append(snapshot, &assetBalancesSnapshot[i]) } return snapshot, nil @@ -1185,15 +1183,16 @@ func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction pro if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") } - wavesBalanceSnapshot, assetBalanceSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) + wavesBalancesSnapshot, assetBalancesSnapshot, err := tp.constructBalancesSnapshotFromDiff(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - for _, wb := range wavesBalanceSnapshot { - snapshot = append(snapshot, &wb) + + for i, _ := range wavesBalancesSnapshot { + snapshot = append(snapshot, &wavesBalancesSnapshot[i]) } - for _, ab := range assetBalanceSnapshot { - snapshot = append(snapshot, &ab) + for i, _ := range assetBalancesSnapshot { + snapshot = append(snapshot, &assetBalancesSnapshot[i]) } } From 8843880e327345e132ffae4ca4a51c9c064fb835 Mon Sep 17 00:00:00 2001 From: esuwu Date: Tue, 20 Jun 2023 01:14:28 -0500 Subject: [PATCH 22/27] Added tests for burn, lease, lease cancel, exchange and create alias transactions --- pkg/state/transaction_performer.go | 27 +- pkg/state/transaction_snapshot_test.go | 326 ++++++++++++++++++++++++- 2 files changed, 339 insertions(+), 14 deletions(-) diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 57b949011..122744239 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -56,6 +56,11 @@ func addressBalanceDiffFromTxDiff(diff txDiff, scheme proto.Scheme) (addressWave if err != nil { return nil, nil, errors.Wrap(err, "failed to convert address id to waves address") } + // if the waves balance diff is 0, it means it did not change. Though the record might occur when LeaseIn and LeaseOut change, + // but they are handled separately in snapshots + if diffAmount.balance == 0 { + continue + } addrWavesBalanceDiff[address] = diffAmount } return addrWavesBalanceDiff, addrAssetBalanceDiff, nil @@ -98,6 +103,7 @@ func (tp *transactionPerformer) constructAssetBalanceSnapshotFromDiff(diff addre if err != nil { return nil, errors.Wrap(err, "failed to get newest asset info") } + newBalance := AssetBalanceSnapshot{ Address: key.address, AssetID: key.asset.Digest(assetInfo.tail), @@ -134,10 +140,10 @@ func (tp *transactionPerformer) transactionSnapshotFromTransactionBalanceDiff(ap if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - for i, _ := range wavesBalancesSnapshot { + for i := range wavesBalancesSnapshot { transactionSnapshot = append(transactionSnapshot, &wavesBalancesSnapshot[i]) } - for i, _ := range assetBalancesSnapshot { + for i := range assetBalancesSnapshot { transactionSnapshot = append(transactionSnapshot, &assetBalancesSnapshot[i]) } return transactionSnapshot, nil @@ -281,10 +287,10 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - for i, _ := range wavesBalancesSnapshot { + for i := range wavesBalancesSnapshot { snapshot = append(snapshot, &wavesBalancesSnapshot[i]) } - for i, _ := range assetBalancesSnapshot { + for i := range assetBalancesSnapshot { snapshot = append(snapshot, &assetBalancesSnapshot[i]) } if specialAssetSnapshot != nil { @@ -620,6 +626,7 @@ func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID * if err != nil { return nil, errors.Wrap(err, "failed to receiver leasing info") } + var snapshot TransactionSnapshot if applicationRes != nil { var err error @@ -630,7 +637,8 @@ func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID * } var amount = -int64(leasingInfo.Amount) - leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseSnapshots(tx.LeaseID, *leasingInfo, *txID, leasingInfo.Sender, leasingInfo.Recipient, amount) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseSnapshots(tx.LeaseID, *leasingInfo, *leasingInfo.OriginTransactionID, leasingInfo.Sender, leasingInfo.Recipient, amount) + leaseStatusSnapshot.Status = LeaseCanceled if err != nil { return nil, errors.Wrap(err, "failed to generate snapshots for a lease cancel transaction") } @@ -885,6 +893,7 @@ func addSenderToAssetBalanceDiff(addrAssetBalanceDiff addressAssetBalanceDiff, } +// TODO optimize this func (tp *transactionPerformer) generateInvokeSnapshot(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { blockHeight := info.height + 1 @@ -1074,10 +1083,10 @@ func (tp *transactionPerformer) generateInvokeSnapshot(txID crypto.Digest, info return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - for i, _ := range wavesBalancesSnapshot { + for i := range wavesBalancesSnapshot { snapshot = append(snapshot, &wavesBalancesSnapshot[i]) } - for i, _ := range assetBalancesSnapshot { + for i := range assetBalancesSnapshot { snapshot = append(snapshot, &assetBalancesSnapshot[i]) } @@ -1188,10 +1197,10 @@ func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction pro return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } - for i, _ := range wavesBalancesSnapshot { + for i := range wavesBalancesSnapshot { snapshot = append(snapshot, &wavesBalancesSnapshot[i]) } - for i, _ := range assetBalancesSnapshot { + for i := range assetBalancesSnapshot { snapshot = append(snapshot, &assetBalancesSnapshot[i]) } } diff --git a/pkg/state/transaction_snapshot_test.go b/pkg/state/transaction_snapshot_test.go index d7590a4fc..2cd37ed44 100644 --- a/pkg/state/transaction_snapshot_test.go +++ b/pkg/state/transaction_snapshot_test.go @@ -3,6 +3,7 @@ package state import ( "encoding/json" "github.com/stretchr/testify/assert" + "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/settings" "math/big" @@ -10,16 +11,16 @@ import ( "testing" ) -func defaultAssetInfoTransfer(tail [12]byte, reissuable bool, amount int64) *assetInfo { +func defaultAssetInfoTransfer(tail [12]byte, reissuable bool, amount int64, issuer crypto.PublicKey, name string) *assetInfo { return &assetInfo{ assetConstInfo: assetConstInfo{ tail: tail, - issuer: testGlobal.issuerInfo.pk, + issuer: issuer, decimals: 2, }, assetChangeableInfo: assetChangeableInfo{ quantity: *big.NewInt(amount), - name: "asset", + name: name, description: "description", lastNameDescChangeHeight: 1, reissuable: reissuable, @@ -155,7 +156,7 @@ func TestDefaultReissueSnapshot(t *testing.T) { to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) - err := to.stor.entities.assets.issueAsset(proto.AssetIDFromDigest(testGlobal.asset0.assetID), defaultAssetInfoTransfer(proto.DigestTail(testGlobal.asset0.assetID), true, 1000), blockID0) + err := to.stor.entities.assets.issueAsset(proto.AssetIDFromDigest(testGlobal.asset0.assetID), defaultAssetInfoTransfer(proto.DigestTail(testGlobal.asset0.assetID), true, 1000, testGlobal.issuerInfo.pk, "asset0"), blockID0) assert.NoError(t, err, "failed to issue asset") err = to.stor.entities.balances.setWavesBalance(testGlobal.issuerInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, blockID0) assert.NoError(t, err, "failed to set waves balance") @@ -218,7 +219,7 @@ func TestDefaultBurnSnapshot(t *testing.T) { to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) - err := to.stor.entities.assets.issueAsset(proto.AssetIDFromDigest(testGlobal.asset0.assetID), defaultAssetInfoTransfer(proto.DigestTail(testGlobal.asset0.assetID), true, 1000), blockID0) + err := to.stor.entities.assets.issueAsset(proto.AssetIDFromDigest(testGlobal.asset0.assetID), defaultAssetInfoTransfer(proto.DigestTail(testGlobal.asset0.assetID), true, 1000, testGlobal.issuerInfo.pk, "asset0"), blockID0) assert.NoError(t, err, "failed to issue asset") err = to.stor.entities.balances.setWavesBalance(testGlobal.issuerInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, blockID0) @@ -275,3 +276,318 @@ func TestDefaultBurnSnapshot(t *testing.T) { assert.Equal(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) } + +func TestDefaultExchangeTransaction(t *testing.T) { + to := createDifferTestObjects(t) + + to.stor.addBlock(t, blockID0) + to.stor.activateFeature(t, int16(settings.NG)) + // issue assets + err := to.stor.entities.assets.issueAsset(proto.AssetIDFromDigest(testGlobal.asset0.assetID), defaultAssetInfoTransfer(proto.DigestTail(testGlobal.asset0.assetID), true, 1000, testGlobal.senderInfo.pk, "asset0"), blockID0) + assert.NoError(t, err, "failed to issue asset") + err = to.stor.entities.assets.issueAsset(proto.AssetIDFromDigest(testGlobal.asset1.assetID), defaultAssetInfoTransfer(proto.DigestTail(testGlobal.asset1.assetID), true, 1000, testGlobal.recipientInfo.pk, "asset1"), blockID0) + assert.NoError(t, err, "failed to issue asset") + + // set waves balance for the seller and the buyer + err = to.stor.entities.balances.setWavesBalance(testGlobal.senderInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, blockID0) + assert.NoError(t, err, "failed to set waves balance") + err = to.stor.entities.balances.setWavesBalance(testGlobal.recipientInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 2000 * FeeUnit * 3}}, blockID0) + assert.NoError(t, err, "failed to set waves balance") + + // set waves balance for the matcher account + err = to.stor.entities.balances.setWavesBalance(testGlobal.matcherInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 3000 * FeeUnit * 3}}, blockID0) + assert.NoError(t, err, "failed to set waves balance") + + // set asset balance for the seller and the buyer + err = to.stor.entities.balances.setAssetBalance(testGlobal.senderInfo.addr.ID(), proto.AssetIDFromDigest(testGlobal.asset1.assetID), 500, blockID0) + assert.NoError(t, err, "failed to set asset balance") + err = to.stor.entities.balances.setAssetBalance(testGlobal.recipientInfo.addr.ID(), proto.AssetIDFromDigest(testGlobal.asset0.assetID), 600, blockID0) + assert.NoError(t, err, "failed to set asset balance") + + bo := proto.NewUnsignedOrderV1(testGlobal.senderInfo.pk, testGlobal.matcherInfo.pk, *testGlobal.asset0.asset, *testGlobal.asset1.asset, proto.Buy, 10e8, 10, 0, 0, 3) + err = bo.Sign(proto.TestNetScheme, testGlobal.senderInfo.sk) + assert.NoError(t, err, "bo.Sign() failed") + so := proto.NewUnsignedOrderV1(testGlobal.recipientInfo.pk, testGlobal.matcherInfo.pk, *testGlobal.asset0.asset, *testGlobal.asset1.asset, proto.Sell, 10e8, 10, 0, 0, 3) + err = so.Sign(proto.TestNetScheme, testGlobal.recipientInfo.sk) + assert.NoError(t, err, "so.Sign() failed") + tx := proto.NewUnsignedExchangeWithSig(bo, so, bo.Price, bo.Amount, 1, 2, uint64(1*FeeUnit), defaultTimestamp) + err = tx.Sign(proto.TestNetScheme, testGlobal.matcherInfo.sk) + + assert.NoError(t, err, "failed to sign burn tx") + ch, err := to.td.createDiffExchange(tx, defaultDifferInfo()) + assert.NoError(t, err, "createDiffBurnWithSig() failed") + applicationRes := &applicationResult{true, 0, ch} + transactionSnapshot, err := to.tp.performExchange(tx, defaultPerformerInfo(), nil, applicationRes) + assert.NoError(t, err, "failed to perform burn tx") + + expectedSnapshot := TransactionSnapshot{ + &WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299999999, + }, + &WavesBalanceSnapshot{ + Address: testGlobal.recipientInfo.addr, + Balance: 599999998, + }, + &WavesBalanceSnapshot{ + Address: testGlobal.matcherInfo.addr, + Balance: 899900003, + }, + &WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &AssetBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 10, + }, + &AssetBalanceSnapshot{ + Address: testGlobal.recipientInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 590, + }, + &AssetBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + AssetID: testGlobal.asset1.assetID, + Balance: 400, + }, + &AssetBalanceSnapshot{ + Address: testGlobal.recipientInfo.addr, + AssetID: testGlobal.asset1.assetID, + Balance: 100, + }, + &FilledVolumeFeeSnapshot{ + OrderID: *bo.ID, + FilledVolume: 10, + FilledFee: 1, + }, + &FilledVolumeFeeSnapshot{ + OrderID: *so.ID, + FilledVolume: 10, + FilledFee: 2, + }, + } + + sort.Slice(expectedSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(expectedSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(expectedSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + sort.Slice(transactionSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(transactionSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(transactionSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + assert.Equal(t, expectedSnapshot, transactionSnapshot) + to.stor.flush(t) +} + +func TestDefaultLeaseSnapshot(t *testing.T) { + to := createDifferTestObjects(t) + + to.stor.addBlock(t, blockID0) + to.stor.activateFeature(t, int16(settings.NG)) + + err := to.stor.entities.balances.setWavesBalance(testGlobal.senderInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, blockID0) + assert.NoError(t, err, "failed to set waves balance") + + tx := proto.NewUnsignedLeaseWithSig(testGlobal.senderInfo.pk, testGlobal.recipientInfo.Recipient(), 50, uint64(1*FeeUnit), defaultTimestamp) + err = tx.Sign(proto.TestNetScheme, testGlobal.senderInfo.sk) + assert.NoError(t, err, "failed to sign burn tx") + ch, err := to.td.createDiffLeaseWithSig(tx, defaultDifferInfo()) + assert.NoError(t, err, "createDiffBurnWithSig() failed") + applicationRes := &applicationResult{true, 0, ch} + transactionSnapshot, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(), nil, applicationRes) + assert.NoError(t, err, "failed to perform burn tx") + + expectedSnapshot := TransactionSnapshot{ + &WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &LeaseStateSnapshot{ + LeaseID: *tx.ID, + Status: LeaseActive, + Amount: 50, + Sender: testGlobal.senderInfo.addr, + Recipient: testGlobal.recipientInfo.addr, + OriginTransactionID: *tx.ID, + Height: 0, + }, + &LeaseBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + LeaseIn: 0, + LeaseOut: 50, + }, + &LeaseBalanceSnapshot{ + Address: testGlobal.recipientInfo.addr, + LeaseIn: 50, + LeaseOut: 0, + }, + } + + sort.Slice(expectedSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(expectedSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(expectedSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + sort.Slice(transactionSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(transactionSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(transactionSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + assert.Equal(t, expectedSnapshot, transactionSnapshot) + to.stor.flush(t) +} + +func TestDefaultLeaseCancelSnapshot(t *testing.T) { + to := createDifferTestObjects(t) + + to.stor.addBlock(t, blockID0) + to.stor.activateFeature(t, int16(settings.NG)) + + leaseID := testGlobal.asset0.assetID + leasing := &leasing{ + Sender: testGlobal.senderInfo.addr, + Recipient: testGlobal.recipientInfo.addr, + Amount: 50, + Height: 1, + Status: LeaseActive, + RecipientAlias: testGlobal.recipientInfo.Recipient().Alias(), + OriginTransactionID: &leaseID, + } + err := to.stor.entities.leases.addLeasing(leaseID, leasing, blockID0) + assert.NoError(t, err, "failed to add leasing") + + err = to.stor.entities.balances.setWavesBalance(testGlobal.senderInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3, leaseIn: 0, leaseOut: 50}}, blockID0) + assert.NoError(t, err, "failed to set waves balance") + err = to.stor.entities.balances.setWavesBalance(testGlobal.recipientInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3, leaseIn: 50, leaseOut: 0}}, blockID0) + assert.NoError(t, err, "failed to set waves balance") + + tx := proto.NewUnsignedLeaseCancelWithSig(testGlobal.senderInfo.pk, leaseID, uint64(1*FeeUnit), defaultTimestamp) + err = tx.Sign(proto.TestNetScheme, testGlobal.senderInfo.sk) + assert.NoError(t, err, "failed to sign burn tx") + ch, err := to.td.createDiffLeaseCancelWithSig(tx, defaultDifferInfo()) + assert.NoError(t, err, "createDiffBurnWithSig() failed") + applicationRes := &applicationResult{true, 0, ch} + transactionSnapshot, err := to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(), nil, applicationRes) + assert.NoError(t, err, "failed to perform burn tx") + + expectedSnapshot := TransactionSnapshot{ + &WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &LeaseStateSnapshot{ + LeaseID: leaseID, + Status: LeaseCanceled, + Amount: 50, + Sender: testGlobal.senderInfo.addr, + Recipient: testGlobal.recipientInfo.addr, + OriginTransactionID: leaseID, + Height: 1, + }, + &LeaseBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + LeaseIn: 0, + LeaseOut: 0, + }, + &LeaseBalanceSnapshot{ + Address: testGlobal.recipientInfo.addr, + LeaseIn: 0, + LeaseOut: 0, + }, + } + sort.Slice(expectedSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(expectedSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(expectedSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + sort.Slice(transactionSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(transactionSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(transactionSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + assert.Equal(t, expectedSnapshot, transactionSnapshot) + to.stor.flush(t) +} + +func TestDefaultCreateAliasSnapshot(t *testing.T) { + to := createDifferTestObjects(t) + + to.stor.addBlock(t, blockID0) + to.stor.activateFeature(t, int16(settings.NG)) + err := to.stor.entities.balances.setWavesBalance(testGlobal.senderInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, blockID0) + assert.NoError(t, err, "failed to set waves balance") + + alias := proto.NewAlias(proto.TestNetScheme, "aliasForSender") + tx := proto.NewUnsignedCreateAliasWithSig(testGlobal.senderInfo.pk, *alias, uint64(1*FeeUnit), defaultTimestamp) + err = tx.Sign(proto.TestNetScheme, testGlobal.senderInfo.sk) + assert.NoError(t, err, "failed to sign burn tx") + ch, err := to.td.createDiffCreateAliasWithSig(tx, defaultDifferInfo()) + assert.NoError(t, err, "createDiffBurnWithSig() failed") + applicationRes := &applicationResult{true, 0, ch} + transactionSnapshot, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, applicationRes) + assert.NoError(t, err, "failed to perform burn tx") + + expectedSnapshot := TransactionSnapshot{ + &WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &AliasSnapshot{ + Address: testGlobal.senderInfo.addr, + Alias: *proto.NewAlias(proto.TestNetScheme, "aliasForSender"), + }, + } + + sort.Slice(expectedSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(expectedSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(expectedSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + sort.Slice(transactionSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(transactionSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(transactionSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + assert.Equal(t, expectedSnapshot, transactionSnapshot) + to.stor.flush(t) +} From 8cd823ff3acddfac1b42af73dd63c954d55b00ad Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 21 Jun 2023 04:03:12 -0500 Subject: [PATCH 23/27] Added tests for data, sponsorship, set account and asset script transactions --- pkg/state/appender.go | 1 + pkg/state/transaction_handler.go | 2 +- pkg/state/transaction_performer.go | 35 +++- pkg/state/transaction_performer_test.go | 2 +- pkg/state/transaction_snapshot_test.go | 264 ++++++++++++++++++++++++ 5 files changed, 300 insertions(+), 4 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 508da669d..da87caf22 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -345,6 +345,7 @@ func (a *txAppender) commitTxApplication(tx proto.Transaction, params *appendTxP blockID: params.checkerInfo.blockID, currentMinerAddress: currentMinerAddress, stateActionsCounter: params.stateActionsCounterInBlock, + checkerInfo: params.checkerInfo, // performer needs to know the estimator version which is stored in checker info } // TODO other snapshots snapshot, err = a.txHandler.performTx(tx, performerInfo, invocationRes, applicationRes) diff --git a/pkg/state/transaction_handler.go b/pkg/state/transaction_handler.go index 28bcd40c4..16ce0b524 100644 --- a/pkg/state/transaction_handler.go +++ b/pkg/state/transaction_handler.go @@ -89,7 +89,7 @@ func buildHandles(tc *transactionChecker, tp *transactionPerformer, td *transact tc.checkCreateAliasWithProofs, tp.performCreateAliasWithProofs, td.createDiffCreateAliasWithProofs, tf.minerFeeCreateAliasWithProofs, }, proto.TransactionTypeInfo{Type: proto.MassTransferTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkMassTransferWithProofs, nil, td.createDiffMassTransferWithProofs, tf.minerFeeMassTransferWithProofs, + tc.checkMassTransferWithProofs, tp.performMassTransferWithProofs, td.createDiffMassTransferWithProofs, tf.minerFeeMassTransferWithProofs, }, proto.TransactionTypeInfo{Type: proto.DataTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ tc.checkDataWithProofs, tp.performDataWithProofs, td.createDiffDataWithProofs, tf.minerFeeDataWithProofs, diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 122744239..5c36d9b44 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -14,6 +14,7 @@ type performerInfo struct { blockID proto.BlockID currentMinerAddress proto.WavesAddress stateActionsCounter *proto.StateActionsCounter + checkerInfo *checkerInfo } type transactionPerformer struct { @@ -709,6 +710,23 @@ func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.T return tp.performCreateAlias(&tx.CreateAlias, info, applicationRes) } +func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { + _, ok := transaction.(*proto.MassTransferWithProofs) + if !ok { + return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") + } + var snapshot TransactionSnapshot + if applicationRes != nil { + var err error + snapshot, err = tp.transactionSnapshotFromTransactionBalanceDiff(applicationRes) + if err != nil { + return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") + } + } + + return snapshot, nil +} + func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.DataWithProofs) if !ok { @@ -787,10 +805,16 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } + treeEstimation, err := tp.stor.scriptsComplexity.newestScriptComplexityByAddr(senderAddr, info.checkerInfo.estimatorVersion()) + if err != nil { + return nil, errors.Wrap(err, "failed to get verifier complexity from storage") + } + complexity := treeEstimation.Verifier + sponsorshipSnapshot := &AccountScriptSnapshot{ SenderPublicKey: tx.SenderPK, Script: tx.Script, - VerifierComplexity: 0, // TODO fix it + VerifierComplexity: uint64(complexity), } snapshot = append(snapshot, sponsorshipSnapshot) } @@ -816,10 +840,17 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } } + + treeEstimation, err := tp.stor.scriptsComplexity.newestScriptComplexityByAsset(proto.AssetIDFromDigest(tx.AssetID)) + if err != nil { + return nil, errors.Wrap(err, "failed to get verifier complexity from storage") + } + complexity := treeEstimation.Verifier + sponsorshipSnapshot := &AssetScriptSnapshot{ AssetID: tx.AssetID, Script: tx.Script, - Complexity: 0, // TDODO fix it + Complexity: uint64(complexity), // TDODO fix it } snapshot = append(snapshot, sponsorshipSnapshot) diff --git a/pkg/state/transaction_performer_test.go b/pkg/state/transaction_performer_test.go index 3ce84f90c..6853cfe61 100644 --- a/pkg/state/transaction_performer_test.go +++ b/pkg/state/transaction_performer_test.go @@ -25,7 +25,7 @@ func createPerformerTestObjects(t *testing.T) *performerTestObjects { } func defaultPerformerInfo() *performerInfo { - return &performerInfo{0, blockID0, proto.WavesAddress{}, new(proto.StateActionsCounter)} + return &performerInfo{0, blockID0, proto.WavesAddress{}, new(proto.StateActionsCounter), nil} } func TestPerformIssueWithSig(t *testing.T) { diff --git a/pkg/state/transaction_snapshot_test.go b/pkg/state/transaction_snapshot_test.go index 2cd37ed44..e6d93dc15 100644 --- a/pkg/state/transaction_snapshot_test.go +++ b/pkg/state/transaction_snapshot_test.go @@ -3,6 +3,7 @@ package state import ( "encoding/json" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/settings" @@ -28,6 +29,29 @@ func defaultAssetInfoTransfer(tail [12]byte, reissuable bool, amount int64, issu } } +func defaultPerformerInfoWithChecker(checker *checkerInfo) *performerInfo { + return &performerInfo{0, blockID0, proto.WavesAddress{}, new(proto.StateActionsCounter), checker} +} + +func defaultCheckerInfoHeight() *checkerInfo { + defaultBlockInfo := defaultBlockInfo() + return &checkerInfo{ + currentTimestamp: defaultBlockInfo.Timestamp, + parentTimestamp: defaultTimestamp - settings.MainNetSettings.MaxTxTimeBackOffset/2, + blockID: blockID0, + blockVersion: defaultBlockInfo.Version, + height: defaultBlockInfo.Height, + } +} + +func createCheckerCustomTestObjects(t *testing.T, stor *testStorageObjects) *checkerTestObjects { + tc, err := newTransactionChecker(proto.NewBlockIDFromSignature(genSig), stor.entities, settings.MainNetSettings) + require.NoError(t, err, "newTransactionChecker() failed") + tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings) + require.NoError(t, err, "newTransactionPerformer() failed") + return &checkerTestObjects{stor, tc, tp} +} + func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { to := createDifferTestObjects(t) @@ -591,3 +615,243 @@ func TestDefaultCreateAliasSnapshot(t *testing.T) { assert.Equal(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) } + +func TestDefaultDataSnapshot(t *testing.T) { + to := createDifferTestObjects(t) + + to.stor.addBlock(t, blockID0) + to.stor.activateFeature(t, int16(settings.NG)) + err := to.stor.entities.balances.setWavesBalance(testGlobal.senderInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, blockID0) + assert.NoError(t, err, "failed to set waves balance") + + tx := proto.NewUnsignedDataWithProofs(1, testGlobal.senderInfo.pk, uint64(1*FeeUnit), defaultTimestamp) + stringEntry := &proto.StringDataEntry{Key: "key_str", Value: "value_str"} + intEntry := &proto.IntegerDataEntry{Key: "key_int", Value: 2} + err = tx.AppendEntry(stringEntry) + require.NoError(t, err) + err = tx.AppendEntry(intEntry) + require.NoError(t, err) + + err = tx.Sign(proto.TestNetScheme, testGlobal.senderInfo.sk) + assert.NoError(t, err, "failed to sign burn tx") + ch, err := to.td.createDiffDataWithProofs(tx, defaultDifferInfo()) + assert.NoError(t, err, "createDiffBurnWithSig() failed") + applicationRes := &applicationResult{true, 0, ch} + transactionSnapshot, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(), nil, applicationRes) + assert.NoError(t, err, "failed to perform burn tx") + + expectedSnapshot := TransactionSnapshot{ + &WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &DataEntriesSnapshot{ + Address: testGlobal.senderInfo.addr, + DataEntries: []proto.DataEntry{&proto.StringDataEntry{Key: "key_str", Value: "value_str"}, &proto.IntegerDataEntry{Key: "key_int", Value: 2}}, + }, + } + + sort.Slice(expectedSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(expectedSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(expectedSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + sort.Slice(transactionSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(transactionSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(transactionSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + assert.Equal(t, expectedSnapshot, transactionSnapshot) + to.stor.flush(t) +} + +func TestDefaultSponsorshipSnapshot(t *testing.T) { + to := createDifferTestObjects(t) + + to.stor.addBlock(t, blockID0) + to.stor.activateFeature(t, int16(settings.NG)) + err := to.stor.entities.balances.setWavesBalance(testGlobal.senderInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, blockID0) + assert.NoError(t, err, "failed to set waves balance") + + tx := proto.NewUnsignedSponsorshipWithProofs(1, testGlobal.senderInfo.pk, testGlobal.asset0.assetID, uint64(5*FeeUnit), uint64(1*FeeUnit), defaultTimestamp) + + err = tx.Sign(proto.TestNetScheme, testGlobal.senderInfo.sk) + assert.NoError(t, err, "failed to sign burn tx") + ch, err := to.td.createDiffSponsorshipWithProofs(tx, defaultDifferInfo()) + assert.NoError(t, err, "createDiffBurnWithSig() failed") + applicationRes := &applicationResult{true, 0, ch} + transactionSnapshot, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(), nil, applicationRes) + assert.NoError(t, err, "failed to perform burn tx") + + expectedSnapshot := TransactionSnapshot{ + &WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &SponsorshipSnapshot{ + AssetID: testGlobal.asset0.assetID, + MinSponsoredFee: 500000, + }, + } + + sort.Slice(expectedSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(expectedSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(expectedSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + sort.Slice(transactionSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(transactionSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(transactionSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + assert.Equal(t, expectedSnapshot, transactionSnapshot) + to.stor.flush(t) +} + +func TestDefaultSetScriptSnapshot(t *testing.T) { + to := createDifferTestObjects(t) + + to.stor.addBlock(t, blockID0) + to.stor.activateFeature(t, int16(settings.NG)) + err := to.stor.entities.balances.setWavesBalance(testGlobal.senderInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, blockID0) + assert.NoError(t, err, "failed to set waves balance") + + tx := proto.NewUnsignedSetScriptWithProofs(1, testGlobal.senderInfo.pk, testGlobal.scriptBytes, uint64(1*FeeUnit), defaultTimestamp) + + err = tx.Sign(proto.TestNetScheme, testGlobal.senderInfo.sk) + assert.NoError(t, err, "failed to sign set script tx") + + co := createCheckerCustomTestObjects(t, to.stor) + checkerInfo := defaultCheckerInfoHeight() + co.stor = to.stor + _, err = co.tc.checkSetScriptWithProofs(tx, checkerInfo) + assert.NoError(t, err, "failed to check set script tx") + + ch, err := to.td.createDiffSetScriptWithProofs(tx, defaultDifferInfo()) + assert.NoError(t, err, "createDiffBurnWithSig() failed") + applicationRes := &applicationResult{true, 0, ch} + transactionSnapshot, err := to.tp.performSetScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerInfo), nil, applicationRes) + assert.NoError(t, err, "failed to perform burn tx") + + expectedSnapshot := TransactionSnapshot{ + &WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &AccountScriptSnapshot{ + SenderPublicKey: testGlobal.senderInfo.pk, + Script: testGlobal.scriptBytes, + VerifierComplexity: 340, + }, + } + + sort.Slice(expectedSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(expectedSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(expectedSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + sort.Slice(transactionSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(transactionSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(transactionSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + assert.Equal(t, expectedSnapshot, transactionSnapshot) + to.stor.flush(t) +} + +func TestDefaultSetAssetScriptSnapshot(t *testing.T) { + to := createDifferTestObjects(t) + + to.stor.addBlock(t, blockID0) + to.stor.activateFeature(t, int16(settings.NG)) + err := to.stor.entities.balances.setWavesBalance(testGlobal.senderInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, blockID0) + assert.NoError(t, err, "failed to set waves balance") + + err = to.stor.entities.assets.issueAsset(proto.AssetIDFromDigest(testGlobal.asset0.assetID), defaultAssetInfoTransfer(proto.DigestTail(testGlobal.asset0.assetID), true, 1000, testGlobal.senderInfo.pk, "asset0"), blockID0) + assert.NoError(t, err, "failed to issue asset") + + err = to.stor.entities.scriptsStorage.setAssetScript(testGlobal.asset0.assetID, testGlobal.scriptBytes, testGlobal.senderInfo.pk, blockID0) + assert.NoError(t, err, "failed to issue asset") + + tx := proto.NewUnsignedSetAssetScriptWithProofs(1, testGlobal.senderInfo.pk, testGlobal.asset0.assetID, testGlobal.scriptBytes, uint64(1*FeeUnit), defaultTimestamp) + + err = tx.Sign(proto.TestNetScheme, testGlobal.senderInfo.sk) + assert.NoError(t, err, "failed to sign burn tx") + + co := createCheckerCustomTestObjects(t, to.stor) + checkerInfo := defaultCheckerInfoHeight() + co.stor = to.stor + _, err = co.tc.checkSetAssetScriptWithProofs(tx, checkerInfo) + assert.NoError(t, err, "failed to check set script tx") + + ch, err := to.td.createDiffSetAssetScriptWithProofs(tx, defaultDifferInfo()) + assert.NoError(t, err, "createDiffBurnWithSig() failed") + applicationRes := &applicationResult{true, 0, ch} + transactionSnapshot, err := to.tp.performSetAssetScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerInfo), nil, applicationRes) + assert.NoError(t, err, "failed to perform burn tx") + + expectedSnapshot := TransactionSnapshot{ + &WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &AssetScriptSnapshot{ + AssetID: testGlobal.asset0.assetID, + Script: testGlobal.scriptBytes, + Complexity: 340, + }, + } + + sort.Slice(expectedSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(expectedSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(expectedSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + sort.Slice(transactionSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(transactionSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(transactionSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + assert.Equal(t, expectedSnapshot, transactionSnapshot) + to.stor.flush(t) +} From cfef63a6f4a0ed5f8cb4acc0173659e996fb1a66 Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 28 Jun 2023 00:34:06 -0500 Subject: [PATCH 24/27] Added a test for the invoke transaction snapshots --- pkg/state/transaction_snapshot_test.go | 119 +++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/pkg/state/transaction_snapshot_test.go b/pkg/state/transaction_snapshot_test.go index e6d93dc15..08469ab7f 100644 --- a/pkg/state/transaction_snapshot_test.go +++ b/pkg/state/transaction_snapshot_test.go @@ -1,11 +1,14 @@ package state import ( + "encoding/base64" "encoding/json" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" + "github.com/wavesplatform/gowaves/pkg/ride" + "github.com/wavesplatform/gowaves/pkg/ride/serialization" "github.com/wavesplatform/gowaves/pkg/settings" "math/big" "sort" @@ -855,3 +858,119 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.T) { assert.Equal(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) } + +func setScript(t *testing.T, to *differTestObjects, addr proto.WavesAddress, pk crypto.PublicKey, script proto.Script) { + tree, err := serialization.Parse(script) + require.NoError(t, err) + estimation, err := ride.EstimateTree(tree, 1) + require.NoError(t, err) + err = to.stor.entities.scriptsComplexity.saveComplexitiesForAddr(addr, map[int]ride.TreeEstimation{1: estimation}, blockID0) + assert.NoError(t, err, "failed to save complexity for address") + err = to.stor.entities.scriptsStorage.setAccountScript(addr, script, pk, blockID0) + assert.NoError(t, err, "failed to set account script") +} + +func TestDefaultInvokeScriptSnapshot(t *testing.T) { + /* + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + @Callable(i) + func call() = { + [ + BooleanEntry("bool", true), + IntegerEntry("int", 1), + StringEntry("str", "") + ] + } + */ + script := "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAAEY2FsbAAAAAAJAARMAAAAAgkBAAAADEJvb2xlYW5FbnRyeQAAAAICAAAABGJvb2wGCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAANpbnQAAAAAAAAAAAEJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgIAAAADc3RyAgAAAAAFAAAAA25pbAAAAADr9Rv/" + scriptsBytes, err := base64.StdEncoding.DecodeString(script) + assert.NoError(t, err, "failed to set decode base64 script") + + to := createDifferTestObjects(t) + + to.stor.addBlock(t, blockID0) + to.stor.activateFeature(t, int16(settings.NG)) + to.stor.activateFeature(t, int16(settings.Ride4DApps)) + to.stor.activateFeature(t, int16(settings.RideV5)) + + setScript(t, to, testGlobal.recipientInfo.addr, testGlobal.recipientInfo.pk, scriptsBytes) + + err = to.stor.entities.balances.setWavesBalance(testGlobal.senderInfo.addr.ID(), &wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, blockID0) + assert.NoError(t, err, "failed to set waves balance") + + functionCall := proto.NewFunctionCall("call", nil) + invokeFee = FeeUnit * feeConstants[proto.InvokeScriptTransaction] + feeAsset = proto.NewOptionalAssetWaves() + + tx := proto.NewUnsignedInvokeScriptWithProofs(1, testGlobal.senderInfo.pk, proto.NewRecipientFromAddress(testGlobal.recipientInfo.addr), functionCall, []proto.ScriptPayment{}, feeAsset, invokeFee, defaultTimestamp) + err = tx.Sign(proto.TestNetScheme, testGlobal.senderInfo.sk) + assert.NoError(t, err, "failed to sign invoke script tx") + + co := createCheckerCustomTestObjects(t, to.stor) + checkerInfo := defaultCheckerInfoHeight() + co.stor = to.stor + _, err = co.tc.checkInvokeScriptWithProofs(tx, checkerInfo) + assert.NoError(t, err, "failed to check invoke script tx") + + ch, err := to.td.createDiffInvokeScriptWithProofs(tx, defaultDifferInfo()) + assert.NoError(t, err, "createDiffInvokeScriptWithProofs() failed") + + actions := []proto.ScriptAction{ + &proto.DataEntryScriptAction{ + Entry: &proto.BooleanDataEntry{Key: "bool", Value: true}, + Sender: &testGlobal.recipientInfo.pk}, + &proto.DataEntryScriptAction{ + Entry: &proto.IntegerDataEntry{Key: "int", Value: 1}, + Sender: &testGlobal.recipientInfo.pk}, + &proto.DataEntryScriptAction{ + Entry: &proto.StringDataEntry{Key: "int", Value: ""}, + Sender: &testGlobal.recipientInfo.pk}, + } + + invocationResult := &invocationResult{actions: actions, changes: ch} + + applicationRes := &applicationResult{true, 0, ch} + transactionSnapshot, err := to.tp.performInvokeScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerInfo), invocationResult, applicationRes) + assert.NoError(t, err, "failed to perform invoke script tx") + + expectedSnapshot := TransactionSnapshot{ + &WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 200000, + }, + &WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299500000, + }, + &DataEntriesSnapshot{ + Address: testGlobal.recipientInfo.addr, + DataEntries: []proto.DataEntry{ + &proto.BooleanDataEntry{Key: "bool", Value: true}, + &proto.IntegerDataEntry{Key: "int", Value: 1}, + &proto.StringDataEntry{Key: "int", Value: ""}, + }, + }, + } + + sort.Slice(expectedSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(expectedSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(expectedSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + sort.Slice(transactionSnapshot, func(i, j int) bool { + snapshotI, err := json.Marshal(transactionSnapshot[i]) + assert.NoError(t, err, "failed to marshal snapshots") + snapshotJ, err := json.Marshal(transactionSnapshot[j]) + assert.NoError(t, err, "failed to marshal snapshots") + return string(snapshotI) < string(snapshotJ) + }) + + assert.Equal(t, expectedSnapshot, transactionSnapshot) + to.stor.flush(t) +} From 624df000efef043cfa0a6a0ce4b4ddc5768b0cf9 Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 28 Jun 2023 00:49:07 -0500 Subject: [PATCH 25/27] Fixed after merge --- pkg/state/transaction_performer.go | 25 +++++++++++++++---------- pkg/state/transaction_snapshot_test.go | 19 ++++++++++++------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 2eb71ad9d..d52873ef4 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -528,12 +528,14 @@ func (tp *transactionPerformer) performExchange(transaction proto.Transaction, i func (tp *transactionPerformer) generateLeaseSnapshots(leaseID crypto.Digest, l leasing, originalTxID crypto.Digest, senderAddress proto.WavesAddress, receiverAddress proto.WavesAddress, amount int64) (*LeaseStateSnapshot, *LeaseBalanceSnapshot, *LeaseBalanceSnapshot, error) { leaseStatusSnapshot := &LeaseStateSnapshot{ - LeaseID: leaseID, - Status: l.Status, + LeaseID: leaseID, + Status: LeaseStateStatus{ + Value: l.Status, + }, Amount: l.Amount, Sender: l.Sender, Recipient: l.Recipient, - OriginTransactionID: originalTxID, + OriginTransactionID: &originalTxID, Height: l.Height, } @@ -638,7 +640,11 @@ func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID * var amount = -int64(leasingInfo.Amount) leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseSnapshots(tx.LeaseID, *leasingInfo, *leasingInfo.OriginTransactionID, leasingInfo.Sender, leasingInfo.Recipient, amount) - leaseStatusSnapshot.Status = LeaseCanceled + leaseStatusSnapshot.Status = LeaseStateStatus{ + Value: LeaseCanceled, + CancelHeight: info.height, + CancelTransactionID: txID, + } if err != nil { return nil, errors.Wrap(err, "failed to generate snapshots for a lease cancel transaction") } @@ -1071,12 +1077,11 @@ func (tp *transactionPerformer) generateInvokeSnapshot(txID crypto.Digest, info recipientAddr = *addr } l := &leasing{ - Sender: senderAddr, - Recipient: recipientAddr, - Amount: uint64(a.Amount), - Height: info.height, - Status: LeaseActive, - RecipientAlias: a.Recipient.Alias(), + Sender: senderAddr, + Recipient: recipientAddr, + Amount: uint64(a.Amount), + Height: info.height, + Status: LeaseActive, } var amount = int64(l.Amount) leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseSnapshots(a.ID, *l, txID, senderAddr, recipientAddr, amount) diff --git a/pkg/state/transaction_snapshot_test.go b/pkg/state/transaction_snapshot_test.go index 08469ab7f..358201558 100644 --- a/pkg/state/transaction_snapshot_test.go +++ b/pkg/state/transaction_snapshot_test.go @@ -444,12 +444,14 @@ func TestDefaultLeaseSnapshot(t *testing.T) { Balance: 299900000, }, &LeaseStateSnapshot{ - LeaseID: *tx.ID, - Status: LeaseActive, + LeaseID: *tx.ID, + Status: LeaseStateStatus{ + Value: LeaseActive, + }, Amount: 50, Sender: testGlobal.senderInfo.addr, Recipient: testGlobal.recipientInfo.addr, - OriginTransactionID: *tx.ID, + OriginTransactionID: tx.ID, Height: 0, }, &LeaseBalanceSnapshot{ @@ -497,7 +499,6 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { Amount: 50, Height: 1, Status: LeaseActive, - RecipientAlias: testGlobal.recipientInfo.Recipient().Alias(), OriginTransactionID: &leaseID, } err := to.stor.entities.leases.addLeasing(leaseID, leasing, blockID0) @@ -527,12 +528,16 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { Balance: 299900000, }, &LeaseStateSnapshot{ - LeaseID: leaseID, - Status: LeaseCanceled, + LeaseID: leaseID, + Status: LeaseStateStatus{ + Value: LeaseCanceled, + CancelHeight: 1, + CancelTransactionID: tx.ID, + }, Amount: 50, Sender: testGlobal.senderInfo.addr, Recipient: testGlobal.recipientInfo.addr, - OriginTransactionID: leaseID, + OriginTransactionID: &leaseID, Height: 1, }, &LeaseBalanceSnapshot{ From 1f45400041dede5e7a210d2ebf7b58d289a4c983 Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 28 Jun 2023 03:56:53 -0500 Subject: [PATCH 26/27] Fixed a function --- pkg/state/transaction_performer.go | 23 +++++++++++------------ pkg/state/transaction_snapshot_test.go | 2 +- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index d52873ef4..18aaa4fa3 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -844,20 +844,19 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } - } - - treeEstimation, err := tp.stor.scriptsComplexity.newestScriptComplexityByAsset(proto.AssetIDFromDigest(tx.AssetID)) - if err != nil { - return nil, errors.Wrap(err, "failed to get verifier complexity from storage") - } - complexity := treeEstimation.Verifier + treeEstimation, err := tp.stor.scriptsComplexity.newestScriptComplexityByAsset(proto.AssetIDFromDigest(tx.AssetID)) + if err != nil { + return nil, errors.Wrap(err, "failed to get verifier complexity from storage") + } + complexity := treeEstimation.Verifier - sponsorshipSnapshot := &AssetScriptSnapshot{ - AssetID: tx.AssetID, - Script: tx.Script, - Complexity: uint64(complexity), // TDODO fix it + sponsorshipSnapshot := &AssetScriptSnapshot{ + AssetID: tx.AssetID, + Script: tx.Script, + Complexity: uint64(complexity), // TDODO fix it + } + snapshot = append(snapshot, sponsorshipSnapshot) } - snapshot = append(snapshot, sponsorshipSnapshot) if err := tp.stor.scriptsStorage.setAssetScript(tx.AssetID, tx.Script, tx.SenderPK, info.blockID); err != nil { return nil, errors.Wrap(err, "failed to set asset script") diff --git a/pkg/state/transaction_snapshot_test.go b/pkg/state/transaction_snapshot_test.go index 358201558..a8db5b609 100644 --- a/pkg/state/transaction_snapshot_test.go +++ b/pkg/state/transaction_snapshot_test.go @@ -531,7 +531,7 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { LeaseID: leaseID, Status: LeaseStateStatus{ Value: LeaseCanceled, - CancelHeight: 1, + CancelHeight: 0, CancelTransactionID: tx.ID, }, Amount: 50, From 256dc87aca0dbfd96bbd7974efe7706fb1b7ef9e Mon Sep 17 00:00:00 2001 From: esuwu Date: Thu, 29 Jun 2023 21:22:28 -0500 Subject: [PATCH 27/27] Moved snapshot generation --- pkg/state/transaction_performer.go | 740 +----------------- pkg/state/transaction_performer_snapshots.go | 745 +++++++++++++++++++ 2 files changed, 750 insertions(+), 735 deletions(-) create mode 100644 pkg/state/transaction_performer_snapshots.go diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 195e04166..c5e7992a0 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -22,141 +22,10 @@ type transactionPerformer struct { settings *settings.BlockchainSettings } -type assetBalanceDiffKey struct { - address proto.WavesAddress - asset proto.AssetID -} - -type addressWavesBalanceDiff map[proto.WavesAddress]balanceDiff -type addressAssetBalanceDiff map[assetBalanceDiffKey]int64 - -func addressBalanceDiffFromTxDiff(diff txDiff, scheme proto.Scheme) (addressWavesBalanceDiff, addressAssetBalanceDiff, error) { - addrWavesBalanceDiff := make(addressWavesBalanceDiff) - addrAssetBalanceDiff := make(addressAssetBalanceDiff) - for balanceKeyString, diffAmount := range diff { - - // construct address from key - wavesBalanceKey := &wavesBalanceKey{} - err := wavesBalanceKey.unmarshal([]byte(balanceKeyString)) - if err != nil { - assetBalanceKey := &assetBalanceKey{} - err := assetBalanceKey.unmarshal([]byte(balanceKeyString)) - if err != nil { - return nil, nil, errors.Wrap(err, "failed to convert balance key to asset balance key") - } - asset := assetBalanceKey.asset - address, err := assetBalanceKey.address.ToWavesAddress(scheme) - if err != nil { - return nil, nil, errors.Wrap(err, "failed to convert address id to waves address") - } - assetBalKey := assetBalanceDiffKey{address: address, asset: asset} - addrAssetBalanceDiff[assetBalKey] = diffAmount.balance - continue - } - address, err := wavesBalanceKey.address.ToWavesAddress(scheme) - if err != nil { - return nil, nil, errors.Wrap(err, "failed to convert address id to waves address") - } - // if the waves balance diff is 0, it means it did not change. Though the record might occur when LeaseIn and LeaseOut change, - // but they are handled separately in snapshots - if diffAmount.balance == 0 { - continue - } - addrWavesBalanceDiff[address] = diffAmount - } - return addrWavesBalanceDiff, addrAssetBalanceDiff, nil -} - func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings.BlockchainSettings) (*transactionPerformer, error) { return &transactionPerformer{stor, settings}, nil } -// from txDiff and fees. no validation needed at this point -func (tp *transactionPerformer) constructWavesBalanceSnapshotFromDiff(diff addressWavesBalanceDiff) ([]WavesBalanceSnapshot, error) { - var wavesBalances []WavesBalanceSnapshot - // add miner address to the diff - - for wavesAddress, diffAmount := range diff { - - fullBalance, err := tp.stor.balances.newestWavesBalance(wavesAddress.ID()) - if err != nil { - return nil, errors.Wrap(err, "failed to receive sender's waves balance") - } - newBalance := WavesBalanceSnapshot{ - Address: wavesAddress, - Balance: uint64(int64(fullBalance.balance) + diffAmount.balance), - } - wavesBalances = append(wavesBalances, newBalance) - } - return wavesBalances, nil -} - -func (tp *transactionPerformer) constructAssetBalanceSnapshotFromDiff(diff addressAssetBalanceDiff) ([]AssetBalanceSnapshot, error) { - var assetBalances []AssetBalanceSnapshot - // add miner address to the diff - - for key, diffAmount := range diff { - balance, err := tp.stor.balances.newestAssetBalance(key.address.ID(), key.asset) - if err != nil { - return nil, errors.Wrap(err, "failed to receive sender's waves balance") - } - assetInfo, err := tp.stor.assets.newestAssetInfo(key.asset) - if err != nil { - return nil, errors.Wrap(err, "failed to get newest asset info") - } - - newBalance := AssetBalanceSnapshot{ - Address: key.address, - AssetID: key.asset.Digest(assetInfo.tail), - Balance: uint64(int64(balance) + diffAmount), - } - assetBalances = append(assetBalances, newBalance) - } - return assetBalances, nil -} - -func (tp *transactionPerformer) generateBalancesAtomicSnapshots(addrWavesBalanceDiff addressWavesBalanceDiff, addrAssetBalanceDiff addressAssetBalanceDiff) ([]WavesBalanceSnapshot, []AssetBalanceSnapshot, error) { - wavesBalanceSnapshot, err := tp.constructWavesBalanceSnapshotFromDiff(addrWavesBalanceDiff) - if err != nil { - return nil, nil, errors.Wrap(err, "failed to construct waves balance snapshot") - } - if len(addrAssetBalanceDiff) == 0 { - return wavesBalanceSnapshot, nil, nil - } - - assetBalanceSnapshot, err := tp.constructAssetBalanceSnapshotFromDiff(addrAssetBalanceDiff) - if err != nil { - return nil, nil, errors.Wrap(err, "failed to construct asset balance snapshot") - } - return wavesBalanceSnapshot, assetBalanceSnapshot, nil -} - -func (tp *transactionPerformer) generateBalancesSnapshot(applicationRes *applicationResult) (TransactionSnapshot, error) { - var transactionSnapshot TransactionSnapshot - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) - if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") - } - wavesBalancesSnapshot, assetBalancesSnapshot, err := tp.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) - if err != nil { - return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") - } - for i := range wavesBalancesSnapshot { - transactionSnapshot = append(transactionSnapshot, &wavesBalancesSnapshot[i]) - } - for i := range assetBalancesSnapshot { - transactionSnapshot = append(transactionSnapshot, &assetBalancesSnapshot[i]) - } - return transactionSnapshot, nil -} - -func (tp *transactionPerformer) generateSnapshotForGenesisTx(applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { - return nil, nil - } - return tp.generateBalancesSnapshot(applicationRes) -} - func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { _, ok := transaction.(*proto.Genesis) if !ok { @@ -165,13 +34,6 @@ func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, in return tp.generateSnapshotForGenesisTx(applicationRes) } -func (tp *transactionPerformer) generateSnapshotForPaymentTx(applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { - return nil, nil - } - return tp.generateBalancesSnapshot(applicationRes) -} - func (tp *transactionPerformer) performPayment(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { _, ok := transaction.(*proto.Payment) if !ok { @@ -180,13 +42,6 @@ func (tp *transactionPerformer) performPayment(transaction proto.Transaction, in return tp.generateSnapshotForPaymentTx(applicationRes) } -func (tp *transactionPerformer) generateSnapshotForTransferTx(applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { - return nil, nil - } - return tp.generateBalancesSnapshot(applicationRes) -} - func (tp *transactionPerformer) performTransfer(applicationRes *applicationResult) (TransactionSnapshot, error) { return tp.generateSnapshotForTransferTx(applicationRes) } @@ -207,71 +62,6 @@ func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Tran return tp.performTransfer(applicationRes) } -func (tp *transactionPerformer) generateSnapshotForIssueTx(assetID crypto.Digest, txID crypto.Digest, senderPK crypto.PublicKey, assetInfo assetInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { - return nil, nil - } - var snapshot TransactionSnapshot - - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) - if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") - } - // Remove the just issues snapshot from the diff, because it's not in the storage yet, so can't be processed with generateBalancesAtomicSnapshots - var specialAssetSnapshot *AssetBalanceSnapshot - for key, diffAmount := range addrAssetBalanceDiff { - if key.asset == proto.AssetIDFromDigest(assetID) { - // remove the element from the array - - delete(addrAssetBalanceDiff, key) - specialAssetSnapshot = &AssetBalanceSnapshot{ - Address: key.address, - AssetID: assetID, - Balance: uint64(diffAmount), - } - } - } - - issueStaticInfoSnapshot := &StaticAssetInfoSnapshot{ - AssetID: assetID, - IssuerPublicKey: senderPK, - SourceTransactionID: txID, - Decimals: assetInfo.decimals, - IsNFT: assetInfo.isNFT(), - } - - assetDescription := &AssetDescriptionSnapshot{ - AssetID: assetID, - AssetName: assetInfo.name, - AssetDescription: assetInfo.description, - ChangeHeight: assetInfo.lastNameDescChangeHeight, - } - - assetReissuability := &AssetVolumeSnapshot{ - AssetID: assetID, - IsReissuable: assetInfo.reissuable, - TotalQuantity: assetInfo.quantity, - } - snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) - - wavesBalancesSnapshot, assetBalancesSnapshot, err := tp.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) - if err != nil { - return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") - } - - for i := range wavesBalancesSnapshot { - snapshot = append(snapshot, &wavesBalancesSnapshot[i]) - } - for i := range assetBalancesSnapshot { - snapshot = append(snapshot, &assetBalancesSnapshot[i]) - } - if specialAssetSnapshot != nil { - snapshot = append(snapshot, specialAssetSnapshot) - } - - return snapshot, nil -} - func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest, assetID crypto.Digest, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { blockHeight := info.height + 1 // Create new asset. @@ -342,30 +132,6 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac return tp.performIssue(&tx.Issue, assetID, assetID, info, applicationRes) } -func (tp *transactionPerformer) generateSnapshotForReissueTx(assetID crypto.Digest, change assetReissueChange, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { - return nil, nil - } - quantityDiff := big.NewInt(change.diff) - assetInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) - if err != nil { - return nil, err - } - resQuantity := assetInfo.quantity.Add(&assetInfo.quantity, quantityDiff) - - snapshot, err := tp.generateBalancesSnapshot(applicationRes) - if err != nil { - return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") - } - assetReissuability := &AssetVolumeSnapshot{ - AssetID: assetID, - TotalQuantity: *resQuantity, - IsReissuable: change.reissuable, - } - snapshot = append(snapshot, assetReissuability) - return snapshot, nil -} - func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { // Modify asset. change := &assetReissueChange{ @@ -400,30 +166,6 @@ func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Trans return tp.performReissue(&tx.Reissue, info, applicationRes) } -func (tp *transactionPerformer) generateSnapshotForBurnTx(assetID crypto.Digest, change assetBurnChange, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { - return nil, nil - } - quantityDiff := big.NewInt(change.diff) - assetInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) - if err != nil { - return nil, err - } - resQuantity := assetInfo.quantity.Sub(&assetInfo.quantity, quantityDiff) - - snapshot, err := tp.generateBalancesSnapshot(applicationRes) - if err != nil { - return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") - } - assetReissuability := &AssetVolumeSnapshot{ - AssetID: assetID, - TotalQuantity: *resQuantity, - IsReissuable: assetInfo.reissuable, - } - snapshot = append(snapshot, assetReissuability) - return snapshot, nil -} - func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { // Modify asset. change := &assetBurnChange{ @@ -458,53 +200,6 @@ func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transact return tp.performBurn(&tx.Burn, info, applicationRes) } -func (tp *transactionPerformer) generateOrderAtomicSnapshot(orderID []byte, volume uint64, fee uint64) (*FilledVolumeFeeSnapshot, error) { - newestFilledAmount, newestFilledFee, err := tp.stor.ordersVolumes.newestFilled(orderID) - if err != nil { - return nil, err - } - orderIdDigset, err := crypto.NewDigestFromBytes(orderID) - if err != nil { - return nil, errors.Wrap(err, "failed to construct digest from order id bytes") - } - orderSnapshot := &FilledVolumeFeeSnapshot{ - OrderID: orderIdDigset, - FilledFee: newestFilledFee + fee, - FilledVolume: newestFilledAmount + volume, - } - return orderSnapshot, nil -} - -func (tp *transactionPerformer) generateSnapshotForExchangeTx(sellOrder proto.Order, sellFee uint64, buyOrder proto.Order, buyFee uint64, volume uint64, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { - return nil, nil - } - snapshot, err := tp.generateBalancesSnapshot(applicationRes) - if err != nil { - return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") - } - - sellOrderID, err := sellOrder.GetID() - if err != nil { - return nil, err - } - sellOrderAtomicSnapshot, err := tp.generateOrderAtomicSnapshot(sellOrderID, volume, sellFee) - if err != nil { - return nil, err - } - buyOrderID, err := buyOrder.GetID() - if err != nil { - return nil, err - } - buyOrderAtomicSnapshot, err := tp.generateOrderAtomicSnapshot(buyOrderID, volume, buyFee) - if err != nil { - return nil, err - } - - snapshot = append(snapshot, sellOrderAtomicSnapshot, buyOrderAtomicSnapshot) - return snapshot, nil -} - func (tp *transactionPerformer) increaseOrderVolume(order proto.Order, fee uint64, volume uint64, info *performerInfo) error { orderID, err := order.GetID() if err != nil { @@ -547,62 +242,6 @@ func (tp *transactionPerformer) performExchange(transaction proto.Transaction, i return snapshot, nil } -func (tp *transactionPerformer) generateLeaseAtomicSnapshots(leaseID crypto.Digest, l leasing, originalTxID crypto.Digest, - senderAddress proto.WavesAddress, receiverAddress proto.WavesAddress, amount int64) (*LeaseStateSnapshot, *LeaseBalanceSnapshot, *LeaseBalanceSnapshot, error) { - leaseStatusSnapshot := &LeaseStateSnapshot{ - LeaseID: leaseID, - Status: LeaseStateStatus{ - Value: l.Status, - }, - Amount: l.Amount, - Sender: l.Sender, - Recipient: l.Recipient, - OriginTransactionID: &originalTxID, - Height: l.Height, - } - - senderBalanceProfile, err := tp.stor.balances.newestWavesBalance(senderAddress.ID()) - if err != nil { - return nil, nil, nil, errors.Wrap(err, "failed to receive sender's waves balance") - } - senderLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ - Address: senderAddress, - LeaseIn: uint64(senderBalanceProfile.leaseIn), - LeaseOut: uint64(senderBalanceProfile.leaseOut + amount), - } - - receiverBalanceProfile, err := tp.stor.balances.newestWavesBalance(receiverAddress.ID()) - if err != nil { - return nil, nil, nil, errors.Wrap(err, "failed to receive recipient's waves balance") - } - recipientLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ - Address: receiverAddress, - LeaseIn: uint64(receiverBalanceProfile.leaseIn + amount), - LeaseOut: uint64(receiverBalanceProfile.leaseOut), - } - - return leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, nil -} - -func (tp *transactionPerformer) generateSnapshotForLeaseTx(lease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { - return nil, nil - } - var err error - snapshot, err := tp.generateBalancesSnapshot(applicationRes) - if err != nil { - return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") - } - amount := int64(lease.Amount) - leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseAtomicSnapshots(leaseID, lease, originalTxID, lease.Sender, lease.Recipient, amount) - if err != nil { - return nil, errors.Wrap(err, "failed to generate snapshots for a lease transaction") - } - - snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) - return snapshot, nil -} - func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { @@ -652,30 +291,6 @@ func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transac return tp.performLease(&tx.Lease, *tx.ID, info, applicationRes) } -func (tp *transactionPerformer) generateSnapshotForLeaseCancelTx(txID *crypto.Digest, oldLease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, cancelHeight uint64, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { - return nil, nil - } - var err error - snapshot, err := tp.generateBalancesSnapshot(applicationRes) - if err != nil { - return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") - } - negativeAmount := -int64(oldLease.Amount) - leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseAtomicSnapshots(leaseID, oldLease, originalTxID, oldLease.Sender, oldLease.Recipient, negativeAmount) - if err != nil { - return nil, errors.Wrap(err, "failed to generate snapshots for a lease transaction") - } - leaseStatusSnapshot.Status = LeaseStateStatus{ - Value: LeaseCanceled, - CancelHeight: cancelHeight, - CancelTransactionID: txID, - } - - snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) - return snapshot, nil -} - func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID *crypto.Digest, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { oldLease, err := tp.stor.leases.newestLeasingInfo(tx.LeaseID) if err != nil { @@ -714,21 +329,10 @@ func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info * return nil, err } - var snapshot TransactionSnapshot - if applicationRes != nil { - var err error - snapshot, err = tp.generateBalancesSnapshot(applicationRes) - if err != nil { - return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") - } - aliasSnapshot := &AliasSnapshot{ - Address: senderAddr, - Alias: tx.Alias, - } - snapshot = append(snapshot, aliasSnapshot) - + snapshot, err := tp.generateSnapshotForCreateAliasTx(senderAddr, tx.Alias, applicationRes) + if err != nil { + return nil, err } - if err := tp.stor.aliases.createAlias(tx.Alias.Alias, senderAddr, info.blockID); err != nil { return nil, err } @@ -751,13 +355,6 @@ func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.T return tp.performCreateAlias(&tx.CreateAlias, info, applicationRes) } -func (tp *transactionPerformer) generateSnapshotForMassTransferTx(applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { - return nil, nil - } - return tp.generateBalancesSnapshot(applicationRes) -} - func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { _, ok := transaction.(*proto.MassTransferWithProofs) if !ok { @@ -766,23 +363,8 @@ func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto. return tp.generateSnapshotForMassTransferTx(applicationRes) } -func (tp *transactionPerformer) generateSnapshotForDataTx(senderAddress proto.WavesAddress, entries []proto.DataEntry, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { - return nil, nil - } - snapshot, err := tp.generateBalancesSnapshot(applicationRes) - if err != nil { - return nil, err - } - dataEntriesSnapshot := &DataEntriesSnapshot{ - Address: senderAddress, - DataEntries: entries, - } - snapshot = append(snapshot, dataEntriesSnapshot) - return snapshot, nil -} - func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { + tx, ok := transaction.(*proto.DataWithProofs) if !ok { return nil, errors.New("failed to convert interface to DataWithProofs transaction") @@ -804,22 +386,6 @@ func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transact return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForSponsorshipTx(assetID crypto.Digest, minAssetFee uint64, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { - return nil, nil - } - snapshot, err := tp.generateBalancesSnapshot(applicationRes) - if err != nil { - return nil, err - } - sponsorshipSnapshot := &SponsorshipSnapshot{ - AssetID: assetID, - MinSponsoredFee: minAssetFee, - } - snapshot = append(snapshot, sponsorshipSnapshot) - return snapshot, nil -} - func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.SponsorshipWithProofs) if !ok { @@ -836,30 +402,6 @@ func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.T return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForSetScriptTx(senderAddress proto.WavesAddress, senderPK crypto.PublicKey, script proto.Script, estimatorVersion int, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { - return nil, nil - } - snapshot, err := tp.generateBalancesSnapshot(applicationRes) - if err != nil { - return nil, err - } - // the complexity was saved before when evaluated in checker - treeEstimation, err := tp.stor.scriptsComplexity.newestScriptComplexityByAddr(senderAddress, estimatorVersion) - if err != nil { - return nil, errors.Wrap(err, "failed to get verifier complexity from storage") - } - complexity := treeEstimation.Verifier - - sponsorshipSnapshot := &AccountScriptSnapshot{ - SenderPublicKey: senderPK, - Script: script, - VerifierComplexity: uint64(complexity), - } - snapshot = append(snapshot, sponsorshipSnapshot) - return snapshot, nil -} - func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.SetScriptWithProofs) if !ok { @@ -870,7 +412,7 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra return nil, err } - snapshot, err := tp.generateSnapshotForSetScriptTx(senderAddr, tx.SenderPK, tx.Script, info.checkerInfo.estimatorVersion(), applicationRes) + snapshot, err := tp.generateSnapshotForSetScriptTx(senderAddr, tx.SenderPK, tx.Script, info, applicationRes) if err != nil { return nil, err } @@ -880,30 +422,6 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { - return nil, nil - } - snapshot, err := tp.generateBalancesSnapshot(applicationRes) - if err != nil { - return nil, err - } - // the complexity was saved before when evaluated in checker - treeEstimation, err := tp.stor.scriptsComplexity.newestScriptComplexityByAsset(proto.AssetIDFromDigest(assetID)) - if err != nil { - return nil, errors.Wrap(err, "failed to get verifier complexity from storage") - } - complexity := treeEstimation.Verifier - - sponsorshipSnapshot := &AssetScriptSnapshot{ - AssetID: assetID, - Script: script, - Complexity: uint64(complexity), - } - snapshot = append(snapshot, sponsorshipSnapshot) - return snapshot, nil -} - func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.SetAssetScriptWithProofs) if !ok { @@ -985,228 +503,6 @@ func addSenderToAssetBalanceDiff(addrAssetBalanceDiff addressAssetBalanceDiff, } -// TODO optimize this -func (tp *transactionPerformer) generateInvokeSnapshot(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { - - blockHeight := info.height + 1 - - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) - if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") - } - var snapshot TransactionSnapshot - var dataEntries = make(map[proto.WavesAddress]proto.DataEntries) - if invocationRes != nil { - - for _, action := range invocationRes.actions { - - switch a := action.(type) { - case *proto.DataEntryScriptAction: - senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) - if err != nil { - return nil, err - } - // construct the map first and create the snapshot later for convenience - if _, ok := dataEntries[senderAddr]; ok { - entries := dataEntries[senderAddr] - entries = append(entries, a.Entry) - dataEntries[senderAddr] = entries - } else { - dataEntries[senderAddr] = proto.DataEntries{a.Entry} - } - - case *proto.AttachedPaymentScriptAction: - senderAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) - if err != nil { - return nil, errors.Wrap(err, "failed to get an address from a public key") - } - recipientAddress, err := recipientToAddress(a.Recipient, tp.stor.aliases) - if err != nil { - return nil, errors.Wrap(err, "failed to apply attached payment") - } - // No balance validation done below - if a.Asset.Present { // Update asset balance - addSenderRecipientToAssetBalanceDiff(addrAssetBalanceDiff, senderAddress, recipientAddress, proto.AssetIDFromDigest(a.Asset.ID), a.Amount) - } else { // Update Waves balance - addToWavesBalanceDiff(addrWavesBalanceDiff, senderAddress, recipientAddress, a.Amount) - } - case *proto.TransferScriptAction: - senderAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) - if err != nil { - return nil, errors.Wrap(err, "failed to get an address from a public key") - } - recipientAddress, err := recipientToAddress(a.Recipient, tp.stor.aliases) - if err != nil { - return nil, errors.Wrap(err, "failed to apply attached payment") - } - // No balance validation done below - if a.Asset.Present { // Update asset balance - addSenderRecipientToAssetBalanceDiff(addrAssetBalanceDiff, senderAddress, recipientAddress, proto.AssetIDFromDigest(a.Asset.ID), a.Amount) - } else { // Update Waves balance - addToWavesBalanceDiff(addrWavesBalanceDiff, senderAddress, recipientAddress, a.Amount) - } - case *proto.SponsorshipScriptAction: - sponsorshipSnapshot := &SponsorshipSnapshot{ - AssetID: a.AssetID, - MinSponsoredFee: uint64(a.MinFee), - } - snapshot = append(snapshot, sponsorshipSnapshot) - case *proto.IssueScriptAction: - assetInfo := assetInfo{ - assetConstInfo: assetConstInfo{ - tail: proto.DigestTail(a.ID), - issuer: *a.Sender, - decimals: uint8(a.Decimals), - issueHeight: blockHeight, - issueSequenceInBlock: info.stateActionsCounter.NextIssueActionNumber(), - }, - assetChangeableInfo: assetChangeableInfo{ - quantity: *big.NewInt(a.Quantity), - name: a.Name, - description: a.Description, - lastNameDescChangeHeight: blockHeight, - reissuable: a.Reissuable, - }, - } - issuerAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) - if err != nil { - return nil, errors.Wrap(err, "failed to get an address from a public key") - } - - issueStaticInfoSnapshot := &StaticAssetInfoSnapshot{ - AssetID: a.ID, - IssuerPublicKey: *a.Sender, - SourceTransactionID: txID, - Decimals: assetInfo.decimals, - IsNFT: assetInfo.isNFT(), - } - - assetDescription := &AssetDescriptionSnapshot{ - AssetID: a.ID, - AssetName: assetInfo.name, - AssetDescription: assetInfo.description, - ChangeHeight: assetInfo.lastNameDescChangeHeight, - } - - assetReissuability := &AssetVolumeSnapshot{ - AssetID: a.ID, - IsReissuable: assetInfo.reissuable, - TotalQuantity: assetInfo.quantity, - } - snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) - - addSenderToAssetBalanceDiff(addrAssetBalanceDiff, issuerAddress, proto.AssetIDFromDigest(a.ID), a.Quantity) - - case *proto.ReissueScriptAction: - - assetInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(a.AssetID)) - if err != nil { - return nil, err - } - quantityDiff := big.NewInt(a.Quantity) - resQuantity := assetInfo.quantity.Add(&assetInfo.quantity, quantityDiff) - assetReissuability := &AssetVolumeSnapshot{ - AssetID: a.AssetID, - TotalQuantity: *resQuantity, - IsReissuable: a.Reissuable, - } - - issueAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) - if err != nil { - return nil, errors.Wrap(err, "failed to get an address from a public key") - } - addSenderToAssetBalanceDiff(addrAssetBalanceDiff, issueAddress, proto.AssetIDFromDigest(a.AssetID), a.Quantity) - snapshot = append(snapshot, assetReissuability) - - case *proto.BurnScriptAction: - assetInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(a.AssetID)) - if err != nil { - return nil, err - } - quantityDiff := big.NewInt(a.Quantity) - resQuantity := assetInfo.quantity.Sub(&assetInfo.quantity, quantityDiff) - assetReissuability := &AssetVolumeSnapshot{ - AssetID: a.AssetID, - TotalQuantity: *resQuantity, - IsReissuable: assetInfo.reissuable, - } - - issueAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) - if err != nil { - return nil, errors.Wrap(err, "failed to get an address from a public key") - } - addSenderToAssetBalanceDiff(addrAssetBalanceDiff, issueAddress, proto.AssetIDFromDigest(a.AssetID), -a.Quantity) - snapshot = append(snapshot, assetReissuability) - case *proto.LeaseScriptAction: - senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) - if err != nil { - return nil, err - } - var recipientAddr proto.WavesAddress - if addr := a.Recipient.Address(); addr == nil { - recipientAddr, err = tp.stor.aliases.newestAddrByAlias(a.Recipient.Alias().Alias) - if err != nil { - return nil, errors.Errorf("invalid alias: %v\n", err) - } - } else { - recipientAddr = *addr - } - l := &leasing{ - Sender: senderAddr, - Recipient: recipientAddr, - Amount: uint64(a.Amount), - Height: info.height, - Status: LeaseActive, - } - var amount = int64(l.Amount) - leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseAtomicSnapshots(a.ID, *l, txID, senderAddr, recipientAddr, amount) - if err != nil { - return nil, errors.Wrap(err, "failed to generate snapshots for a lease action") - } - snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) - case *proto.LeaseCancelScriptAction: - l, err := tp.stor.leases.leasingInfo(a.LeaseID) - if err != nil { - return nil, errors.Wrap(err, "failed to receiver leasing info") - } - - var amount = -int64(l.Amount) - leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseAtomicSnapshots(a.LeaseID, *l, txID, l.Sender, l.Recipient, amount) - if err != nil { - return nil, errors.Wrap(err, "failed to generate snapshots for a lease cancel action") - } - snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) - default: - return nil, errors.Errorf("unknown script action type %T", a) - } - } - - for address, entries := range dataEntries { - dataEntrySnapshot := &DataEntriesSnapshot{Address: address, DataEntries: entries} - snapshot = append(snapshot, dataEntrySnapshot) - } - - } - - wavesBalancesSnapshot, assetBalancesSnapshot, err := tp.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) - if err != nil { - return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") - } - - for i := range wavesBalancesSnapshot { - snapshot = append(snapshot, &wavesBalancesSnapshot[i]) - } - for i := range assetBalancesSnapshot { - snapshot = append(snapshot, &assetBalancesSnapshot[i]) - } - - return snapshot, nil -} - -func (tp *transactionPerformer) generateSnapshotForInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { - return tp.generateInvokeSnapshot(txID, info, invocationRes, applicationRes) -} - func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { if _, ok := transaction.(*proto.InvokeScriptWithProofs); !ok { return nil, errors.New("failed to convert interface to InvokeScriptWithProofs transaction") @@ -1231,10 +527,6 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForInvokeExpressionTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { - return tp.generateInvokeSnapshot(txID, info, invocationRes, applicationRes) -} - func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { if _, ok := transaction.(*proto.InvokeExpressionTransactionWithProofs); !ok { return nil, errors.New("failed to convert interface to InvokeExpressionWithProofs transaction") @@ -1254,10 +546,6 @@ func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction pr return tp.generateSnapshotForInvokeExpressionTx(txID, info, invocationRes, applicationRes) } -func (tp *transactionPerformer) generateSnapshotForEthereumInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { - return tp.generateInvokeSnapshot(txID, info, invocationRes, applicationRes) -} - func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { ethTx, ok := transaction.(*proto.EthereumTransaction) if !ok { @@ -1285,24 +573,6 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForUpdateAssetInfoTx(assetID crypto.Digest, assetName string, assetDescription string, changeHeight proto.Height, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { - return nil, nil - } - snapshot, err := tp.generateBalancesSnapshot(applicationRes) - if err != nil { - return nil, err - } - sponsorshipSnapshot := &AssetDescriptionSnapshot{ - AssetID: assetID, - AssetName: assetName, - AssetDescription: assetDescription, - ChangeHeight: changeHeight, - } - snapshot = append(snapshot, sponsorshipSnapshot) - return snapshot, nil -} - func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.UpdateAssetInfoWithProofs) if !ok { diff --git a/pkg/state/transaction_performer_snapshots.go b/pkg/state/transaction_performer_snapshots.go new file mode 100644 index 000000000..c2a1383f3 --- /dev/null +++ b/pkg/state/transaction_performer_snapshots.go @@ -0,0 +1,745 @@ +package state + +import ( + "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/crypto" + "github.com/wavesplatform/gowaves/pkg/proto" + "math/big" +) + +type assetBalanceDiffKey struct { + address proto.WavesAddress + asset proto.AssetID +} + +type addressWavesBalanceDiff map[proto.WavesAddress]balanceDiff +type addressAssetBalanceDiff map[assetBalanceDiffKey]int64 + +func (tp *transactionPerformer) generateSnapshotForGenesisTx(applicationRes *applicationResult) (TransactionSnapshot, error) { + if applicationRes == nil { + return nil, nil + } + return tp.generateBalancesSnapshot(applicationRes) +} + +func (tp *transactionPerformer) generateSnapshotForPaymentTx(applicationRes *applicationResult) (TransactionSnapshot, error) { + if applicationRes == nil { + return nil, nil + } + return tp.generateBalancesSnapshot(applicationRes) +} + +func (tp *transactionPerformer) generateSnapshotForTransferTx(applicationRes *applicationResult) (TransactionSnapshot, error) { + if applicationRes == nil { + return nil, nil + } + return tp.generateBalancesSnapshot(applicationRes) +} + +func (tp *transactionPerformer) generateSnapshotForIssueTx(assetID crypto.Digest, txID crypto.Digest, senderPK crypto.PublicKey, assetInfo assetInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { + if applicationRes == nil { + return nil, nil + } + var snapshot TransactionSnapshot + + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + // Remove the just issues snapshot from the diff, because it's not in the storage yet, so can't be processed with generateBalancesAtomicSnapshots + var specialAssetSnapshot *AssetBalanceSnapshot + for key, diffAmount := range addrAssetBalanceDiff { + if key.asset == proto.AssetIDFromDigest(assetID) { + // remove the element from the array + + delete(addrAssetBalanceDiff, key) + specialAssetSnapshot = &AssetBalanceSnapshot{ + Address: key.address, + AssetID: assetID, + Balance: uint64(diffAmount), + } + } + } + + issueStaticInfoSnapshot := &StaticAssetInfoSnapshot{ + AssetID: assetID, + IssuerPublicKey: senderPK, + SourceTransactionID: txID, + Decimals: assetInfo.decimals, + IsNFT: assetInfo.isNFT(), + } + + assetDescription := &AssetDescriptionSnapshot{ + AssetID: assetID, + AssetName: assetInfo.name, + AssetDescription: assetInfo.description, + ChangeHeight: assetInfo.lastNameDescChangeHeight, + } + + assetReissuability := &AssetVolumeSnapshot{ + AssetID: assetID, + IsReissuable: assetInfo.reissuable, + TotalQuantity: assetInfo.quantity, + } + snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) + + wavesBalancesSnapshot, assetBalancesSnapshot, err := tp.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + + for i := range wavesBalancesSnapshot { + snapshot = append(snapshot, &wavesBalancesSnapshot[i]) + } + for i := range assetBalancesSnapshot { + snapshot = append(snapshot, &assetBalancesSnapshot[i]) + } + if specialAssetSnapshot != nil { + snapshot = append(snapshot, specialAssetSnapshot) + } + + return snapshot, nil +} + +func (tp *transactionPerformer) generateSnapshotForReissueTx(assetID crypto.Digest, change assetReissueChange, applicationRes *applicationResult) (TransactionSnapshot, error) { + if applicationRes == nil { + return nil, nil + } + quantityDiff := big.NewInt(change.diff) + assetInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) + if err != nil { + return nil, err + } + resQuantity := assetInfo.quantity.Add(&assetInfo.quantity, quantityDiff) + + snapshot, err := tp.generateBalancesSnapshot(applicationRes) + if err != nil { + return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") + } + assetReissuability := &AssetVolumeSnapshot{ + AssetID: assetID, + TotalQuantity: *resQuantity, + IsReissuable: change.reissuable, + } + snapshot = append(snapshot, assetReissuability) + return snapshot, nil +} + +func (tp *transactionPerformer) generateSnapshotForBurnTx(assetID crypto.Digest, change assetBurnChange, applicationRes *applicationResult) (TransactionSnapshot, error) { + if applicationRes == nil { + return nil, nil + } + quantityDiff := big.NewInt(change.diff) + assetInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) + if err != nil { + return nil, err + } + resQuantity := assetInfo.quantity.Sub(&assetInfo.quantity, quantityDiff) + + snapshot, err := tp.generateBalancesSnapshot(applicationRes) + if err != nil { + return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") + } + assetReissuability := &AssetVolumeSnapshot{ + AssetID: assetID, + TotalQuantity: *resQuantity, + IsReissuable: assetInfo.reissuable, + } + snapshot = append(snapshot, assetReissuability) + return snapshot, nil +} + +func (tp *transactionPerformer) generateSnapshotForExchangeTx(sellOrder proto.Order, sellFee uint64, buyOrder proto.Order, buyFee uint64, volume uint64, applicationRes *applicationResult) (TransactionSnapshot, error) { + if applicationRes == nil { + return nil, nil + } + snapshot, err := tp.generateBalancesSnapshot(applicationRes) + if err != nil { + return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") + } + + sellOrderID, err := sellOrder.GetID() + if err != nil { + return nil, err + } + sellOrderAtomicSnapshot, err := tp.generateOrderAtomicSnapshot(sellOrderID, volume, sellFee) + if err != nil { + return nil, err + } + buyOrderID, err := buyOrder.GetID() + if err != nil { + return nil, err + } + buyOrderAtomicSnapshot, err := tp.generateOrderAtomicSnapshot(buyOrderID, volume, buyFee) + if err != nil { + return nil, err + } + + snapshot = append(snapshot, sellOrderAtomicSnapshot, buyOrderAtomicSnapshot) + return snapshot, nil +} + +func (tp *transactionPerformer) generateSnapshotForLeaseTx(lease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, applicationRes *applicationResult) (TransactionSnapshot, error) { + if applicationRes == nil { + return nil, nil + } + var err error + snapshot, err := tp.generateBalancesSnapshot(applicationRes) + if err != nil { + return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") + } + amount := int64(lease.Amount) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseAtomicSnapshots(leaseID, lease, originalTxID, lease.Sender, lease.Recipient, amount) + if err != nil { + return nil, errors.Wrap(err, "failed to generate snapshots for a lease transaction") + } + + snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) + return snapshot, nil +} + +func (tp *transactionPerformer) generateSnapshotForLeaseCancelTx(txID *crypto.Digest, oldLease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, cancelHeight uint64, applicationRes *applicationResult) (TransactionSnapshot, error) { + if applicationRes == nil { + return nil, nil + } + var err error + snapshot, err := tp.generateBalancesSnapshot(applicationRes) + if err != nil { + return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") + } + negativeAmount := -int64(oldLease.Amount) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseAtomicSnapshots(leaseID, oldLease, originalTxID, oldLease.Sender, oldLease.Recipient, negativeAmount) + if err != nil { + return nil, errors.Wrap(err, "failed to generate snapshots for a lease transaction") + } + leaseStatusSnapshot.Status = LeaseStateStatus{ + Value: LeaseCanceled, + CancelHeight: cancelHeight, + CancelTransactionID: txID, + } + + snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) + return snapshot, nil +} + +func (tp *transactionPerformer) generateSnapshotForCreateAliasTx(senderAddress proto.WavesAddress, alias proto.Alias, applicationRes *applicationResult) (TransactionSnapshot, error) { + if applicationRes == nil { + return nil, nil + } + snapshot, err := tp.generateBalancesSnapshot(applicationRes) + if err != nil { + return nil, err + } + aliasSnapshot := &AliasSnapshot{ + Address: senderAddress, + Alias: alias, + } + snapshot = append(snapshot, aliasSnapshot) + return snapshot, nil +} + +func (tp *transactionPerformer) generateSnapshotForMassTransferTx(applicationRes *applicationResult) (TransactionSnapshot, error) { + if applicationRes == nil { + return nil, nil + } + return tp.generateBalancesSnapshot(applicationRes) +} + +func (tp *transactionPerformer) generateSnapshotForDataTx(senderAddress proto.WavesAddress, entries []proto.DataEntry, applicationRes *applicationResult) (TransactionSnapshot, error) { + if applicationRes == nil { + return nil, nil + } + snapshot, err := tp.generateBalancesSnapshot(applicationRes) + if err != nil { + return nil, err + } + dataEntriesSnapshot := &DataEntriesSnapshot{ + Address: senderAddress, + DataEntries: entries, + } + snapshot = append(snapshot, dataEntriesSnapshot) + return snapshot, nil +} + +func (tp *transactionPerformer) generateSnapshotForSponsorshipTx(assetID crypto.Digest, minAssetFee uint64, applicationRes *applicationResult) (TransactionSnapshot, error) { + if applicationRes == nil { + return nil, nil + } + snapshot, err := tp.generateBalancesSnapshot(applicationRes) + if err != nil { + return nil, err + } + sponsorshipSnapshot := &SponsorshipSnapshot{ + AssetID: assetID, + MinSponsoredFee: minAssetFee, + } + snapshot = append(snapshot, sponsorshipSnapshot) + return snapshot, nil +} + +func (tp *transactionPerformer) generateSnapshotForSetScriptTx(senderAddress proto.WavesAddress, senderPK crypto.PublicKey, script proto.Script, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { + if applicationRes == nil { + return nil, nil + } + snapshot, err := tp.generateBalancesSnapshot(applicationRes) + if err != nil { + return nil, err + } + estimatorVersion := info.checkerInfo.estimatorVersion() + // the complexity was saved before when evaluated in checker + treeEstimation, err := tp.stor.scriptsComplexity.newestScriptComplexityByAddr(senderAddress, estimatorVersion) + if err != nil { + return nil, errors.Wrap(err, "failed to get verifier complexity from storage") + } + complexity := treeEstimation.Verifier + + sponsorshipSnapshot := &AccountScriptSnapshot{ + SenderPublicKey: senderPK, + Script: script, + VerifierComplexity: uint64(complexity), + } + snapshot = append(snapshot, sponsorshipSnapshot) + return snapshot, nil +} + +func (tp *transactionPerformer) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, applicationRes *applicationResult) (TransactionSnapshot, error) { + if applicationRes == nil { + return nil, nil + } + snapshot, err := tp.generateBalancesSnapshot(applicationRes) + if err != nil { + return nil, err + } + // the complexity was saved before when evaluated in checker + treeEstimation, err := tp.stor.scriptsComplexity.newestScriptComplexityByAsset(proto.AssetIDFromDigest(assetID)) + if err != nil { + return nil, errors.Wrap(err, "failed to get verifier complexity from storage") + } + complexity := treeEstimation.Verifier + + sponsorshipSnapshot := &AssetScriptSnapshot{ + AssetID: assetID, + Script: script, + Complexity: uint64(complexity), + } + snapshot = append(snapshot, sponsorshipSnapshot) + return snapshot, nil +} + +func (tp *transactionPerformer) generateSnapshotForInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { + return tp.generateInvokeSnapshot(txID, info, invocationRes, applicationRes) +} + +func (tp *transactionPerformer) generateSnapshotForInvokeExpressionTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { + return tp.generateInvokeSnapshot(txID, info, invocationRes, applicationRes) +} + +func (tp *transactionPerformer) generateSnapshotForEthereumInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { + return tp.generateInvokeSnapshot(txID, info, invocationRes, applicationRes) +} + +func (tp *transactionPerformer) generateSnapshotForUpdateAssetInfoTx(assetID crypto.Digest, assetName string, assetDescription string, changeHeight proto.Height, applicationRes *applicationResult) (TransactionSnapshot, error) { + if applicationRes == nil { + return nil, nil + } + snapshot, err := tp.generateBalancesSnapshot(applicationRes) + if err != nil { + return nil, err + } + sponsorshipSnapshot := &AssetDescriptionSnapshot{ + AssetID: assetID, + AssetName: assetName, + AssetDescription: assetDescription, + ChangeHeight: changeHeight, + } + snapshot = append(snapshot, sponsorshipSnapshot) + return snapshot, nil +} + +// TODO optimize this +func (tp *transactionPerformer) generateInvokeSnapshot(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { + + blockHeight := info.height + 1 + + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + var snapshot TransactionSnapshot + var dataEntries = make(map[proto.WavesAddress]proto.DataEntries) + if invocationRes != nil { + + for _, action := range invocationRes.actions { + + switch a := action.(type) { + case *proto.DataEntryScriptAction: + senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + if err != nil { + return nil, err + } + // construct the map first and create the snapshot later for convenience + if _, ok := dataEntries[senderAddr]; ok { + entries := dataEntries[senderAddr] + entries = append(entries, a.Entry) + dataEntries[senderAddr] = entries + } else { + dataEntries[senderAddr] = proto.DataEntries{a.Entry} + } + + case *proto.AttachedPaymentScriptAction: + senderAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + if err != nil { + return nil, errors.Wrap(err, "failed to get an address from a public key") + } + recipientAddress, err := recipientToAddress(a.Recipient, tp.stor.aliases) + if err != nil { + return nil, errors.Wrap(err, "failed to apply attached payment") + } + // No balance validation done below + if a.Asset.Present { // Update asset balance + addSenderRecipientToAssetBalanceDiff(addrAssetBalanceDiff, senderAddress, recipientAddress, proto.AssetIDFromDigest(a.Asset.ID), a.Amount) + } else { // Update Waves balance + addToWavesBalanceDiff(addrWavesBalanceDiff, senderAddress, recipientAddress, a.Amount) + } + case *proto.TransferScriptAction: + senderAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + if err != nil { + return nil, errors.Wrap(err, "failed to get an address from a public key") + } + recipientAddress, err := recipientToAddress(a.Recipient, tp.stor.aliases) + if err != nil { + return nil, errors.Wrap(err, "failed to apply attached payment") + } + // No balance validation done below + if a.Asset.Present { // Update asset balance + addSenderRecipientToAssetBalanceDiff(addrAssetBalanceDiff, senderAddress, recipientAddress, proto.AssetIDFromDigest(a.Asset.ID), a.Amount) + } else { // Update Waves balance + addToWavesBalanceDiff(addrWavesBalanceDiff, senderAddress, recipientAddress, a.Amount) + } + case *proto.SponsorshipScriptAction: + sponsorshipSnapshot := &SponsorshipSnapshot{ + AssetID: a.AssetID, + MinSponsoredFee: uint64(a.MinFee), + } + snapshot = append(snapshot, sponsorshipSnapshot) + case *proto.IssueScriptAction: + assetInfo := assetInfo{ + assetConstInfo: assetConstInfo{ + tail: proto.DigestTail(a.ID), + issuer: *a.Sender, + decimals: uint8(a.Decimals), + issueHeight: blockHeight, + issueSequenceInBlock: info.stateActionsCounter.NextIssueActionNumber(), + }, + assetChangeableInfo: assetChangeableInfo{ + quantity: *big.NewInt(a.Quantity), + name: a.Name, + description: a.Description, + lastNameDescChangeHeight: blockHeight, + reissuable: a.Reissuable, + }, + } + issuerAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + if err != nil { + return nil, errors.Wrap(err, "failed to get an address from a public key") + } + + issueStaticInfoSnapshot := &StaticAssetInfoSnapshot{ + AssetID: a.ID, + IssuerPublicKey: *a.Sender, + SourceTransactionID: txID, + Decimals: assetInfo.decimals, + IsNFT: assetInfo.isNFT(), + } + + assetDescription := &AssetDescriptionSnapshot{ + AssetID: a.ID, + AssetName: assetInfo.name, + AssetDescription: assetInfo.description, + ChangeHeight: assetInfo.lastNameDescChangeHeight, + } + + assetReissuability := &AssetVolumeSnapshot{ + AssetID: a.ID, + IsReissuable: assetInfo.reissuable, + TotalQuantity: assetInfo.quantity, + } + snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) + + addSenderToAssetBalanceDiff(addrAssetBalanceDiff, issuerAddress, proto.AssetIDFromDigest(a.ID), a.Quantity) + + case *proto.ReissueScriptAction: + + assetInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(a.AssetID)) + if err != nil { + return nil, err + } + quantityDiff := big.NewInt(a.Quantity) + resQuantity := assetInfo.quantity.Add(&assetInfo.quantity, quantityDiff) + assetReissuability := &AssetVolumeSnapshot{ + AssetID: a.AssetID, + TotalQuantity: *resQuantity, + IsReissuable: a.Reissuable, + } + + issueAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + if err != nil { + return nil, errors.Wrap(err, "failed to get an address from a public key") + } + addSenderToAssetBalanceDiff(addrAssetBalanceDiff, issueAddress, proto.AssetIDFromDigest(a.AssetID), a.Quantity) + snapshot = append(snapshot, assetReissuability) + + case *proto.BurnScriptAction: + assetInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(a.AssetID)) + if err != nil { + return nil, err + } + quantityDiff := big.NewInt(a.Quantity) + resQuantity := assetInfo.quantity.Sub(&assetInfo.quantity, quantityDiff) + assetReissuability := &AssetVolumeSnapshot{ + AssetID: a.AssetID, + TotalQuantity: *resQuantity, + IsReissuable: assetInfo.reissuable, + } + + issueAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + if err != nil { + return nil, errors.Wrap(err, "failed to get an address from a public key") + } + addSenderToAssetBalanceDiff(addrAssetBalanceDiff, issueAddress, proto.AssetIDFromDigest(a.AssetID), -a.Quantity) + snapshot = append(snapshot, assetReissuability) + case *proto.LeaseScriptAction: + senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + if err != nil { + return nil, err + } + var recipientAddr proto.WavesAddress + if addr := a.Recipient.Address(); addr == nil { + recipientAddr, err = tp.stor.aliases.newestAddrByAlias(a.Recipient.Alias().Alias) + if err != nil { + return nil, errors.Errorf("invalid alias: %v\n", err) + } + } else { + recipientAddr = *addr + } + l := &leasing{ + Sender: senderAddr, + Recipient: recipientAddr, + Amount: uint64(a.Amount), + Height: info.height, + Status: LeaseActive, + } + var amount = int64(l.Amount) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseAtomicSnapshots(a.ID, *l, txID, senderAddr, recipientAddr, amount) + if err != nil { + return nil, errors.Wrap(err, "failed to generate snapshots for a lease action") + } + snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) + case *proto.LeaseCancelScriptAction: + l, err := tp.stor.leases.leasingInfo(a.LeaseID) + if err != nil { + return nil, errors.Wrap(err, "failed to receiver leasing info") + } + + var amount = -int64(l.Amount) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseAtomicSnapshots(a.LeaseID, *l, txID, l.Sender, l.Recipient, amount) + if err != nil { + return nil, errors.Wrap(err, "failed to generate snapshots for a lease cancel action") + } + snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) + default: + return nil, errors.Errorf("unknown script action type %T", a) + } + } + + for address, entries := range dataEntries { + dataEntrySnapshot := &DataEntriesSnapshot{Address: address, DataEntries: entries} + snapshot = append(snapshot, dataEntrySnapshot) + } + + } + + wavesBalancesSnapshot, assetBalancesSnapshot, err := tp.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + + for i := range wavesBalancesSnapshot { + snapshot = append(snapshot, &wavesBalancesSnapshot[i]) + } + for i := range assetBalancesSnapshot { + snapshot = append(snapshot, &assetBalancesSnapshot[i]) + } + + return snapshot, nil +} + +func (tp *transactionPerformer) generateLeaseAtomicSnapshots(leaseID crypto.Digest, l leasing, originalTxID crypto.Digest, + senderAddress proto.WavesAddress, receiverAddress proto.WavesAddress, amount int64) (*LeaseStateSnapshot, *LeaseBalanceSnapshot, *LeaseBalanceSnapshot, error) { + leaseStatusSnapshot := &LeaseStateSnapshot{ + LeaseID: leaseID, + Status: LeaseStateStatus{ + Value: l.Status, + }, + Amount: l.Amount, + Sender: l.Sender, + Recipient: l.Recipient, + OriginTransactionID: &originalTxID, + Height: l.Height, + } + + senderBalanceProfile, err := tp.stor.balances.newestWavesBalance(senderAddress.ID()) + if err != nil { + return nil, nil, nil, errors.Wrap(err, "failed to receive sender's waves balance") + } + senderLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ + Address: senderAddress, + LeaseIn: uint64(senderBalanceProfile.leaseIn), + LeaseOut: uint64(senderBalanceProfile.leaseOut + amount), + } + + receiverBalanceProfile, err := tp.stor.balances.newestWavesBalance(receiverAddress.ID()) + if err != nil { + return nil, nil, nil, errors.Wrap(err, "failed to receive recipient's waves balance") + } + recipientLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ + Address: receiverAddress, + LeaseIn: uint64(receiverBalanceProfile.leaseIn + amount), + LeaseOut: uint64(receiverBalanceProfile.leaseOut), + } + + return leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, nil +} + +func (tp *transactionPerformer) generateOrderAtomicSnapshot(orderID []byte, volume uint64, fee uint64) (*FilledVolumeFeeSnapshot, error) { + newestFilledAmount, newestFilledFee, err := tp.stor.ordersVolumes.newestFilled(orderID) + if err != nil { + return nil, err + } + orderIdDigset, err := crypto.NewDigestFromBytes(orderID) + if err != nil { + return nil, errors.Wrap(err, "failed to construct digest from order id bytes") + } + orderSnapshot := &FilledVolumeFeeSnapshot{ + OrderID: orderIdDigset, + FilledFee: newestFilledFee + fee, + FilledVolume: newestFilledAmount + volume, + } + return orderSnapshot, nil +} + +func (tp *transactionPerformer) generateBalancesSnapshot(applicationRes *applicationResult) (TransactionSnapshot, error) { + var transactionSnapshot TransactionSnapshot + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + } + wavesBalancesSnapshot, assetBalancesSnapshot, err := tp.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) + if err != nil { + return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + } + for i := range wavesBalancesSnapshot { + transactionSnapshot = append(transactionSnapshot, &wavesBalancesSnapshot[i]) + } + for i := range assetBalancesSnapshot { + transactionSnapshot = append(transactionSnapshot, &assetBalancesSnapshot[i]) + } + return transactionSnapshot, nil +} + +func (tp *transactionPerformer) generateBalancesAtomicSnapshots(addrWavesBalanceDiff addressWavesBalanceDiff, addrAssetBalanceDiff addressAssetBalanceDiff) ([]WavesBalanceSnapshot, []AssetBalanceSnapshot, error) { + wavesBalanceSnapshot, err := tp.constructWavesBalanceSnapshotFromDiff(addrWavesBalanceDiff) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to construct waves balance snapshot") + } + if len(addrAssetBalanceDiff) == 0 { + return wavesBalanceSnapshot, nil, nil + } + + assetBalanceSnapshot, err := tp.constructAssetBalanceSnapshotFromDiff(addrAssetBalanceDiff) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to construct asset balance snapshot") + } + return wavesBalanceSnapshot, assetBalanceSnapshot, nil +} + +func addressBalanceDiffFromTxDiff(diff txDiff, scheme proto.Scheme) (addressWavesBalanceDiff, addressAssetBalanceDiff, error) { + addrWavesBalanceDiff := make(addressWavesBalanceDiff) + addrAssetBalanceDiff := make(addressAssetBalanceDiff) + for balanceKeyString, diffAmount := range diff { + + // construct address from key + wavesBalanceKey := &wavesBalanceKey{} + err := wavesBalanceKey.unmarshal([]byte(balanceKeyString)) + if err != nil { + assetBalanceKey := &assetBalanceKey{} + err := assetBalanceKey.unmarshal([]byte(balanceKeyString)) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to convert balance key to asset balance key") + } + asset := assetBalanceKey.asset + address, err := assetBalanceKey.address.ToWavesAddress(scheme) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to convert address id to waves address") + } + assetBalKey := assetBalanceDiffKey{address: address, asset: asset} + addrAssetBalanceDiff[assetBalKey] = diffAmount.balance + continue + } + address, err := wavesBalanceKey.address.ToWavesAddress(scheme) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to convert address id to waves address") + } + // if the waves balance diff is 0, it means it did not change. Though the record might occur when LeaseIn and LeaseOut change, + // but they are handled separately in snapshots + if diffAmount.balance == 0 { + continue + } + addrWavesBalanceDiff[address] = diffAmount + } + return addrWavesBalanceDiff, addrAssetBalanceDiff, nil +} + +// from txDiff and fees. no validation needed at this point +func (tp *transactionPerformer) constructWavesBalanceSnapshotFromDiff(diff addressWavesBalanceDiff) ([]WavesBalanceSnapshot, error) { + var wavesBalances []WavesBalanceSnapshot + // add miner address to the diff + + for wavesAddress, diffAmount := range diff { + + fullBalance, err := tp.stor.balances.newestWavesBalance(wavesAddress.ID()) + if err != nil { + return nil, errors.Wrap(err, "failed to receive sender's waves balance") + } + newBalance := WavesBalanceSnapshot{ + Address: wavesAddress, + Balance: uint64(int64(fullBalance.balance) + diffAmount.balance), + } + wavesBalances = append(wavesBalances, newBalance) + } + return wavesBalances, nil +} + +func (tp *transactionPerformer) constructAssetBalanceSnapshotFromDiff(diff addressAssetBalanceDiff) ([]AssetBalanceSnapshot, error) { + var assetBalances []AssetBalanceSnapshot + // add miner address to the diff + + for key, diffAmount := range diff { + balance, err := tp.stor.balances.newestAssetBalance(key.address.ID(), key.asset) + if err != nil { + return nil, errors.Wrap(err, "failed to receive sender's waves balance") + } + assetInfo, err := tp.stor.assets.newestAssetInfo(key.asset) + if err != nil { + return nil, errors.Wrap(err, "failed to get newest asset info") + } + + newBalance := AssetBalanceSnapshot{ + Address: key.address, + AssetID: key.asset.Digest(assetInfo.tail), + Balance: uint64(int64(balance) + diffAmount), + } + assetBalances = append(assetBalances, newBalance) + } + return assetBalances, nil +}