From 4c1cea880f445e214cc28559c8b322973d68cb08 Mon Sep 17 00:00:00 2001 From: esuwu Date: Thu, 6 Apr 2023 03:35:47 -0500 Subject: [PATCH 001/139] Added types --- pkg/state/snapshots.go | 143 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 pkg/state/snapshots.go diff --git a/pkg/state/snapshots.go b/pkg/state/snapshots.go new file mode 100644 index 000000000..89e9e6ef2 --- /dev/null +++ b/pkg/state/snapshots.go @@ -0,0 +1,143 @@ +package state + +import "github.com/wavesplatform/gowaves/pkg/proto" + +type TransactionSnapshot []AtomicSnapshot + +type AtomicSnapshot interface { + dummy() error +} + +type WavesBalanceSnapshot struct { + address *proto.Address + balance uint64 +} + +func (s *WavesBalanceSnapshot) dummy() error { + return nil +} + +type AssetBalancesSnapshot struct { + address *proto.Address + assetBalance map[proto.AssetID]uint64 +} + +func (s *AssetBalancesSnapshot) dummy() error { + return nil +} + +type DataEntriesSnapshot struct { + address *proto.Address + dataEntries []proto.DataEntry +} + +func (s *DataEntriesSnapshot) dummy() error { + return nil +} + +type AccountScriptSnapshot struct { + address *proto.Address + script *proto.Script +} + +func (s *AccountScriptSnapshot) dummy() error { + return nil +} + +type AssetScriptSnapshot struct { + assetID *proto.AssetID + script *proto.Script +} + +func (s *AssetScriptSnapshot) dummy() error { + return nil +} + +type LeaseBalanceSnapshot struct { + address *proto.Address + leaseIn uint64 + leaseOut uint64 +} + +func (s *LeaseBalanceSnapshot) dummy() error { + return nil +} + +type LeaseStatusSnapshot struct { + leaseID uint64 + isActive bool +} + +func (s *LeaseStatusSnapshot) dummy() error { + return nil +} + +type SponsorshipSnapshot struct { + assetID *proto.AssetID + minSponsoredFee uint64 +} + +func (s *SponsorshipSnapshot) dummy() error { + return nil +} + +type AliasSnapshot struct { + alias *proto.Alias + address *proto.Address +} + +func (s *AliasSnapshot) dummy() error { + return nil +} + +// FilledVolumeFee Filled Volume and Fee +type FilledVolumeFeeSnapshot struct { + orderID uint64 + filledVolume uint64 + filledFee uint64 +} + +func (s *FilledVolumeFeeSnapshot) dummy() error { + return nil +} + +type StaticAssetInfoSnapshot struct { + assetID *proto.AssetID + issuer *proto.WavesAddress + isNFT bool +} + +func (s *StaticAssetInfoSnapshot) dummy() error { + return nil +} + +type AssetReissuabilitySnapshot struct { + assetID *proto.AssetID + isReissuable bool +} + +func (s *AssetReissuabilitySnapshot) dummy() error { + return nil +} + +type AssetDescriptionSnapshot struct { + assetID *proto.AssetID + assetName *string + assetDescription string + changeHeight uint64 +} + +func (s *AssetDescriptionSnapshot) dummy() error { + return nil +} + +type SnapshotManager struct { + diffStor *diffStorage + atx *addressTransactions + stor *blockchainEntitiesStorage +} + +func (SnapshotManager) TxSnapshotFromTx(tx *proto.Transaction) TransactionSnapshot { + var snapshots []AtomicSnapshot + return snapshots +} From ced7bb32217be2c0a103a4189dcf250594989800 Mon Sep 17 00:00:00 2001 From: esuwu Date: Thu, 6 Apr 2023 03:37:41 -0500 Subject: [PATCH 002/139] Renamed a file --- pkg/state/{snapshots.go => snapshot_types.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pkg/state/{snapshots.go => snapshot_types.go} (100%) diff --git a/pkg/state/snapshots.go b/pkg/state/snapshot_types.go similarity index 100% rename from pkg/state/snapshots.go rename to pkg/state/snapshot_types.go From 5aebec495389bf695f058e0159c961d851a8a152 Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 17 Apr 2023 18:11:11 -0500 Subject: [PATCH 003/139] Changed asset- and waves balances structures --- pkg/state/snapshot_types.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 89e9e6ef2..682442c73 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -8,20 +8,29 @@ type AtomicSnapshot interface { dummy() error } -type WavesBalanceSnapshot struct { +type balanceWaves struct { address *proto.Address balance uint64 } -func (s *WavesBalanceSnapshot) dummy() error { +type WavesBalancesSnapshot struct { + wavesBalances []balanceWaves +} + +func (s *WavesBalancesSnapshot) dummy() error { return nil } -type AssetBalancesSnapshot struct { +// What is address || asset_id? +type balanceAsset struct { address *proto.Address assetBalance map[proto.AssetID]uint64 } +type AssetBalancesSnapshot struct { + assetBalances []balanceAsset +} + func (s *AssetBalancesSnapshot) dummy() error { return nil } From de88b10cdcee5cde7c9a0328572ff1677c04c91c Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 17 Apr 2023 18:19:10 -0500 Subject: [PATCH 004/139] Commented a function --- pkg/state/snapshot_types.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 682442c73..da8940dd4 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -146,7 +146,7 @@ type SnapshotManager struct { stor *blockchainEntitiesStorage } -func (SnapshotManager) TxSnapshotFromTx(tx *proto.Transaction) TransactionSnapshot { - var snapshots []AtomicSnapshot - return snapshots -} +//func (SnapshotManager) TxSnapshotFromTx(tx *proto.Transaction) TransactionSnapshot { +// var snapshots []AtomicSnapshot +// return snapshots +//} From 3ab9ba453d1627a7ba5990d8ade70ecb72223ef1 Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 17 Apr 2023 21:41:50 -0500 Subject: [PATCH 005/139] Changed addresses types --- pkg/state/snapshot_types.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index da8940dd4..0b93ad461 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -9,7 +9,7 @@ type AtomicSnapshot interface { } type balanceWaves struct { - address *proto.Address + address proto.Address balance uint64 } @@ -23,7 +23,7 @@ func (s *WavesBalancesSnapshot) dummy() error { // What is address || asset_id? type balanceAsset struct { - address *proto.Address + address proto.Address assetBalance map[proto.AssetID]uint64 } @@ -36,7 +36,7 @@ func (s *AssetBalancesSnapshot) dummy() error { } type DataEntriesSnapshot struct { - address *proto.Address + address proto.Address dataEntries []proto.DataEntry } @@ -45,8 +45,8 @@ func (s *DataEntriesSnapshot) dummy() error { } type AccountScriptSnapshot struct { - address *proto.Address - script *proto.Script + address proto.Address + script proto.Script } func (s *AccountScriptSnapshot) dummy() error { @@ -54,8 +54,8 @@ func (s *AccountScriptSnapshot) dummy() error { } type AssetScriptSnapshot struct { - assetID *proto.AssetID - script *proto.Script + assetID proto.AssetID + script proto.Script } func (s *AssetScriptSnapshot) dummy() error { @@ -63,7 +63,7 @@ func (s *AssetScriptSnapshot) dummy() error { } type LeaseBalanceSnapshot struct { - address *proto.Address + address proto.Address leaseIn uint64 leaseOut uint64 } @@ -82,7 +82,7 @@ func (s *LeaseStatusSnapshot) dummy() error { } type SponsorshipSnapshot struct { - assetID *proto.AssetID + assetID proto.AssetID minSponsoredFee uint64 } @@ -111,8 +111,8 @@ func (s *FilledVolumeFeeSnapshot) dummy() error { } type StaticAssetInfoSnapshot struct { - assetID *proto.AssetID - issuer *proto.WavesAddress + assetID proto.AssetID + issuer proto.Address isNFT bool } @@ -121,7 +121,7 @@ func (s *StaticAssetInfoSnapshot) dummy() error { } type AssetReissuabilitySnapshot struct { - assetID *proto.AssetID + assetID proto.AssetID isReissuable bool } @@ -130,7 +130,7 @@ func (s *AssetReissuabilitySnapshot) dummy() error { } type AssetDescriptionSnapshot struct { - assetID *proto.AssetID + assetID proto.AssetID assetName *string assetDescription string changeHeight uint64 From cd6b4a2bf51dd5a9fea368e580d00e53c94aa7d7 Mon Sep 17 00:00:00 2001 From: esuwu Date: Tue, 18 Apr 2023 00:23:48 -0500 Subject: [PATCH 006/139] Changed balanceAsset --- pkg/state/snapshot_types.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 0b93ad461..acc63cd6f 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -23,8 +23,9 @@ func (s *WavesBalancesSnapshot) dummy() error { // What is address || asset_id? type balanceAsset struct { - address proto.Address - assetBalance map[proto.AssetID]uint64 + address proto.Address + assetID proto.AssetID + balance uint64 } type AssetBalancesSnapshot struct { From 26c3c616ae8d558992dbb7aaf6a3c13229e55d5c Mon Sep 17 00:00:00 2001 From: esuwu Date: Tue, 18 Apr 2023 23:19:30 -0500 Subject: [PATCH 007/139] Added a constructor --- pkg/state/snapshot_types.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index acc63cd6f..2a452797f 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -142,12 +142,10 @@ func (s *AssetDescriptionSnapshot) dummy() error { } type SnapshotManager struct { - diffStor *diffStorage - atx *addressTransactions - stor *blockchainEntitiesStorage + stor *blockchainEntitiesStorage + scheme proto.Scheme } -//func (SnapshotManager) TxSnapshotFromTx(tx *proto.Transaction) TransactionSnapshot { -// var snapshots []AtomicSnapshot -// return snapshots -//} +func NewSnapshotManager(stor *blockchainEntitiesStorage) *SnapshotManager { + return &SnapshotManager{stor: stor} +} From fba465fae1e308831120a3024684bf0ec08285e9 Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 24 Apr 2023 18:11:19 -0500 Subject: [PATCH 008/139] Added decimals to asset snapshot --- pkg/state/snapshot_types.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 2a452797f..f1aad4c80 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -112,9 +112,10 @@ func (s *FilledVolumeFeeSnapshot) dummy() error { } type StaticAssetInfoSnapshot struct { - assetID proto.AssetID - issuer proto.Address - isNFT bool + assetID proto.AssetID + issuer proto.Address + decimals uint8 + isNFT bool } func (s *StaticAssetInfoSnapshot) dummy() error { @@ -132,7 +133,7 @@ func (s *AssetReissuabilitySnapshot) dummy() error { type AssetDescriptionSnapshot struct { assetID proto.AssetID - assetName *string + assetName string assetDescription string changeHeight uint64 } From ce406664f3dc9b4a7a18f2723c9132db363154e1 Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 24 Apr 2023 18:13:04 -0500 Subject: [PATCH 009/139] Changed uint8 to int8 --- pkg/state/snapshot_types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index f1aad4c80..816b97db8 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -114,7 +114,7 @@ func (s *FilledVolumeFeeSnapshot) dummy() error { type StaticAssetInfoSnapshot struct { assetID proto.AssetID issuer proto.Address - decimals uint8 + decimals int8 isNFT bool } From 60b6bd2a8ca85fb547275660611350944918a311 Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 24 Apr 2023 18:28:49 -0500 Subject: [PATCH 010/139] Added a field for asset reissuability --- pkg/state/snapshot_types.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 816b97db8..7f268bb98 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -123,8 +123,9 @@ func (s *StaticAssetInfoSnapshot) dummy() error { } type AssetReissuabilitySnapshot struct { - assetID proto.AssetID - isReissuable bool + assetID proto.AssetID + totalQuantity uint64 + isReissuable bool } func (s *AssetReissuabilitySnapshot) dummy() error { From e449c64c3222457f13652177f555d692176a39b9 Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 24 Apr 2023 18:33:08 -0500 Subject: [PATCH 011/139] Changed the type of total quantity --- pkg/state/snapshot_types.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 7f268bb98..1ea5c183f 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -1,6 +1,10 @@ package state -import "github.com/wavesplatform/gowaves/pkg/proto" +import ( + "math/big" + + "github.com/wavesplatform/gowaves/pkg/proto" +) type TransactionSnapshot []AtomicSnapshot @@ -124,7 +128,7 @@ func (s *StaticAssetInfoSnapshot) dummy() error { type AssetReissuabilitySnapshot struct { assetID proto.AssetID - totalQuantity uint64 + totalQuantity *big.Int isReissuable bool } From 178e7ab7e7374647336747e947f87b124d00ff31 Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 24 Apr 2023 18:34:03 -0500 Subject: [PATCH 012/139] removed the pointer --- pkg/state/snapshot_types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 1ea5c183f..6062ad4e2 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -128,7 +128,7 @@ func (s *StaticAssetInfoSnapshot) dummy() error { type AssetReissuabilitySnapshot struct { assetID proto.AssetID - totalQuantity *big.Int + totalQuantity big.Int isReissuable bool } From 53ff541eea133ae4ba294bb911ce48d48bcf55c3 Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 24 Apr 2023 20:14:36 -0500 Subject: [PATCH 013/139] Changed the type of orderID --- pkg/state/snapshot_types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 6062ad4e2..6c4296bdc 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -106,7 +106,7 @@ func (s *AliasSnapshot) dummy() error { // FilledVolumeFee Filled Volume and Fee type FilledVolumeFeeSnapshot struct { - orderID uint64 + orderID []byte filledVolume uint64 filledFee uint64 } From 95f7a491da52252cc9ee9af6c05ec655b66c8266 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Tue, 25 Apr 2023 21:49:18 +0300 Subject: [PATCH 014/139] Make 'SnapshotManager' as an interface type. --- pkg/state/snapshot_types.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 6c4296bdc..fa403f2a9 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -147,11 +147,6 @@ func (s *AssetDescriptionSnapshot) dummy() error { return nil } -type SnapshotManager struct { - stor *blockchainEntitiesStorage - scheme proto.Scheme -} - -func NewSnapshotManager(stor *blockchainEntitiesStorage) *SnapshotManager { - return &SnapshotManager{stor: stor} +type SnapshotManager interface { + // TODO: add all necessary methods here } From 3872883c986ab619de7bb8e31c15afd6a910d49b Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Tue, 25 Apr 2023 22:09:17 +0300 Subject: [PATCH 015/139] Replace 'proto.assetID' to 'crypto.Digest'. --- pkg/state/snapshot_types.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index fa403f2a9..37b94841e 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -3,6 +3,7 @@ package state import ( "math/big" + "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" ) @@ -28,7 +29,7 @@ func (s *WavesBalancesSnapshot) dummy() error { // What is address || asset_id? type balanceAsset struct { address proto.Address - assetID proto.AssetID + assetID crypto.Digest balance uint64 } @@ -59,7 +60,7 @@ func (s *AccountScriptSnapshot) dummy() error { } type AssetScriptSnapshot struct { - assetID proto.AssetID + assetID crypto.Digest script proto.Script } @@ -87,7 +88,7 @@ func (s *LeaseStatusSnapshot) dummy() error { } type SponsorshipSnapshot struct { - assetID proto.AssetID + assetID crypto.Digest minSponsoredFee uint64 } @@ -116,7 +117,7 @@ func (s *FilledVolumeFeeSnapshot) dummy() error { } type StaticAssetInfoSnapshot struct { - assetID proto.AssetID + assetID crypto.Digest issuer proto.Address decimals int8 isNFT bool @@ -127,7 +128,7 @@ func (s *StaticAssetInfoSnapshot) dummy() error { } type AssetReissuabilitySnapshot struct { - assetID proto.AssetID + assetID crypto.Digest totalQuantity big.Int isReissuable bool } @@ -137,7 +138,7 @@ func (s *AssetReissuabilitySnapshot) dummy() error { } type AssetDescriptionSnapshot struct { - assetID proto.AssetID + assetID crypto.Digest assetName string assetDescription string changeHeight uint64 From 31b3825860820558acfde598dfb7e678037629d0 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Tue, 25 Apr 2023 22:10:00 +0300 Subject: [PATCH 016/139] Replace 'proto.Address' to 'proto.WavesAddress'. --- pkg/state/snapshot_types.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 37b94841e..b66519c75 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -14,7 +14,7 @@ type AtomicSnapshot interface { } type balanceWaves struct { - address proto.Address + address proto.WavesAddress balance uint64 } @@ -28,7 +28,7 @@ func (s *WavesBalancesSnapshot) dummy() error { // What is address || asset_id? type balanceAsset struct { - address proto.Address + address proto.WavesAddress assetID crypto.Digest balance uint64 } @@ -42,7 +42,7 @@ func (s *AssetBalancesSnapshot) dummy() error { } type DataEntriesSnapshot struct { - address proto.Address + address proto.WavesAddress dataEntries []proto.DataEntry } @@ -51,7 +51,7 @@ func (s *DataEntriesSnapshot) dummy() error { } type AccountScriptSnapshot struct { - address proto.Address + address proto.WavesAddress script proto.Script } @@ -69,7 +69,7 @@ func (s *AssetScriptSnapshot) dummy() error { } type LeaseBalanceSnapshot struct { - address proto.Address + address proto.WavesAddress leaseIn uint64 leaseOut uint64 } @@ -98,7 +98,7 @@ func (s *SponsorshipSnapshot) dummy() error { type AliasSnapshot struct { alias *proto.Alias - address *proto.Address + address *proto.WavesAddress } func (s *AliasSnapshot) dummy() error { @@ -118,7 +118,7 @@ func (s *FilledVolumeFeeSnapshot) dummy() error { type StaticAssetInfoSnapshot struct { assetID crypto.Digest - issuer proto.Address + issuer proto.WavesAddress decimals int8 isNFT bool } From ae7f506fff4e9c9b9406bd35d18cde9ea5853341 Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 26 Apr 2023 01:10:43 -0500 Subject: [PATCH 017/139] Changed leaseID type --- pkg/state/snapshot_types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index b66519c75..5a8f60d1a 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -79,7 +79,7 @@ func (s *LeaseBalanceSnapshot) dummy() error { } type LeaseStatusSnapshot struct { - leaseID uint64 + leaseID crypto.Digest isActive bool } From 4253a0d598c36b0f600d00a121b894c454339e45 Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 26 Apr 2023 01:31:56 -0500 Subject: [PATCH 018/139] changed types of leaseIn and leaseOut --- pkg/state/snapshot_types.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 5a8f60d1a..90a1688e7 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -70,8 +70,8 @@ func (s *AssetScriptSnapshot) dummy() error { type LeaseBalanceSnapshot struct { address proto.WavesAddress - leaseIn uint64 - leaseOut uint64 + leaseIn int64 + leaseOut int64 } func (s *LeaseBalanceSnapshot) dummy() error { From b1fbfbb924d3d228b572aa183d14166f4685ed65 Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 10 May 2023 21:14:45 -0500 Subject: [PATCH 019/139] Removed the pointer types from AliasSnapshot --- pkg/state/snapshot_types.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 90a1688e7..61e07db00 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -97,8 +97,8 @@ func (s *SponsorshipSnapshot) dummy() error { } type AliasSnapshot struct { - alias *proto.Alias - address *proto.WavesAddress + alias proto.Alias + address proto.WavesAddress } func (s *AliasSnapshot) dummy() error { From 327aa8df423694d27ebf57b1ea862ad471799a1c Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Wed, 3 May 2023 03:04:30 +0300 Subject: [PATCH 020/139] Change a bit 'AtomicSnapshot' interface. --- pkg/state/snapshot_types.go | 55 ++++++++++--------------------------- 1 file changed, 15 insertions(+), 40 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 61e07db00..07605e6ae 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -10,7 +10,8 @@ import ( type TransactionSnapshot []AtomicSnapshot type AtomicSnapshot interface { - dummy() error + atomicSnapshotMarker() + // TODO: add all necessary methods here } type balanceWaves struct { @@ -22,9 +23,7 @@ type WavesBalancesSnapshot struct { wavesBalances []balanceWaves } -func (s *WavesBalancesSnapshot) dummy() error { - return nil -} +func (*WavesBalancesSnapshot) atomicSnapshotMarker() {} // What is address || asset_id? type balanceAsset struct { @@ -37,36 +36,28 @@ type AssetBalancesSnapshot struct { assetBalances []balanceAsset } -func (s *AssetBalancesSnapshot) dummy() error { - return nil -} +func (*AssetBalancesSnapshot) atomicSnapshotMarker() {} type DataEntriesSnapshot struct { address proto.WavesAddress dataEntries []proto.DataEntry } -func (s *DataEntriesSnapshot) dummy() error { - return nil -} +func (*DataEntriesSnapshot) atomicSnapshotMarker() {} type AccountScriptSnapshot struct { address proto.WavesAddress script proto.Script } -func (s *AccountScriptSnapshot) dummy() error { - return nil -} +func (*AccountScriptSnapshot) atomicSnapshotMarker() {} type AssetScriptSnapshot struct { assetID crypto.Digest script proto.Script } -func (s *AssetScriptSnapshot) dummy() error { - return nil -} +func (*AssetScriptSnapshot) atomicSnapshotMarker() {} type LeaseBalanceSnapshot struct { address proto.WavesAddress @@ -74,36 +65,28 @@ type LeaseBalanceSnapshot struct { leaseOut int64 } -func (s *LeaseBalanceSnapshot) dummy() error { - return nil -} +func (*LeaseBalanceSnapshot) atomicSnapshotMarker() {} type LeaseStatusSnapshot struct { leaseID crypto.Digest isActive bool } -func (s *LeaseStatusSnapshot) dummy() error { - return nil -} +func (*LeaseStatusSnapshot) atomicSnapshotMarker() {} type SponsorshipSnapshot struct { assetID crypto.Digest minSponsoredFee uint64 } -func (s *SponsorshipSnapshot) dummy() error { - return nil -} +func (*SponsorshipSnapshot) atomicSnapshotMarker() {} type AliasSnapshot struct { alias proto.Alias address proto.WavesAddress } -func (s *AliasSnapshot) dummy() error { - return nil -} +func (*AliasSnapshot) atomicSnapshotMarker() {} // FilledVolumeFee Filled Volume and Fee type FilledVolumeFeeSnapshot struct { @@ -112,9 +95,7 @@ type FilledVolumeFeeSnapshot struct { filledFee uint64 } -func (s *FilledVolumeFeeSnapshot) dummy() error { - return nil -} +func (*FilledVolumeFeeSnapshot) atomicSnapshotMarker() {} type StaticAssetInfoSnapshot struct { assetID crypto.Digest @@ -123,9 +104,7 @@ type StaticAssetInfoSnapshot struct { isNFT bool } -func (s *StaticAssetInfoSnapshot) dummy() error { - return nil -} +func (*StaticAssetInfoSnapshot) atomicSnapshotMarker() {} type AssetReissuabilitySnapshot struct { assetID crypto.Digest @@ -133,9 +112,7 @@ type AssetReissuabilitySnapshot struct { isReissuable bool } -func (s *AssetReissuabilitySnapshot) dummy() error { - return nil -} +func (*AssetReissuabilitySnapshot) atomicSnapshotMarker() {} type AssetDescriptionSnapshot struct { assetID crypto.Digest @@ -144,9 +121,7 @@ type AssetDescriptionSnapshot struct { changeHeight uint64 } -func (s *AssetDescriptionSnapshot) dummy() error { - return nil -} +func (*AssetDescriptionSnapshot) atomicSnapshotMarker() {} type SnapshotManager interface { // TODO: add all necessary methods here From 227a7b37bbfb1963f75a006b063f6f07af6fdfdc Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Tue, 16 May 2023 23:05:51 +0300 Subject: [PATCH 021/139] Update snapshot types. --- pkg/state/snapshot_types.go | 98 ++++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 44 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 07605e6ae..76560cb51 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -14,111 +14,121 @@ type AtomicSnapshot interface { // TODO: add all necessary methods here } -type balanceWaves struct { - address proto.WavesAddress - balance uint64 +type BalanceWaves struct { + Address proto.WavesAddress + Balance uint64 } type WavesBalancesSnapshot struct { - wavesBalances []balanceWaves + WavesBalances []BalanceWaves } func (*WavesBalancesSnapshot) atomicSnapshotMarker() {} // What is address || asset_id? -type balanceAsset struct { - address proto.WavesAddress - assetID crypto.Digest - balance uint64 +type BalanceAsset struct { + Address proto.WavesAddress + AssetID crypto.Digest + Balance uint64 } type AssetBalancesSnapshot struct { - assetBalances []balanceAsset + AssetBalances []BalanceAsset } func (*AssetBalancesSnapshot) atomicSnapshotMarker() {} type DataEntriesSnapshot struct { - address proto.WavesAddress - dataEntries []proto.DataEntry + Address proto.WavesAddress + DataEntries []proto.DataEntry } func (*DataEntriesSnapshot) atomicSnapshotMarker() {} type AccountScriptSnapshot struct { - address proto.WavesAddress - script proto.Script + Address proto.WavesAddress // TODO: is it necessary? + PublicKey crypto.PublicKey + Script proto.Script + VerifierComplexity uint64 + CallableComplexities map[string]uint64 } func (*AccountScriptSnapshot) atomicSnapshotMarker() {} type AssetScriptSnapshot struct { - assetID crypto.Digest - script proto.Script + AssetID crypto.Digest + Script proto.Script + Complexity uint64 } func (*AssetScriptSnapshot) atomicSnapshotMarker() {} type LeaseBalanceSnapshot struct { - address proto.WavesAddress - leaseIn int64 - leaseOut int64 + Address proto.WavesAddress + LeaseIn uint64 + LeaseOut uint64 } func (*LeaseBalanceSnapshot) atomicSnapshotMarker() {} -type LeaseStatusSnapshot struct { - leaseID crypto.Digest - isActive bool +type LeaseStateSnapshot struct { + LeaseID crypto.Digest + Status LeaseStatus // TODO(nickeskov): add cancelHeight and cancelTxID info for canceled leases + Amount uint64 + Sender proto.WavesAddress + Recipient proto.WavesAddress + OriginTransactionID crypto.Digest + Height proto.Height } -func (*LeaseStatusSnapshot) atomicSnapshotMarker() {} +func (*LeaseStateSnapshot) atomicSnapshotMarker() {} type SponsorshipSnapshot struct { - assetID crypto.Digest - minSponsoredFee uint64 + AssetID crypto.Digest + MinSponsoredFee uint64 } func (*SponsorshipSnapshot) atomicSnapshotMarker() {} type AliasSnapshot struct { - alias proto.Alias - address proto.WavesAddress + Address proto.WavesAddress + Alias proto.Alias } func (*AliasSnapshot) atomicSnapshotMarker() {} -// FilledVolumeFee Filled Volume and Fee -type FilledVolumeFeeSnapshot struct { - orderID []byte - filledVolume uint64 - filledFee uint64 +// FilledVolumeFeeSnapshot Filled Volume and Fee +type FilledVolumeFeeSnapshot struct { // OrderFill + OrderID crypto.Digest + FilledVolume uint64 + FilledFee uint64 } func (*FilledVolumeFeeSnapshot) atomicSnapshotMarker() {} type StaticAssetInfoSnapshot struct { - assetID crypto.Digest - issuer proto.WavesAddress - decimals int8 - isNFT bool + AssetID crypto.Digest + SourceTransactionID crypto.Digest + Issuer proto.WavesAddress + Decimals uint8 + IsNFT bool } func (*StaticAssetInfoSnapshot) atomicSnapshotMarker() {} -type AssetReissuabilitySnapshot struct { - assetID crypto.Digest - totalQuantity big.Int - isReissuable bool +type AssetReissuabilitySnapshot struct { // AssetVolume in pb + AssetID crypto.Digest + TotalQuantity big.Int // volume in protobuf + IsReissuable bool } func (*AssetReissuabilitySnapshot) atomicSnapshotMarker() {} -type AssetDescriptionSnapshot struct { - assetID crypto.Digest - assetName string - assetDescription string - changeHeight uint64 +type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb + AssetID crypto.Digest + AssetName string + AssetDescription string + ChangeHeight proto.Height // last_updated in pb } func (*AssetDescriptionSnapshot) atomicSnapshotMarker() {} From 55c7026589260ba99ae147be51a484021609f12c Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Wed, 17 May 2023 13:11:06 +0300 Subject: [PATCH 022/139] Removed unnecessary fields in 'AccountScriptSnapshot' struct. --- pkg/state/snapshot_types.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 76560cb51..7d239c3b9 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -46,11 +46,9 @@ type DataEntriesSnapshot struct { func (*DataEntriesSnapshot) atomicSnapshotMarker() {} type AccountScriptSnapshot struct { - Address proto.WavesAddress // TODO: is it necessary? - PublicKey crypto.PublicKey - Script proto.Script - VerifierComplexity uint64 - CallableComplexities map[string]uint64 + PublicKey crypto.PublicKey + Script proto.Script + VerifierComplexity uint64 } func (*AccountScriptSnapshot) atomicSnapshotMarker() {} From 2db610ce3d10cdb5490ad8ab1e4886608fa547c0 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Wed, 17 May 2023 17:50:26 +0300 Subject: [PATCH 023/139] Remove unnecessary types. --- pkg/state/snapshot_types.go | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 7d239c3b9..535797bfc 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -14,31 +14,23 @@ type AtomicSnapshot interface { // TODO: add all necessary methods here } -type BalanceWaves struct { +type WavesBalanceSnapshot struct { Address proto.WavesAddress Balance uint64 } -type WavesBalancesSnapshot struct { - WavesBalances []BalanceWaves -} - -func (*WavesBalancesSnapshot) atomicSnapshotMarker() {} +func (*WavesBalanceSnapshot) atomicSnapshotMarker() {} // What is address || asset_id? -type BalanceAsset struct { +type AssetBalanceSnapshot struct { Address proto.WavesAddress AssetID crypto.Digest Balance uint64 } -type AssetBalancesSnapshot struct { - AssetBalances []BalanceAsset -} - -func (*AssetBalancesSnapshot) atomicSnapshotMarker() {} +func (*AssetBalanceSnapshot) atomicSnapshotMarker() {} -type DataEntriesSnapshot struct { +type DataEntriesSnapshot struct { // AccountData in pb Address proto.WavesAddress DataEntries []proto.DataEntry } From a9d0d3ff74c8e28b096feba4fe3f257ab7a2f962 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Fri, 19 May 2023 16:28:51 +0300 Subject: [PATCH 024/139] Change 'StaticAssetInfoSnapshot.Issuer' field to 'StaticAssetInfoSnapshot.IssuerPublicKey'. --- pkg/state/snapshot_types.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 535797bfc..6e15a1f79 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -38,7 +38,7 @@ type DataEntriesSnapshot struct { // AccountData in pb func (*DataEntriesSnapshot) atomicSnapshotMarker() {} type AccountScriptSnapshot struct { - PublicKey crypto.PublicKey + SenderPublicKey crypto.PublicKey Script proto.Script VerifierComplexity uint64 } @@ -99,7 +99,7 @@ func (*FilledVolumeFeeSnapshot) atomicSnapshotMarker() {} type StaticAssetInfoSnapshot struct { AssetID crypto.Digest SourceTransactionID crypto.Digest - Issuer proto.WavesAddress + IssuerPublicKey crypto.PublicKey Decimals uint8 IsNFT bool } From 8109d5549f6d7479b8b016487da8ef9dc246e587 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Fri, 19 May 2023 17:29:50 +0300 Subject: [PATCH 025/139] Rename 'AssetReissuabilitySnapshot' to 'AssetVolumeSnapshot'. --- pkg/state/snapshot_types.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 6e15a1f79..67df41639 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -106,13 +106,13 @@ type StaticAssetInfoSnapshot struct { func (*StaticAssetInfoSnapshot) atomicSnapshotMarker() {} -type AssetReissuabilitySnapshot struct { // AssetVolume in pb +type AssetVolumeSnapshot struct { // AssetVolume in pb AssetID crypto.Digest TotalQuantity big.Int // volume in protobuf IsReissuable bool } -func (*AssetReissuabilitySnapshot) atomicSnapshotMarker() {} +func (*AssetVolumeSnapshot) atomicSnapshotMarker() {} type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb AssetID crypto.Digest From 88618791999a0335edcec1f3afb3ddeb7976eeaf Mon Sep 17 00:00:00 2001 From: Anton Ilin <48175203+Anton-Rampage@users.noreply.github.com> Date: Mon, 22 May 2023 16:54:30 +0300 Subject: [PATCH 026/139] Add feature block reward distribution (#1082) * add feature BlockRewardDistribution * fix tests * Improvement of the test on reward distribution to check that remainder of division goes to miner. * refactor after rewiev * fix feature info and add reward addresses in testnet and stagenet configs * DAO and buyback addresses added for MainNet. Formatting of settings files fixed. --------- Co-authored-by: Alexey Kiselev Co-authored-by: Nikolay Eskov --- pkg/settings/blockchain_settings.go | 9 +-- pkg/settings/embedded/mainnet.json | 4 ++ pkg/settings/embedded/stagenet.json | 4 ++ pkg/settings/embedded/testnet.json | 4 ++ pkg/settings/features.go | 14 +++-- pkg/state/block_differ.go | 19 +++++- pkg/state/block_differ_test.go | 98 ++++++++++++++++++++++++++++- 7 files changed, 138 insertions(+), 14 deletions(-) diff --git a/pkg/settings/blockchain_settings.go b/pkg/settings/blockchain_settings.go index e3acdc8e8..08223395a 100644 --- a/pkg/settings/blockchain_settings.go +++ b/pkg/settings/blockchain_settings.go @@ -81,10 +81,11 @@ type FunctionalitySettings struct { MaxBaseTarget uint64 `json:"max_base_target"` // Block Reward - BlockRewardTerm uint64 `json:"block_reward_term"` - InitialBlockReward uint64 `json:"initial_block_reward"` - BlockRewardIncrement uint64 `json:"block_reward_increment"` - BlockRewardVotingPeriod uint64 `json:"block_reward_voting_period"` + BlockRewardTerm uint64 `json:"block_reward_term"` + InitialBlockReward uint64 `json:"initial_block_reward"` + BlockRewardIncrement uint64 `json:"block_reward_increment"` + BlockRewardVotingPeriod uint64 `json:"block_reward_voting_period"` + RewardAddresses []proto.WavesAddress `json:"reward_addresses"` MinUpdateAssetInfoInterval uint64 `json:"min_update_asset_info_interval"` } diff --git a/pkg/settings/embedded/mainnet.json b/pkg/settings/embedded/mainnet.json index 793802725..e2e905c53 100644 --- a/pkg/settings/embedded/mainnet.json +++ b/pkg/settings/embedded/mainnet.json @@ -33,6 +33,10 @@ "initial_block_reward": 600000000, "block_reward_increment": 50000000, "block_reward_voting_period": 10000, + "reward_addresses": [ + "3PEgG7eZHLFhcfsTSaYxgRhZsh4AxMvA4Ms", + "3PHiS1yeSecmAE9r3Q4hrXXRwXQ6ofstqSN" + ], "min_update_asset_info_interval": 100000, "type": 0, "genesis": { diff --git a/pkg/settings/embedded/stagenet.json b/pkg/settings/embedded/stagenet.json index 68586303a..c96a69976 100644 --- a/pkg/settings/embedded/stagenet.json +++ b/pkg/settings/embedded/stagenet.json @@ -47,6 +47,10 @@ "initial_block_reward": 600000000, "block_reward_increment": 50000000, "block_reward_voting_period": 10000, + "reward_addresses": [ + "3MaFVH1vTv18FjBRugSRebx259D7xtRh9ic", + "3MbhiRiLFLJ1EVKNP9npRszcLLQDjwnFfZM" + ], "min_update_asset_info_interval": 10, "type": 2, "genesis": { diff --git a/pkg/settings/embedded/testnet.json b/pkg/settings/embedded/testnet.json index 00097dd39..930a34d7f 100644 --- a/pkg/settings/embedded/testnet.json +++ b/pkg/settings/embedded/testnet.json @@ -33,6 +33,10 @@ "initial_block_reward": 600000000, "block_reward_increment": 50000000, "block_reward_voting_period": 10000, + "reward_addresses": [ + "3Myb6G8DkdBb8YcZzhrky65HrmiNuac3kvS", + "3N13KQpdY3UU7JkWUBD9kN7t7xuUgeyYMTT" + ], "min_update_asset_info_interval": 100000, "type": 1, "genesis": { diff --git a/pkg/settings/features.go b/pkg/settings/features.go index ba422933e..ab6e5fbf7 100644 --- a/pkg/settings/features.go +++ b/pkg/settings/features.go @@ -16,12 +16,13 @@ const ( Ride4DApps // RIDE V3 OrderV3 ReduceNFTFee - BlockReward // 14 - BlockV5 // 15 - RideV5 // 16 - RideV6 // 17 - ConsensusImprovements // 18 - InvokeExpression // 19 + BlockReward // 14 + BlockV5 // 15 + RideV5 // 16 + RideV6 // 17 + ConsensusImprovements // 18 + BlockRewardDistribution // 19 + InvokeExpression // 20 ) type FeatureInfo struct { @@ -48,5 +49,6 @@ var FeaturesInfo = map[Feature]FeatureInfo{ RideV5: {true, "Ride V5, dApp-to-dApp invocations"}, RideV6: {true, "Ride V6, MetaMask support"}, ConsensusImprovements: {true, "Consensus and MetaMask updates"}, + BlockRewardDistribution: {true, "Block Reward Distribution"}, InvokeExpression: {false, "InvokeExpression"}, } diff --git a/pkg/state/block_differ.go b/pkg/state/block_differ.go index 8baac93e4..d06ffa7af 100644 --- a/pkg/state/block_differ.go +++ b/pkg/state/block_differ.go @@ -203,11 +203,26 @@ func (d *blockDiffer) addBlockReward(diff txDiff, addr proto.AddressID, block *p if reward > math.MaxInt64 { return errors.New("reward overflows int64") } - wavesKey := wavesBalanceKey{addr} - err = diff.appendBalanceDiff(wavesKey.bytes(), balanceDiff{balance: int64(reward)}) + blockRewardDistribution, err := d.stor.features.newestIsActivated(int16(settings.BlockRewardDistribution)) if err != nil { return err } + wavesKey := wavesBalanceKey{addr} + minerReward := int64(reward) + if blockRewardDistribution { + numberOfAddresses := uint64(len(d.settings.RewardAddresses) + 1) + for _, a := range d.settings.RewardAddresses { + balanceKey := wavesBalanceKey{a.ID()} + addressReward := int64(reward / numberOfAddresses) + if err = diff.appendBalanceDiff(balanceKey.bytes(), balanceDiff{balance: addressReward}); err != nil { + return err + } + minerReward -= addressReward + } + } + if err = diff.appendBalanceDiff(wavesKey.bytes(), balanceDiff{balance: minerReward}); err != nil { + return err + } d.appendBlockInfoToTxDiff(diff, block) return nil } diff --git a/pkg/state/block_differ_test.go b/pkg/state/block_differ_test.go index 3fd6ddf0b..48dc5ac1c 100644 --- a/pkg/state/block_differ_test.go +++ b/pkg/state/block_differ_test.go @@ -18,8 +18,11 @@ type blockDifferTestObjects struct { } func createBlockDiffer(t *testing.T) *blockDifferTestObjects { - sets := settings.TestNetSettings - stor := createStorageObjects(t, false) + return createBlockDifferWithSettings(t, settings.TestNetSettings) +} + +func createBlockDifferWithSettings(t *testing.T, sets *settings.BlockchainSettings) *blockDifferTestObjects { + stor := createStorageObjectsWithOptions(t, testStorageObjectsOptions{Amend: false, Settings: sets}) handler, err := newTransactionHandler(sets.Genesis.BlockID(), stor.entities, sets) require.NoError(t, err, "newTransactionHandler() failed") blockDiffer, err := newBlockDiffer(handler, stor.entities, sets) @@ -190,3 +193,94 @@ func TestCreateBlockDiffWithReward(t *testing.T) { correctMinerDiff := txDiff{testGlobal.minerInfo.wavesKey: correctMinerWavesBalanceDiff} assert.Equal(t, correctMinerDiff, minerDiff) } + +func TestBlockRewardDistributionWithTwoAddresses(t *testing.T) { + sets := settings.TestNetSettings + // Add some addresses for reward distribution + sets.RewardAddresses = []proto.WavesAddress{testGlobal.senderInfo.addr, testGlobal.recipientInfo.addr} + sets.InitialBlockReward = 800000000 + to := createBlockDifferWithSettings(t, sets) + + // Activate NG and BlockReward + to.stor.activateFeature(t, int16(settings.NG)) + to.stor.activateFeature(t, int16(settings.BlockReward)) + to.stor.activateFeature(t, int16(settings.BlockRewardDistribution)) + + sig := genRandBlockIds(t, 1)[0] + gs := crypto.MustBytesFromBase58(defaultGenSig) + + // First block + block1 := genBlockWithSingleTransaction(t, sig, gs, to) + to.stor.addBlock(t, block1.BlockID()) + txs := block1.Transactions + for _, tx := range txs { + err := to.blockDiffer.countMinerFee(tx) + require.NoError(t, err) + } + err := to.blockDiffer.saveCurFeeDistr(&block1.BlockHeader) + require.NoError(t, err) + + // Second block + block2 := genBlockWithSingleTransaction(t, block1.BlockID(), block1.GenSignature, to) + to.stor.addBlock(t, block2.BlockID()) + minerDiff, err := to.blockDiffer.createMinerDiff(&block2.BlockHeader, true) + require.NoError(t, err) + + fee := int64(defaultFee - defaultFee/5*2) + reward := int64(to.blockDiffer.settings.FunctionalitySettings.InitialBlockReward) + additionalAddressReward := reward / 3 + correctFirstRewardAddressBalanceDiff := newBalanceDiff(additionalAddressReward, 0, 0, false) + correctSecondRewardAddressBalanceDiff := newBalanceDiff(additionalAddressReward, 0, 0, false) + correctMinerWavesBalanceDiff := newBalanceDiff(fee+reward-2*additionalAddressReward, 0, 0, false) + correctMinerWavesBalanceDiff.blockID = block2.BlockID() + correctFirstRewardAddressBalanceDiff.blockID = block2.BlockID() + correctSecondRewardAddressBalanceDiff.blockID = block2.BlockID() + correctDiff := txDiff{ + testGlobal.minerInfo.wavesKey: correctMinerWavesBalanceDiff, + testGlobal.senderInfo.wavesKey: correctFirstRewardAddressBalanceDiff, + testGlobal.recipientInfo.wavesKey: correctSecondRewardAddressBalanceDiff, + } + assert.Equal(t, correctDiff, minerDiff) +} + +func TestBlockRewardDistributionWithOneAddress(t *testing.T) { + to := createBlockDiffer(t) + // Add some addresses for reward distribution + to.blockDiffer.settings.RewardAddresses = []proto.WavesAddress{testGlobal.senderInfo.addr} + + // Activate NG and BlockReward + to.stor.activateFeature(t, int16(settings.NG)) + to.stor.activateFeature(t, int16(settings.BlockReward)) + to.stor.activateFeature(t, int16(settings.BlockRewardDistribution)) + + sig := genRandBlockIds(t, 1)[0] + gs := crypto.MustBytesFromBase58(defaultGenSig) + + // First block + block1 := genBlockWithSingleTransaction(t, sig, gs, to) + to.stor.addBlock(t, block1.BlockID()) + txs := block1.Transactions + for _, tx := range txs { + err := to.blockDiffer.countMinerFee(tx) + require.NoError(t, err) + } + err := to.blockDiffer.saveCurFeeDistr(&block1.BlockHeader) + require.NoError(t, err) + + // Second block + block2 := genBlockWithSingleTransaction(t, block1.BlockID(), block1.GenSignature, to) + to.stor.addBlock(t, block2.BlockID()) + minerDiff, err := to.blockDiffer.createMinerDiff(&block2.BlockHeader, true) + require.NoError(t, err) + + fee := defaultFee - defaultFee/5*2 + correctMinerWavesBalanceDiff := newBalanceDiff(int64(fee+(to.blockDiffer.settings.FunctionalitySettings.InitialBlockReward/2)), 0, 0, false) + correctRewardAddressBalanceDiff := newBalanceDiff(int64(to.blockDiffer.settings.FunctionalitySettings.InitialBlockReward/2), 0, 0, false) + correctMinerWavesBalanceDiff.blockID = block2.BlockID() + correctRewardAddressBalanceDiff.blockID = block2.BlockID() + correctDiff := txDiff{ + testGlobal.minerInfo.wavesKey: correctMinerWavesBalanceDiff, + testGlobal.senderInfo.wavesKey: correctRewardAddressBalanceDiff, + } + assert.Equal(t, correctDiff, minerDiff) +} From fa0d23deb43334d6550d6eaed528987d2d0445f0 Mon Sep 17 00:00:00 2001 From: Anton Ilin <48175203+Anton-Rampage@users.noreply.github.com> Date: Mon, 22 May 2023 18:13:38 +0300 Subject: [PATCH 027/139] change actions count with feature BlockRewardDistribution activated (#1088) * change count actions with feature BlockRewardDistribution activated * fix comment in script * Merge fix. * Fix version in comment * Eth transaction refactoring and tests --------- Co-authored-by: Alexey Kiselev Co-authored-by: Nikolay Eskov --- pkg/proto/eth_transaction.go | 95 +++++++- pkg/proto/eth_transaction_test.go | 133 +++++++++++ pkg/proto/ethabi/abi_test.go | 13 +- pkg/proto/ethabi/argument.go | 15 +- pkg/proto/ethabi/data_types.go | 2 +- pkg/proto/ethabi/erc20.go | 3 +- pkg/proto/ethabi/function_signature.go | 2 +- pkg/proto/ethabi/methods_map.go | 36 +-- pkg/proto/ethabi/parsing_test.go | 60 ++++- pkg/proto/ethabi/type.go | 5 - pkg/proto/ethabi/unpack.go | 295 +++++++++++++++---------- pkg/ride/converters.go | 58 +---- pkg/ride/converters_test.go | 2 +- pkg/ride/environment.go | 81 ++++--- pkg/ride/ethabi.go | 40 ---- pkg/ride/ethabi_test.go | 55 ----- pkg/ride/runtime.go | 1 + pkg/ride/runtime_moq_test.go | 37 ++++ pkg/ride/test_helpers_test.go | 10 + pkg/ride/tree_evaluation_test.go | 164 ++++++++++++++ pkg/state/appender.go | 132 ++++++----- pkg/state/eth_info.go | 7 +- pkg/state/ethereum_tx_test.go | 2 +- pkg/state/invoke_applier.go | 1 + pkg/state/script_caller.go | 7 +- pkg/state/transaction_checker.go | 41 +++- 26 files changed, 875 insertions(+), 422 deletions(-) delete mode 100644 pkg/ride/ethabi.go delete mode 100644 pkg/ride/ethabi_test.go diff --git a/pkg/proto/eth_transaction.go b/pkg/proto/eth_transaction.go index 019fe0f6c..3a2741a76 100644 --- a/pkg/proto/eth_transaction.go +++ b/pkg/proto/eth_transaction.go @@ -97,11 +97,11 @@ func NewEthereumTransferWavesTxKind() *EthereumTransferWavesTxKind { return &EthereumTransferWavesTxKind{} } -func (tx *EthereumTransferWavesTxKind) DecodedData() *ethabi.DecodedCallData { +func (k *EthereumTransferWavesTxKind) DecodedData() *ethabi.DecodedCallData { return nil } -func (tx *EthereumTransferWavesTxKind) String() string { +func (k *EthereumTransferWavesTxKind) String() string { return "EthereumTransferWavesTxKind" } @@ -115,11 +115,11 @@ func NewEthereumTransferAssetsErc20TxKind(decodedData ethabi.DecodedCallData, as return &EthereumTransferAssetsErc20TxKind{Asset: asset, decodedData: decodedData, Arguments: arguments} } -func (tx *EthereumTransferAssetsErc20TxKind) DecodedData() *ethabi.DecodedCallData { - return &tx.decodedData +func (k *EthereumTransferAssetsErc20TxKind) DecodedData() *ethabi.DecodedCallData { + return &k.decodedData } -func (tx *EthereumTransferAssetsErc20TxKind) String() string { +func (k *EthereumTransferAssetsErc20TxKind) String() string { return "EthereumTransferAssetsErc20TxKind" } @@ -131,14 +131,93 @@ func NewEthereumInvokeScriptTxKind(decodedData ethabi.DecodedCallData) *Ethereum return &EthereumInvokeScriptTxKind{decodedData: decodedData} } -func (tx *EthereumInvokeScriptTxKind) DecodedData() *ethabi.DecodedCallData { - return &tx.decodedData +func (k *EthereumInvokeScriptTxKind) DecodedData() *ethabi.DecodedCallData { + return &k.decodedData } -func (tx *EthereumInvokeScriptTxKind) String() string { +func (k *EthereumInvokeScriptTxKind) String() string { return "EthereumInvokeScriptTxKind" } +// ethABIDataTypeToArgument perform conversion of ethabi.DataType to Argument type. +// Note that this function doesn't copy ethabi.Bytes. It only copies a pointer to type. +func ethABIDataTypeToArgument(dataType ethabi.DataType) (argument Argument, _ error) { + switch t := dataType.(type) { + case ethabi.Int: + argument = &IntegerArgument{Value: int64(t)} + case ethabi.Bool: + argument = &BooleanArgument{Value: bool(t)} + case ethabi.Bytes: + argument = &BinaryArgument{Value: t} + case ethabi.String: + argument = &StringArgument{Value: string(t)} + case ethabi.List: + arguments := make(Arguments, len(t)) + for i, ethABIElem := range t { + arg, err := ethABIDataTypeToArgument(ethABIElem) + if err != nil { + return nil, errors.Wrapf(err, + "failed to convert ethabi.DataType (%T) to Argument at %d list postition", ethABIElem, i, + ) + } + arguments[i] = arg + } + argument = &ListArgument{Items: arguments} + default: // ethabi.BigInt is not supported + return nil, errors.Errorf( + "ethabi.DataType (%T) to Argument conversion is not supported", dataType, + ) + } + return argument, nil +} + +func ConvertDecodedEthereumArgumentsToProtoArguments(decodedArgs []ethabi.DecodedArg) (Arguments, error) { + args := make(Arguments, len(decodedArgs)) + for i, input := range decodedArgs { + arg, err := ethABIDataTypeToArgument(input.Value) + if err != nil { + return nil, errors.Wrapf(err, + "failed to convert ethabi.DataType (%T) to Argument at %d inputs position", input.Value, i) + } + args[i] = arg + } + return args, nil +} + +func (k *EthereumInvokeScriptTxKind) ValidateCallData(dApp WavesAddress) error { + args, err := ConvertDecodedEthereumArgumentsToProtoArguments(k.decodedData.Inputs) + if err != nil { + return errors.Wrap(err, "failed to convert decoded data inputs") + } + fc := NewFunctionCall(k.decodedData.Name, args) + if err := fc.Valid(); err != nil { + return errors.Wrap(err, "function call validation failed") + } + fcBytes, err := fc.MarshalBinary() + if err != nil { + return errors.Wrap(err, "failed to marshal function call") + } + rcpPB, err := NewRecipientFromAddress(dApp).ToProtobuf() + if err != nil { + return errors.Wrapf(err, "failed to convert addr %q to protobuf recipient", dApp.String()) + } + payments := make([]*g.Amount, len(k.decodedData.Payments)) + for i, pmt := range k.decodedData.Payments { + asset := NewOptionalAsset(pmt.PresentAssetID, pmt.AssetID) + payments[i] = &g.Amount{AssetId: asset.ToID(), Amount: pmt.Amount} + } + data := g.InvokeScriptTransactionData{ + DApp: rcpPB, + FunctionCall: fcBytes, + Payments: payments, + } + s := data.SizeVT() + if s > maxInvokeScriptWithProofsProtobufPayloadBytes { + return errors.Errorf("ethereum tx calldata too big: max %d, got %d", maxInvokeScriptWithProofsProtobufPayloadBytes, s) + } + return nil +} + type EthereumTransaction struct { inner EthereumTxData innerBinarySize int diff --git a/pkg/proto/eth_transaction_test.go b/pkg/proto/eth_transaction_test.go index 67fbd1a06..407610cb5 100644 --- a/pkg/proto/eth_transaction_test.go +++ b/pkg/proto/eth_transaction_test.go @@ -2,11 +2,16 @@ package proto import ( "encoding/json" + "math/big" + "strconv" + "strings" "testing" "github.com/mr-tron/base58" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/wavesplatform/gowaves/pkg/crypto" + "github.com/wavesplatform/gowaves/pkg/proto/ethabi" ) func TestEthereumTransaction_GetID(t *testing.T) { @@ -121,3 +126,131 @@ func TestEthereumTransactionFromScalaJSON(t *testing.T) { require.NoError(t, err) assert.Equal(t, expSenderPK, pk) } + +func TestEthABIDataTypeToArgument(t *testing.T) { + hugeInt, ok := new(big.Int).SetString("123454323456434285767546723400991456870502323864587234659828639850098161345465903596567", 10) + require.True(t, ok) + + tests := []struct { + inputDataType ethabi.DataType + expectedRideType Argument + err string + }{ + {ethabi.Int(5345345), &IntegerArgument{Value: 5345345}, ""}, + {ethabi.Bool(true), &BooleanArgument{Value: true}, ""}, + {ethabi.Bool(false), &BooleanArgument{Value: false}, ""}, + {ethabi.Bytes("#This is Test bytes!"), &BinaryArgument{Value: []byte("#This is Test bytes!")}, ""}, + {ethabi.String("This is @ Test string!"), &StringArgument{Value: "This is @ Test string!"}, ""}, + { + inputDataType: ethabi.List{ + ethabi.Int(453), + ethabi.Bool(true), + ethabi.String("the best test string ever!"), + ethabi.Bytes("command and conquer!"), + ethabi.List{ + ethabi.Bytes("one more"), + ethabi.Bool(false), + }, + }, + expectedRideType: &ListArgument{Items: Arguments{ + &IntegerArgument{Value: 453}, + &BooleanArgument{Value: true}, + &StringArgument{Value: "the best test string ever!"}, + &BinaryArgument{Value: []byte("command and conquer!")}, + &ListArgument{Items: Arguments{ + &BinaryArgument{Value: []byte("one more")}, + &BooleanArgument{Value: false}, + }}, + }}, + err: "", + }, + {ethabi.BigInt{V: hugeInt}, nil, "ethabi.DataType (ethabi.BigInt) to Argument conversion is not supported"}, + } + for _, tc := range tests { + actualRideType, err := ethABIDataTypeToArgument(tc.inputDataType) + if tc.err == "" { + assert.NoError(t, err) + assert.Equal(t, tc.expectedRideType, actualRideType) + } else { + assert.EqualError(t, err, tc.err) + } + } +} + +func TestEthereumInvokeScriptTxKind_ValidateCallData(t *testing.T) { + exampleDapp := MustAddressFromString("3MXLD5eVtKEswHWD5p841dKSzqYgBBV1jeA") + repeatArg := func(arg ethabi.DecodedArg, cnt int) []ethabi.DecodedArg { + args := make([]ethabi.DecodedArg, cnt) + for i := range args { + args[i] = arg + } + return args + } + tests := []struct { + callData ethabi.DecodedCallData + err string + }{ + { + callData: ethabi.DecodedCallData{ + Name: "ok", + Inputs: []ethabi.DecodedArg{ + {Soltype: ethabi.Argument{}, Value: ethabi.Int(100500)}, + {Soltype: ethabi.Argument{}, Value: ethabi.Bool(true)}, + {Soltype: ethabi.Argument{}, Value: ethabi.Bool(false)}, + {Soltype: ethabi.Argument{}, Value: ethabi.String("kekekekek")}, + {Soltype: ethabi.Argument{}, Value: ethabi.Bytes([]byte{1, 2, 3, 42, 21})}, + {Soltype: ethabi.Argument{}, Value: ethabi.List{ethabi.Int(100500), ethabi.Bool(true)}}, + }, + Payments: []ethabi.Payment{{Amount: 21}, {PresentAssetID: true, AssetID: crypto.Digest{1, 2, 3}, Amount: 42}}, + }, + err: "", + }, + { + callData: ethabi.DecodedCallData{ + Name: "fail", + Inputs: []ethabi.DecodedArg{ + {Soltype: ethabi.Argument{}, Value: ethabi.Bool(true)}, + {Soltype: ethabi.Argument{}, Value: ethabi.Bool(false)}, + {Soltype: ethabi.Argument{}, Value: ethabi.BigInt{V: big.NewInt(100500)}}, + }, + Payments: []ethabi.Payment{{Amount: 42}, {PresentAssetID: true, AssetID: crypto.Digest{1, 2, 3}, Amount: 21}}, + }, + err: "failed to convert decoded data inputs: failed to convert ethabi.DataType (ethabi.BigInt) to Argument at 2 inputs position: ethabi.DataType (ethabi.BigInt) to Argument conversion is not supported", + }, + { + callData: ethabi.DecodedCallData{ + Name: "fail", + Inputs: []ethabi.DecodedArg{{Soltype: ethabi.Argument{}, Value: ethabi.String(strings.Repeat("F", 5050))}}, + Payments: []ethabi.Payment{{Amount: 11}, {PresentAssetID: true, AssetID: crypto.Digest{1, 2, 3}, Amount: 22}}, + }, + err: "ethereum tx calldata too big: max 5120, got 5139", + }, + { + callData: ethabi.DecodedCallData{ + Name: strings.Repeat("F", maxFunctionNameBytes+1), + Inputs: []ethabi.DecodedArg{{Soltype: ethabi.Argument{}, Value: ethabi.String(strings.Repeat("F", 5050))}}, + Payments: []ethabi.Payment{{Amount: 11}, {PresentAssetID: true, AssetID: crypto.Digest{1, 2, 3}, Amount: 22}}, + }, + err: "function call validation failed: function name is too big", + }, + { + callData: ethabi.DecodedCallData{ + Name: "fail", + Inputs: repeatArg(ethabi.DecodedArg{Soltype: ethabi.Argument{}, Value: ethabi.String(strings.Repeat("F", 5050))}, maxArguments+1), + Payments: []ethabi.Payment{{Amount: 11}, {PresentAssetID: true, AssetID: crypto.Digest{1, 2, 3}, Amount: 22}}, + }, + err: "function call validation failed: too many arguments", + }, + } + for i, tc := range tests { + t.Run(strconv.Itoa(i+1), func(t *testing.T) { + kind := NewEthereumInvokeScriptTxKind(tc.callData) + err := kind.ValidateCallData(exampleDapp) + if tc.err == "" { + assert.NoError(t, err) + } else { + assert.EqualError(t, err, tc.err) + } + }) + } +} diff --git a/pkg/proto/ethabi/abi_test.go b/pkg/proto/ethabi/abi_test.go index 530eb1a6d..42663438d 100644 --- a/pkg/proto/ethabi/abi_test.go +++ b/pkg/proto/ethabi/abi_test.go @@ -253,31 +253,37 @@ func TestUnpackPayment(t *testing.T) { tests := []struct { hexInput string expectedPayment Payment + slotsRead int }{ { "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", Payment{PresentAssetID: false, AssetID: crypto.Digest{}, Amount: 1}, + 2, }, { "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a", Payment{PresentAssetID: false, AssetID: crypto.Digest{}, Amount: 10}, + 2, }, { "0x06000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", Payment{PresentAssetID: true, AssetID: crypto.Digest{0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}, Amount: 1}, + 2, }, { "0x01000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000009", Payment{PresentAssetID: true, AssetID: crypto.Digest{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5}, Amount: 9}, + 2, }, } for _, tc := range tests { bts, err := hex.DecodeString(strings.TrimPrefix(tc.hexInput, "0x")) require.NoError(t, err) - actualPayment, err := unpackPayment(bts) + actualPayment, slotsRead, err := unpackPayment(bts) require.NoError(t, err) require.Equal(t, tc.expectedPayment, actualPayment) + require.Equal(t, tc.slotsRead, slotsRead) } } @@ -285,11 +291,13 @@ func TestUnpackPayments(t *testing.T) { tests := []struct { hexCallData string paymentsSliceOffset int + slotsRead int expectedPayments []Payment }{ { hexCallData: "0x3e08c22800000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000573616664730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", paymentsSliceOffset: 32, + slotsRead: 2, expectedPayments: make([]Payment, 0), }, } @@ -297,8 +305,9 @@ func TestUnpackPayments(t *testing.T) { bts, err := hex.DecodeString(strings.TrimPrefix(tc.hexCallData, "0x")) require.NoError(t, err) - payments, err := unpackPayments(tc.paymentsSliceOffset, bts[SelectorSize:]) + payments, slotsRead, err := unpackPayments(tc.paymentsSliceOffset, bts[SelectorSize:]) require.NoError(t, err) require.Equal(t, tc.expectedPayments, payments) + require.Equal(t, tc.slotsRead, slotsRead) } } diff --git a/pkg/proto/ethabi/argument.go b/pkg/proto/ethabi/argument.go index f9787a275..bcf5530c7 100644 --- a/pkg/proto/ethabi/argument.go +++ b/pkg/proto/ethabi/argument.go @@ -29,22 +29,23 @@ func NewArgumentFromRideTypeMeta(name string, rideT meta.Type) (Argument, error) // UnpackRideValues can be used to unpack ABI-encoded hexdata according to the ABI-specification, // without supplying a struct to unpack into. Instead, this method returns a list containing the // values. An atomic argument will be a list with one element. -func (arguments Arguments) UnpackRideValues(data []byte) ([]DataType, int, error) { +func (arguments Arguments) UnpackRideValues(output []byte) (_ []DataType, paymentsSliceIndex, slotsReadTotal int, _ error) { retval := make([]DataType, 0, len(arguments)) virtualArgs := 0 for index, arg := range arguments { - marshalledValue, err := toDataType((index+virtualArgs)*32, arg.Type, data) + marshalledValue, slotsRead, err := toDataType((index+virtualArgs)*abiSlotSize, arg.Type, output) if arg.Type.T == TupleType && !isDynamicType(arg.Type) { // If we have a static tuple, like (uint256, bool, uint256), these are - // coded as just like uint256,bool,uint256 - tupleSize := getTypeSize(arg.Type)/32 - 1 + // coded as uint256,bool,uint256 + tupleSize := getTypeSize(arg.Type)/abiSlotSize - 1 virtualArgs += tupleSize } if err != nil { - return nil, 0, err + return nil, 0, 0, err } retval = append(retval, marshalledValue) + slotsReadTotal += slotsRead } - paymentsSliceOffset := (len(arguments) + virtualArgs) * 32 - return retval, paymentsSliceOffset, nil + paymentsSliceIndex = (len(arguments) + virtualArgs) * abiSlotSize + return retval, paymentsSliceIndex, slotsReadTotal, nil } diff --git a/pkg/proto/ethabi/data_types.go b/pkg/proto/ethabi/data_types.go index 3cdddc761..26a00251c 100644 --- a/pkg/proto/ethabi/data_types.go +++ b/pkg/proto/ethabi/data_types.go @@ -48,7 +48,7 @@ func (b Bool) EncodeToABI() []byte { func (s String) EncodeToABI() []byte { l := len(s) strSlots := l / abiSlotSize - if l-strSlots*abiSlotSize > 0 { // division rem + if l%abiSlotSize != 0 { // doesn't fit in strSlots strSlots += 1 // add slot } var ( diff --git a/pkg/proto/ethabi/erc20.go b/pkg/proto/ethabi/erc20.go index ea0c418bc..8696db9c6 100644 --- a/pkg/proto/ethabi/erc20.go +++ b/pkg/proto/ethabi/erc20.go @@ -8,12 +8,13 @@ const ( erc20TransferSignature Signature = "transfer(address,uint256)" EthereumAddressSize int = 20 NumberOfERC20TransferArguments int = 2 + ERC20TransferCallDataSize = SelectorSize + 2*abiSlotSize // selector + _to + _value ) var ( erc20TransferSelector = erc20TransferSignature.Selector() - erc20Methods = map[Selector]Method{ + methods = map[Selector]Method{ erc20TransferSelector: { RawName: "transfer", Inputs: Arguments{ diff --git a/pkg/proto/ethabi/function_signature.go b/pkg/proto/ethabi/function_signature.go index cb96ed0e5..2c79db940 100644 --- a/pkg/proto/ethabi/function_signature.go +++ b/pkg/proto/ethabi/function_signature.go @@ -132,7 +132,7 @@ type fixedBytesTextBuilder struct { } func (fbtb fixedBytesTextBuilder) MarshalText() (text []byte, err error) { - if fbtb.size < 1 || fbtb.size > 32 { + if fbtb.size < 1 || fbtb.size > abiSlotSize { return nil, errors.Errorf("invalid fixed bytes type size (%d)", fbtb.size) } return []byte(fmt.Sprintf("bytes%d", fbtb.size)), nil diff --git a/pkg/proto/ethabi/methods_map.go b/pkg/proto/ethabi/methods_map.go index 67b9b6fbe..3304b598c 100644 --- a/pkg/proto/ethabi/methods_map.go +++ b/pkg/proto/ethabi/methods_map.go @@ -39,7 +39,7 @@ type MethodsMap struct { func NewErc20MethodsMap() MethodsMap { return MethodsMap{ - methods: erc20Methods, + methods: methods, parsePayments: false, } } @@ -76,7 +76,7 @@ func (mm MethodsMap) MethodBySelector(id Selector) (Method, error) { return Method{}, fmt.Errorf("signature %q not found", id.String()) } -func (mm MethodsMap) ParseCallDataRide(data []byte) (*DecodedCallData, error) { +func (mm MethodsMap) ParseCallDataRide(data []byte, sanityChecksEnabled bool) (*DecodedCallData, error) { // If the data is empty, we have a plain value transfer, nothing more to do if len(data) == 0 { return nil, errors.New("transaction doesn't contain data") @@ -85,19 +85,25 @@ func (mm MethodsMap) ParseCallDataRide(data []byte) (*DecodedCallData, error) { if len(data) < SelectorSize { return nil, errors.New("transaction data is not valid ABI: missing the 4 byte call prefix") } - if n := len(data) - SelectorSize; n%32 != 0 { + if n := len(data) - SelectorSize; sanityChecksEnabled && n%abiSlotSize != 0 { return nil, errors.Errorf("transaction data is not valid ABI (length should be a multiple of 32 (was %d))", n) } - var selector Selector - copy(selector[:], data[:SelectorSize]) + selector, err := NewSelectorFromBytes(data[:SelectorSize]) + if err != nil { + return nil, errors.Wrap(err, "failed to parse selector") + } method, err := mm.MethodBySelector(selector) if err != nil { - return nil, errors.Errorf("Transaction contains data, but the ABI signature could not be found: %v", err) + return nil, errors.Errorf("transaction contains data, but the ABI signature could not be found: %v", err) } - info, err := parseArgDataToRideTypes(&method, data[SelectorSize:], mm.parsePayments) + argsData := data[SelectorSize:] + info, slotsReadTotal, err := parseArgDataToRideTypes(&method, argsData, mm.parsePayments) if err != nil { - return nil, errors.Errorf("Transaction contains data, but provided ABI signature could not be verified: %v", err) + return nil, errors.Errorf("transaction contains data, but provided ABI signature could not be verified: %v", err) + } + if readData := slotsReadTotal * abiSlotSize; sanityChecksEnabled && readData != len(argsData) { + return nil, errors.Errorf("transaction abi contains garbage data: read %d, len %d", readData, len(argsData)) } return info, nil } @@ -140,18 +146,20 @@ func (da *DecodedArg) InternalType() byte { return byte(da.Soltype.Type.T) } -func parseArgDataToRideTypes(method *Method, argData []byte, parsePayments bool) (*DecodedCallData, error) { - values, paymentsOffset, err := method.Inputs.UnpackRideValues(argData) +func parseArgDataToRideTypes(method *Method, argData []byte, parsePayments bool) (_ *DecodedCallData, slotsReadTotal int, _ error) { + values, paymentsIndex, slotsReadTotal, err := method.Inputs.UnpackRideValues(argData) if err != nil { - return nil, errors.Wrap(err, "failed to unpack Inputs arguments ABI data") + return nil, 0, errors.Wrap(err, "failed to unpack Inputs arguments ABI data") } var payments []Payment if parsePayments { - payments, err = unpackPayments(paymentsOffset, argData) + var paymentsSlotsRead int + payments, paymentsSlotsRead, err = unpackPayments(paymentsIndex, argData) if err != nil { - return nil, errors.Wrap(err, "failed to unpack payments") + return nil, 0, errors.Wrap(err, "failed to unpack payments") } + slotsReadTotal += paymentsSlotsRead } decodedInputs := make([]DecodedArg, len(method.Inputs)) @@ -164,5 +172,5 @@ func parseArgDataToRideTypes(method *Method, argData []byte, parsePayments bool) Inputs: decodedInputs, Payments: payments, } - return &decoded, nil + return &decoded, slotsReadTotal, nil } diff --git a/pkg/proto/ethabi/parsing_test.go b/pkg/proto/ethabi/parsing_test.go index c5e0ec53d..6132d44dc 100644 --- a/pkg/proto/ethabi/parsing_test.go +++ b/pkg/proto/ethabi/parsing_test.go @@ -1,6 +1,7 @@ package ethabi import ( + "bytes" "encoding/base64" "encoding/hex" "encoding/json" @@ -27,7 +28,7 @@ func TestERC20EthereumTransfer(t *testing.T) { require.NoError(t, err) erc20Db := NewErc20MethodsMap() - callData, err := erc20Db.ParseCallDataRide(data) + callData, err := erc20Db.ParseCallDataRide(data, true) require.NoError(t, err) require.Equal(t, expectedSignature, callData.Signature.String()) @@ -52,7 +53,7 @@ func TestGetERC20TransferArguments(t *testing.T) { require.NoError(t, err) erc20Db := NewErc20MethodsMap() - callData, err := erc20Db.ParseCallDataRide(data) + callData, err := erc20Db.ParseCallDataRide(data, true) require.NoError(t, err) transferArgs, err := GetERC20TransferArguments(callData) @@ -91,7 +92,7 @@ func TestRandomFunctionABIParsing(t *testing.T) { methods: customDB, parsePayments: false, } - callData, err := db.ParseCallDataRide(data) + callData, err := db.ParseCallDataRide(data, true) require.NoError(t, err) require.Equal(t, "minta", callData.Name) @@ -335,7 +336,7 @@ func TestParsingABIUsingRideMeta(t *testing.T) { db, err := newMethodsMapFromRideDAppMeta(dAppMeta, tc.parsePayments) require.NoError(t, err) - decodedCallData, err := db.ParseCallDataRide(data) + decodedCallData, err := db.ParseCallDataRide(data, true) require.NoError(t, err) values := make([]DataType, 0, len(decodedCallData.Inputs)) @@ -349,3 +350,54 @@ func TestParsingABIUsingRideMeta(t *testing.T) { } } } + +func TestMethodsMap_ParseCallDataRide_GarbageTal(t *testing.T) { + const invalidCallData = "0xa9059cbb000000000000000000000000d0ba6c90e23ffe63049fa4fff4e0c4d3ad79e83a0000000000000000000000000000000000000000000000000000000000d59f806273632c307836443230613564416543324233433531353038383631393166343744383866394266343234413031" + callData, err := hex.DecodeString(strings.TrimPrefix(invalidCallData, "0x")) + require.NoError(t, err) + mm := NewErc20MethodsMap() + + _, err = mm.ParseCallDataRide(callData, false) + require.NoError(t, err) + + _, err = mm.ParseCallDataRide(callData, true) + require.EqualError(t, err, "transaction data is not valid ABI (length should be a multiple of 32 (was 110))") +} + +func TestMethodsMap_ParseCallDataRide_GarbageMiddle(t *testing.T) { + var ( + intData = Int(21) + stringData = String(strings.Repeat("f", 42)) + fnSelector = Signature("foo(int64,string)").Selector() + ) + type slot [abiSlotSize]byte + var ( + one = (&slot{1})[:] + two = (&slot{2})[:] + slots = [][]byte{two, one, two, one, two, one, two, one, two, one, two, one} + ) + offset := Int((1 + 1 + len(slots)) * abiSlotSize).EncodeToABI() // 1 slot for intData + 1 slot for offsetItself + garbage + length := Int(len(stringData)).EncodeToABI() + stringSlots := make([]byte, abiSlotSize*slotsSizeForBytes([]byte(stringData))) + copy(stringSlots, stringData) + + callData := bytes.Join([][]byte{fnSelector[:], intData.EncodeToABI(), offset, bytes.Join(slots, nil), length, stringSlots}, nil) + + dAppMeta := meta.DApp{ + Version: 1, + Functions: []meta.Function{{Name: "foo", Arguments: []meta.Type{meta.Int, meta.String}}}, + } + + mm, err := newMethodsMapFromRideDAppMeta(dAppMeta, false) + require.NoError(t, err) + + res, err := mm.ParseCallDataRide(callData, false) + require.NoError(t, err) + require.Equal(t, "foo", res.Name) + require.Len(t, res.Inputs, 2) + require.Equal(t, intData, res.Inputs[0].Value) + require.Equal(t, stringData, res.Inputs[1].Value) + + _, err = mm.ParseCallDataRide(callData, true) + require.EqualError(t, err, "transaction abi contains garbage data: read 160, len 544") +} diff --git a/pkg/proto/ethabi/type.go b/pkg/proto/ethabi/type.go index 210ce73ee..8538fb307 100644 --- a/pkg/proto/ethabi/type.go +++ b/pkg/proto/ethabi/type.go @@ -68,11 +68,6 @@ func (t *Type) String() string { return t.stringKind } -// requiresLengthPrefix returns whether the type requires any sort of length prefixing. -func requiresLengthPrefix(t Type) bool { - return t.T == StringType || t.T == BytesType || t.T == SliceType -} - // getTypeSize returns the size that this type needs to occupy. // We distinguish static and dynamic types. Static types are encoded in-place // and dynamic types are encoded at a separately allocated location after the diff --git a/pkg/proto/ethabi/unpack.go b/pkg/proto/ethabi/unpack.go index 8abf5743c..d28e58e28 100644 --- a/pkg/proto/ethabi/unpack.go +++ b/pkg/proto/ethabi/unpack.go @@ -17,12 +17,12 @@ var ( // readBool reads a bool. func readBool(word []byte) (bool, error) { - for _, b := range word[:31] { + for _, b := range word[:abiSlotSize-1] { if b != 0 { return false, errors.New("abi: improperly encoded boolean value") } } - switch word[31] { + switch word[abiSlotSize-1] { case 0: return false, nil case 1: @@ -88,20 +88,19 @@ func tryAsInt64(dataT DataType) (int64, error) { } // forEachUnpack iteratively unpack elements. -func forEachUnpackRideList(t Type, output []byte, start, size int) (List, error) { - if size < 0 { - return nil, errors.Errorf("cannot marshal input to array, size is negative (%d)", size) +func forEachUnpackRideList(t Type, output []byte, start, size int) (_ List, slotsReadTotal int, err error) { + if t.T != SliceType { // here we can only handle slice type + return nil, 0, errors.Errorf("abi: invalid type in slice unpacking stage") } - if start+32*size > len(output) { - return nil, errors.Errorf( + if size < 0 { // size is positive + return nil, 0, errors.Errorf("cannot marshal input to array, size is negative (%d)", size) + } + if start+abiSlotSize*size > len(output) { // check that we can read size slots + return nil, 0, errors.Errorf( "abi: cannot marshal in to go array: offset %d would go over slice boundary (len=%d)", - len(output), start+32*size, + len(output), start+abiSlotSize*size, ) } - if t.T != SliceType { - return nil, errors.Errorf("abi: invalid type in slice unpacking stage") - - } // this value will become our slice or our array, depending on the type slice := make(List, 0, size) @@ -111,64 +110,72 @@ func forEachUnpackRideList(t Type, output []byte, start, size int) (List, error) elemSize := getTypeSize(*t.Elem) for i, j := start, 0; j < size; i, j = i+elemSize, j+1 { - inter, err := toDataType(i, *t.Elem, output) + inter, slotsRead, err := toDataType(i, *t.Elem, output) if err != nil { - return nil, err + return nil, 0, err } slice = append(slice, inter) + slotsReadTotal += slotsRead } - return slice, nil + return slice, slotsReadTotal, nil } -func extractIndexFromFirstElemOfTuple(index int, t Type, output []byte) (int64, error) { +func extractIndexFromFirstElemOfTuple(index int, t Type, output []byte) (_ int64, slotsRead int, _ error) { if t.T != IntType && t.T != UintType { - return 0, errors.New( + return 0, 0, errors.New( "abi: failed to convert eth tuple to ride union, first element of eth tuple must be a number", ) } - rideT, err := toDataType(index, t, output) + rideT, slotsRead, err := toDataType(index, t, output) if err != nil { - return 0, err + return 0, 0, err } - return tryAsInt64(rideT) + idx, err := tryAsInt64(rideT) + if err != nil { + return 0, 0, err + } + return idx, slotsRead, nil } -func forUnionTupleUnpackToDataType(t Type, output []byte) (DataType, error) { - if t.T != TupleType { - return nil, errors.New("abi: type in forTupleUnpack must be TupleTy") +func forUnionTupleUnpackToDataType(t Type, output []byte) (_ DataType, slotsReadTotal int, _ error) { + if t.T != TupleType { // here we can only handle slice type + return nil, 0, errors.New("abi: type in forTupleUnpack must be TupleTy") } - if len(t.TupleFields) < 2 { - return nil, errors.New( + if len(t.TupleFields) < 2 { // tuple is reasonable + return nil, 0, errors.New( "abi: failed to convert eth tuple to ride union, elements count of eth tuple must greater than 2", ) } - unionIndex, err := extractIndexFromFirstElemOfTuple(0, t.TupleFields[0].Type, output) + // first slot is an index with necessary and present value + unionIndex, slotsRead, err := extractIndexFromFirstElemOfTuple(0, t.TupleFields[0].Type, output) if err != nil { - return nil, err + return nil, 0, err } - fields := t.TupleFields[1:] - if unionIndex >= int64(len(fields)) { - return nil, errors.Errorf( + slotsReadTotal += slotsRead + + fields := t.TupleFields[1:] // first slot is an index, other slots are slots with field values + if unionIndex >= int64(len(fields)) { // check that index is correct, i.e. we don't violate fields slice boundaries + return nil, 0, errors.Errorf( "abi: failed to convert eth tuple to ride union, union index (%d) greater than tuple fields count (%d)", unionIndex, len(fields), ) } retval := make([]DataType, 0, len(fields)) virtualArgs := 0 - for index := 1; index < len(fields); index++ { + for index := 1; index < len(fields); index++ { // start with 1 because we've already read first slot field := fields[index] - marshalledValue, err := toDataType((index+virtualArgs)*32, field.Type, output) + marshalledValue, slotsRead, err := toDataType((index+virtualArgs)*abiSlotSize, field.Type, output) if err != nil { - return nil, err + return nil, 0, err } if field.Type.T == TupleType && !isDynamicType(field.Type) { - - virtualArgs += getTypeSize(field.Type)/32 - 1 + virtualArgs += getTypeSize(field.Type)/abiSlotSize - 1 } retval = append(retval, marshalledValue) + slotsReadTotal += slotsRead } - return retval[unionIndex], nil + return retval[unionIndex], slotsReadTotal, nil } // readFixedBytes creates a Bytes with length 1..32 to be read from. @@ -178,10 +185,10 @@ func readFixedBytes(t Type, word []byte) (Bytes, error) { return nil, errors.Errorf("abi: invalid type in call to make fixed byte array") } // size check - if t.Size < 1 || t.Size > 32 { + if t.Size < 1 || t.Size > abiSlotSize { return nil, errors.Errorf( - "abi: invalid type size in call to make fixed byte array, want 0 < size <= 32, actual size=%d", - t.Size, + "abi: invalid type size in call to make fixed byte array, want 0 < size <= %d, actual size=%d", + abiSlotSize, t.Size, ) } array := word[0:t.Size] @@ -212,14 +219,15 @@ var ( } ) -func unpackPayment(output []byte) (Payment, error) { +func unpackPayment(output []byte) (_ Payment, slotsReadTotal int, _ error) { assetIDType := paymentType.TupleFields[0].Type amountType := paymentType.TupleFields[1].Type - assetRideValue, err := toDataType(0, assetIDType, output) + assetRideValue, slotsRead, err := toDataType(0, assetIDType, output) if err != nil { - return Payment{}, errors.Wrap(err, "failed to decode payment, failed to parse fullAssetID") + return Payment{}, 0, errors.Wrap(err, "failed to decode payment, failed to parse fullAssetID") } + slotsReadTotal += slotsRead fullAssetIDBytes, ok := assetRideValue.(Bytes) if !ok { @@ -227,16 +235,22 @@ func unpackPayment(output []byte) (Payment, error) { } fullAssetID, err := crypto.NewDigestFromBytes(fullAssetIDBytes) if err != nil { - return Payment{}, errors.Wrapf(err, "abi: failed extract asset from bytes") + return Payment{}, 0, errors.Wrapf(err, "abi: failed extract asset from bytes") } - amountRideValue, err := toDataType(getTypeSize(assetIDType), amountType, output) + amountRideValue, slotsRead, err := toDataType(getTypeSize(assetIDType), amountType, output) if err != nil { - return Payment{}, errors.Wrap(err, "failed to decode payment, failed to parse amount") + return Payment{}, 0, errors.Wrap(err, "failed to decode payment, failed to parse amount") } + slotsReadTotal += slotsRead + amount, err := tryAsInt64(amountRideValue) if err != nil { - return Payment{}, errors.Wrapf(err, "failed to parse payment, amountRideValue type MUST be representable as int64") + return Payment{}, 0, errors.Wrapf(err, + "failed to parse payment, amountRideValue type MUST be representable as int64") + } + if amount < 0 { + return Payment{}, 0, errors.New("negative payment amount") } payment := Payment{ @@ -244,163 +258,200 @@ func unpackPayment(output []byte) (Payment, error) { AssetID: fullAssetID, Amount: amount, } - return payment, nil + return payment, slotsReadTotal, nil } // unpackPayments unpacks payments from call data without selector -func unpackPayments(paymentsSliceOffset int, output []byte) ([]Payment, error) { +func unpackPayments(paymentsSliceIndex int, output []byte) (_ []Payment, slotsReadTotal int, _ error) { if len(output) == 0 { - return nil, errors.Errorf("empty payments bytes") + return nil, 0, errors.Errorf("empty payments bytes") } - begin, size, err := lengthPrefixPointsTo(paymentsSliceOffset, output) + begin, size, slotsRead, err := lengthPrefixPointsTo(paymentsSliceIndex, output) if err != nil { - return nil, err + return nil, 0, errors.Wrap(err, "failed to read offset and length") } - // jumping to the data section - output = output[begin:] + output = output[begin:] // jumping to the data section + slotsReadTotal += slotsRead // count offset and length slots - if size < 0 { - return nil, errors.Errorf("cannot marshal input to array, size is negative (%d)", size) + if size < 0 { // size is positive + return nil, 0, errors.Errorf("cannot marshal input to array, size is negative (%d)", size) } - if 32*size > len(output) { - return nil, errors.Errorf( + if abiSlotSize*size > len(output) { // check that we don't violate slice boundaries + return nil, 0, errors.Errorf( "abi: cannot marshal in to go array: offset %d would go over slice boundary (len=%d)", - len(output), 32*size, + len(output), abiSlotSize*size, ) } - elemSize := getTypeSize(*paymentsType.Elem) + elemSize := getTypeSize(*paymentsType.Elem) // we know that elem size here is fixed (and equal 32) payments := make([]Payment, 0, size) for i := 0; i < size; i++ { - payment, err := unpackPayment(output[i*elemSize:]) + payment, slotsRead, err := unpackPayment(output[i*elemSize:]) if err != nil { - return nil, errors.Wrap(err, "failed to unpack payment") + return nil, 0, errors.Wrap(err, "failed to unpack payment") } payments = append(payments, payment) + slotsReadTotal += slotsRead } - return payments, nil + return payments, slotsReadTotal, nil } // lengthPrefixPointsTo interprets a 32 byte slice as an offset and then determines which indices to look to decode the type. -func lengthPrefixPointsTo(index int, output []byte) (start int, length int, err error) { - bigOffsetBytes := output[index : index+32] +func lengthPrefixPointsTo(index int, output []byte) (start, length, slotsReadTotal int, err error) { + // read offset bytes + bigOffsetBytes := output[index : index+abiSlotSize] bigOffsetEnd := new(big.Int).SetBytes(bigOffsetBytes) + // validate offset bytes bigOffsetEnd.Add(bigOffsetEnd, big32) outputLength := new(big.Int).SetUint64(uint64(len(output))) if bigOffsetEnd.Cmp(outputLength) > 0 { - return 0, 0, errors.Errorf( + return 0, 0, 0, errors.Errorf( "abi: cannot marshal in to go slice: offset %v would go over slice boundary (len=%v)", bigOffsetEnd, outputLength, ) } if bigOffsetEnd.BitLen() > 63 { - return 0, 0, errors.Errorf("abi offset larger than int64: %v", bigOffsetEnd) + return 0, 0, 0, errors.Errorf("abi offset larger than int64: %v", bigOffsetEnd) } - offsetEnd := bigOffsetEnd.Uint64() - lengthBig := new(big.Int).SetBytes(output[offsetEnd-32 : offsetEnd]) - totalSize := big.NewInt(0) - totalSize.Add(totalSize, bigOffsetEnd) - totalSize.Add(totalSize, lengthBig) - if totalSize.BitLen() > 63 { - return 0, 0, errors.Errorf("abi: length larger than int64: %v", totalSize) + // read length + bigLengthBytes := output[offsetEnd-abiSlotSize : offsetEnd] + lengthBig := new(big.Int).SetBytes(bigLengthBytes) + + //validate length + totalSize := big.NewInt(0) // init with sero + totalSize.Add(totalSize, bigOffsetEnd) // add offset + totalSize.Add(totalSize, lengthBig) // add length + if totalSize.BitLen() > 63 { // compare whether it's int64 or not + return 0, 0, 0, errors.Errorf("abi: length larger than int64: %v", totalSize) } - if totalSize.Cmp(outputLength) > 0 { - return 0, 0, errors.Errorf( + if totalSize.Cmp(outputLength) > 0 { // now compare it with output length, check bounds os slice + return 0, 0, 0, errors.Errorf( "abi: cannot marshal in to go type: length insufficient %v require %v", outputLength, totalSize, ) } - start = int(bigOffsetEnd.Uint64()) - length = int(lengthBig.Uint64()) - return + start = int(bigOffsetEnd.Uint64()) // count first slot + length = int(lengthBig.Uint64()) // count second slot + return start, length, 2, nil } // tuplePointsTo resolves the location reference for dynamic tuple. -func tuplePointsTo(index int, output []byte) (start int, err error) { - offset := new(big.Int).SetBytes(output[index : index+32]) +func tuplePointsTo(index int, output []byte) (start int, slotsReadTotal int, err error) { + offset := new(big.Int).SetBytes(output[index : index+abiSlotSize]) // read exactly one slot outputLen := big.NewInt(int64(len(output))) - if offset.Cmp(big.NewInt(int64(len(output)))) > 0 { - return 0, errors.Errorf( + if offset.Cmp(outputLen) > 0 { + return 0, 0, errors.Errorf( "abi: cannot marshal in to go slice: offset %v would go over slice boundary (len=%v)", offset, outputLen, ) } if offset.BitLen() > 63 { - return 0, errors.Errorf("abi offset larger than int64: %v", offset) + return 0, 0, errors.Errorf("abi offset larger than int64: %v", offset) } - return int(offset.Uint64()), nil + return int(offset.Uint64()), 1, nil } -func toDataType(index int, t Type, output []byte) (DataType, error) { - if index+32 > len(output) { - return nil, errors.Errorf("abi: cannot marshal in to go type: length insufficient %d require %d", - len(output), index+32, - ) +func slotsSizeForBytes(b []byte) int { + l := len(b) + size := l / abiSlotSize + if l%abiSlotSize != 0 { // doesn't fit in slots + size += 1 // add slot } + return size // slots size for data +} - var ( - returnOutput []byte - begin, length int - err error - ) - - // if we require a length prefix, find the beginning word and size returned. - if requiresLengthPrefix(t) { - begin, length, err = lengthPrefixPointsTo(index, output) - if err != nil { - return nil, err - } - } else { - returnOutput = output[index : index+32] +func toDataType(index int, t Type, output []byte) (_ DataType, slotsReadTotal int, _ error) { + if l := len(output); index+abiSlotSize > l { // check that we can read at least one slot + return nil, 0, errors.Errorf("abi: cannot marshal in to go type: length insufficient %d require %d", + l, index+abiSlotSize, + ) } switch t.T { case TupleType: if isDynamicType(t) { - begin, err := tuplePointsTo(index, output) + begin, slotsRead, err := tuplePointsTo(index, output) // read offset for dynamic tuple if err != nil { - return nil, err + return nil, 0, err } - return forUnionTupleUnpackToDataType(t, output[begin:]) + slotsReadTotal += slotsRead // count offset slot + union, slotsRead, err := forUnionTupleUnpackToDataType(t, output[begin:]) + if err != nil { + return nil, 0, err + } + slotsReadTotal += slotsRead // count data slots + return union, slotsReadTotal, nil } return forUnionTupleUnpackToDataType(t, output[index:]) case SliceType: - return forEachUnpackRideList(t, output[begin:], 0, length) + begin, length, slotsRead, err := lengthPrefixPointsTo(index, output) + if err != nil { + return nil, 0, err + } + slotsReadTotal += slotsRead // count offset and length slots + list, slotsRead, err := forEachUnpackRideList(t, output[begin:], 0, length) + if err != nil { + return nil, 0, err + } + slotsReadTotal += slotsRead // count data slots + return list, slotsReadTotal, err case StringType: // variable arrays are written at the end of the return bytes - return String(output[begin : begin+length]), nil + begin, length, slotsRead, err := lengthPrefixPointsTo(index, output) + if err != nil { + return nil, 0, err + } + slotsReadTotal += slotsRead // count offset and length slots + s := output[begin : begin+length] + slotsReadTotal += slotsSizeForBytes(s) // count data slots + return String(s), slotsReadTotal, nil + case BytesType: + begin, length, slotsRead, err := lengthPrefixPointsTo(index, output) + if err != nil { + return nil, 0, err + } + slotsReadTotal += slotsRead // count offset and length slots + s := output[begin : begin+length] + slotsReadTotal += slotsSizeForBytes(s) // count data slots + return Bytes(output[begin : begin+length]), slotsReadTotal, nil case IntType, UintType: - return readInteger(t, returnOutput), nil + slot := output[index : index+abiSlotSize] // read exactly one slot for simple types + slotsReadTotal += 1 + return readInteger(t, slot), slotsReadTotal, nil case BoolType: - boolean, err := readBool(returnOutput) + slot := output[index : index+abiSlotSize] // read exactly one slot for simple types + slotsReadTotal += 1 + boolean, err := readBool(slot) if err != nil { - return nil, err + return nil, 0, err } - return Bool(boolean), nil + return Bool(boolean), slotsReadTotal, nil case AddressType: - if len(returnOutput) == 0 { - return nil, errors.Errorf( + slot := output[index : index+abiSlotSize] // read exactly one slot for simple types + slotsReadTotal += 1 + if len(slot) == 0 { + return nil, 0, errors.Errorf( "invalid etherum address size, expected %d, actual %d", - EthereumAddressSize, len(returnOutput), + EthereumAddressSize, len(slot), ) } - return Bytes(returnOutput[len(returnOutput)-EthereumAddressSize:]), nil - case BytesType: - return Bytes(output[begin : begin+length]), nil + return Bytes(slot[len(slot)-EthereumAddressSize:]), slotsReadTotal, nil case FixedBytesType: - fixedBytes, err := readFixedBytes(t, returnOutput) + slot := output[index : index+abiSlotSize] // read exactly one slot for simple types + slotsReadTotal += 1 + fixedBytes, err := readFixedBytes(t, slot) if err != nil { - return nil, err + return nil, 0, err } - return fixedBytes, err + return fixedBytes, slotsReadTotal, err default: - return nil, errors.Errorf("abi: unknown type %v", t.T) + return nil, 0, errors.Errorf("abi: unknown type %v", t.T) } } diff --git a/pkg/ride/converters.go b/pkg/ride/converters.go index 72c4cd892..9442a20a8 100644 --- a/pkg/ride/converters.go +++ b/pkg/ride/converters.go @@ -6,7 +6,6 @@ import ( "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" - "github.com/wavesplatform/gowaves/pkg/proto/ethabi" "github.com/wavesplatform/gowaves/pkg/ride/ast" "github.com/wavesplatform/gowaves/pkg/util/common" ) @@ -893,51 +892,6 @@ func invokeExpressionWithProofsToObject(scheme byte, tx *proto.InvokeExpressionT ), nil } -func ConvertEthereumRideArgumentsToSpecificArgument(decodedArg rideType) (proto.Argument, error) { - var arg proto.Argument - switch m := decodedArg.(type) { - case rideInt: - arg = &proto.IntegerArgument{Value: int64(m)} - case rideBoolean: - arg = &proto.BooleanArgument{Value: bool(m)} - case rideByteVector: - arg = &proto.BinaryArgument{Value: m} - case rideString: - arg = &proto.StringArgument{Value: string(m)} - case rideList: - var miniArgs proto.Arguments - for _, v := range m { - a, err := ConvertEthereumRideArgumentsToSpecificArgument(v) - if err != nil { - return nil, err - } - miniArgs = append(miniArgs, a) - } - arg = &proto.ListArgument{Items: miniArgs} - default: - return nil, EvaluationFailure.New("unknown argument type") - } - - return arg, nil -} - -func ConvertDecodedEthereumArgumentsToProtoArguments(decodedArgs []ethabi.DecodedArg) ([]proto.Argument, error) { - var arguments []proto.Argument - for _, decodedArg := range decodedArgs { - value, err := ethABIDataTypeToRideType(decodedArg.Value) - if err != nil { - return nil, EvaluationFailure.Errorf("failed to convert data type to ride type %v", err) - } - arg, err := ConvertEthereumRideArgumentsToSpecificArgument(value) - if err != nil { - return nil, err - } - arguments = append(arguments, arg) - - } - return arguments, nil -} - func ethereumTransactionToObject(ver ast.LibraryVersion, scheme proto.Scheme, tx *proto.EthereumTransaction) (rideType, error) { sender, err := tx.WavesAddressFrom(scheme) if err != nil { @@ -1009,17 +963,13 @@ func ethereumTransactionToObject(ver ast.LibraryVersion, scheme proto.Scheme, tx payment := proto.ScriptPayment{Amount: uint64(p.Amount), Asset: optAsset} scriptPayments = append(scriptPayments, payment) } - arguments, err := ConvertDecodedEthereumArgumentsToProtoArguments(tx.TxKind.DecodedData().Inputs) + arguments, err := proto.ConvertDecodedEthereumArgumentsToProtoArguments(tx.TxKind.DecodedData().Inputs) if err != nil { return nil, errors.Errorf("failed to convert ethereum arguments, %v", err) } - args := make(rideList, len(arguments)) - for i, arg := range arguments { - a, err := convertArgument(arg) - if err != nil { - return nil, errors.Wrap(err, "invokeScriptWithProofsToObject") - } - args[i] = a + args, err := convertProtoArguments(arguments) + if err != nil { + return nil, errors.Wrap(err, "invokeScriptWithProofsToObject") } switch ver { case ast.LibV1, ast.LibV2, ast.LibV3: diff --git a/pkg/ride/converters_test.go b/pkg/ride/converters_test.go index 16d27c7d1..82fd0b477 100644 --- a/pkg/ride/converters_test.go +++ b/pkg/ride/converters_test.go @@ -3238,7 +3238,7 @@ func TestEthereumTransferAssetsTransformTxToRideObj(t *testing.T) { tx := proto.NewEthereumTransaction(txData, nil, &crypto.Digest{}, &senderPK, 0) db := ethabi.NewErc20MethodsMap() assert.NotNil(t, tx.Data()) - decodedData, err := db.ParseCallDataRide(tx.Data()) + decodedData, err := db.ParseCallDataRide(tx.Data(), true) assert.NoError(t, err) makeLessDataAmount(t, decodedData) diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index 10de117f8..6e165451d 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -391,6 +391,7 @@ func (ws *WrappedState) validateAsset(action proto.ScriptAction, asset proto.Opt env.blockV5Activated(), env.rideV6Activated(), env.consensusImprovementsActivated(), + env.blockRewardDistributionActivated(), env.invokeExpressionActivated(), ) if err != nil { @@ -739,8 +740,14 @@ func (ws *WrappedState) ApplyToState( Scheme: ws.scheme, ScriptAddress: ws.callee(), } + var libVersion ast.LibraryVersion + if env.blockRewardDistributionActivated() { + libVersion = ws.rootScriptLibVersion + } else { + libVersion = currentLibVersion + } if len(actions) == 0 { - if err := ws.rootActionsCountValidator.ValidateCounts(currentLibVersion, env.rideV6Activated()); err != nil { + if err := ws.rootActionsCountValidator.ValidateCounts(libVersion, env.rideV6Activated()); err != nil { return nil, errors.Wrap(err, "failed to validate total actions count") } } @@ -748,7 +755,7 @@ func (ws *WrappedState) ApplyToState( if err := localActionsCountValidator.CountAction(action, currentLibVersion, env.rideV6Activated()); err != nil { return nil, errors.Wrap(err, "failed to validate local actions count") } - if err := ws.countActionTotal(action, currentLibVersion, env.rideV6Activated()); err != nil { + if err := ws.countActionTotal(action, libVersion, env.rideV6Activated()); err != nil { return nil, errors.Wrap(err, "failed to validate total actions count") } switch a := action.(type) { @@ -988,26 +995,27 @@ func (ws *WrappedState) ApplyToState( } type EvaluationEnvironment struct { - sch proto.Scheme - st types.SmartState - h rideInt - tx rideType - id rideType - th rideType - time uint64 - b rideType - check func(int) bool - takeStr func(s string, n int) rideString - inv rideType - ver ast.LibraryVersion - validatePaymentsAfter uint64 - isBlockV5Activated bool - isRideV6Activated bool - isConsensusImprovementsActivated bool // isConsensusImprovementsActivated => nodeVersion >= 1.4.12 - isInvokeExpressionActivated bool // isInvokeExpressionActivated => nodeVersion >= 1.5.0 - isProtobufTransaction bool - mds int - cc complexityCalculator + sch proto.Scheme + st types.SmartState + h rideInt + tx rideType + id rideType + th rideType + time uint64 + b rideType + check func(int) bool + takeStr func(s string, n int) rideString + inv rideType + ver ast.LibraryVersion + validatePaymentsAfter uint64 + isBlockV5Activated bool + isRideV6Activated bool + isConsensusImprovementsActivated bool // isConsensusImprovementsActivated => nodeVersion >= 1.4.12 + isBlockRewardDistributionActivated bool // isBlockRewardDistributionActivated => nodeVersion >= 1.4.16 + isInvokeExpressionActivated bool // isInvokeExpressionActivated => nodeVersion >= 1.5.0 + isProtobufTransaction bool + mds int + cc complexityCalculator } func bytesSizeCheckV1V2(l int) bool { @@ -1019,24 +1027,25 @@ func bytesSizeCheckV3V6(l int) bool { } func NewEnvironment(scheme proto.Scheme, state types.SmartState, internalPaymentsValidationHeight uint64, - blockV5, rideV6, consensusImprovements, invokeExpression bool, + blockV5, rideV6, consensusImprovements, blockRewardDistribution, invokeExpression bool, ) (*EvaluationEnvironment, error) { height, err := state.AddingBlockHeight() if err != nil { return nil, err } return &EvaluationEnvironment{ - sch: scheme, - st: state, - h: rideInt(height), - check: bytesSizeCheckV1V2, // By default almost unlimited - takeStr: func(s string, n int) rideString { panic("function 'takeStr' was not initialized") }, - validatePaymentsAfter: internalPaymentsValidationHeight, - isBlockV5Activated: blockV5, - isRideV6Activated: rideV6, - isInvokeExpressionActivated: invokeExpression, - isConsensusImprovementsActivated: consensusImprovements, - cc: newComplexityCalculatorByRideV6Activation(rideV6), + sch: scheme, + st: state, + h: rideInt(height), + check: bytesSizeCheckV1V2, // By default almost unlimited + takeStr: func(s string, n int) rideString { panic("function 'takeStr' was not initialized") }, + validatePaymentsAfter: internalPaymentsValidationHeight, + isBlockV5Activated: blockV5, + isRideV6Activated: rideV6, + isBlockRewardDistributionActivated: blockRewardDistribution, + isInvokeExpressionActivated: invokeExpression, + isConsensusImprovementsActivated: consensusImprovements, + cc: newComplexityCalculatorByRideV6Activation(rideV6), }, nil } @@ -1098,6 +1107,10 @@ func (e *EvaluationEnvironment) consensusImprovementsActivated() bool { return e.isConsensusImprovementsActivated } +func (e *EvaluationEnvironment) blockRewardDistributionActivated() bool { + return e.isBlockRewardDistributionActivated +} + func (e *EvaluationEnvironment) invokeExpressionActivated() bool { return e.isInvokeExpressionActivated } diff --git a/pkg/ride/ethabi.go b/pkg/ride/ethabi.go deleted file mode 100644 index 79d43b3ce..000000000 --- a/pkg/ride/ethabi.go +++ /dev/null @@ -1,40 +0,0 @@ -package ride - -import ( - "github.com/pkg/errors" - "github.com/wavesplatform/gowaves/pkg/proto/ethabi" -) - -// ethABIDataTypeToRideType perform conversion of ethabi.DataType to rideType. -// Note that this function doesn't copy ethabi.Bytes and ethabi.BigInt. It only copies a pointer to type. -func ethABIDataTypeToRideType(dataType ethabi.DataType) (rideType rideType, err error) { - switch t := dataType.(type) { - case ethabi.Int: - rideType = rideInt(t) - case ethabi.BigInt: - rideType = rideBigInt{v: t.V} - case ethabi.Bool: - rideType = rideBoolean(t) - case ethabi.Bytes: - rideType = rideByteVector(t) - case ethabi.String: - rideType = rideString(t) - case ethabi.List: - rideList := make(rideList, len(t)) - for i, ethABIElem := range t { - rideElem, err := ethABIDataTypeToRideType(ethABIElem) - if err != nil { - return nil, errors.Wrapf(err, - "failed to convert ethabi.DataType (%T) to rideType at %d list postition", ethABIElem, i, - ) - } - rideList[i] = rideElem - } - rideType = rideList - default: - return nil, errors.Errorf( - "ethabi.DataType (%T) to RIdeType converstion doesn't supported", dataType, - ) - } - return rideType, nil -} diff --git a/pkg/ride/ethabi_test.go b/pkg/ride/ethabi_test.go deleted file mode 100644 index f05090dde..000000000 --- a/pkg/ride/ethabi_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package ride - -import ( - "math/big" - "testing" - - "github.com/stretchr/testify/require" - "github.com/wavesplatform/gowaves/pkg/proto/ethabi" -) - -func TestEthABIDataTypeToRideType(t *testing.T) { - hugeInt, ok := new(big.Int).SetString("123454323456434285767546723400991456870502323864587234659828639850098161345465903596567", 10) - require.True(t, ok) - - tests := []struct { - inputDataType ethabi.DataType - expectedRideType rideType - }{ - {ethabi.Int(5345345), rideInt(5345345)}, - {ethabi.BigInt{V: hugeInt}, rideBigInt{v: hugeInt}}, - {ethabi.Bool(true), rideBoolean(true)}, - {ethabi.Bool(false), rideBoolean(false)}, - {ethabi.Bytes("#This is Test bytes!"), rideByteVector("#This is Test bytes!")}, - {ethabi.String("This is @ Test string!"), rideString("This is @ Test string!")}, - { - inputDataType: ethabi.List{ - ethabi.Int(453), - ethabi.Bool(true), - ethabi.String("the best test string ever!"), - ethabi.Bytes("command and conquer!"), - ethabi.BigInt{V: big.NewInt(1232347)}, - ethabi.List{ - ethabi.Bytes("one more"), - ethabi.Bool(false), - }, - }, - expectedRideType: rideList{ - rideInt(453), - rideBoolean(true), - rideString("the best test string ever!"), - rideByteVector("command and conquer!"), - rideBigInt{v: big.NewInt(1232347)}, - rideList{ - rideByteVector("one more"), - rideBoolean(false), - }, - }, - }, - } - for _, tc := range tests { - actualRideType, err := ethABIDataTypeToRideType(tc.inputDataType) - require.NoError(t, err) - require.Equal(t, tc.expectedRideType, actualRideType) - } -} diff --git a/pkg/ride/runtime.go b/pkg/ride/runtime.go index a6f2e4311..c9342d500 100644 --- a/pkg/ride/runtime.go +++ b/pkg/ride/runtime.go @@ -431,6 +431,7 @@ type environment interface { blockV5Activated() bool rideV6Activated() bool consensusImprovementsActivated() bool + blockRewardDistributionActivated() bool invokeExpressionActivated() bool // TODO: check naming internalPaymentsValidationHeight() uint64 maxDataEntriesSize() int diff --git a/pkg/ride/runtime_moq_test.go b/pkg/ride/runtime_moq_test.go index dc28cc630..044bb01db 100644 --- a/pkg/ride/runtime_moq_test.go +++ b/pkg/ride/runtime_moq_test.go @@ -23,6 +23,9 @@ var _ environment = &mockRideEnvironment{} // blockFunc: func() rideType { // panic("mock out the block method") // }, +// blockRewardDistributionActivatedFunc: func() bool { +// panic("mock out the blockRewardDistributionActivated method") +// }, // blockV5ActivatedFunc: func() bool { // panic("mock out the blockV5Activated method") // }, @@ -102,6 +105,9 @@ type mockRideEnvironment struct { // blockFunc mocks the block method. blockFunc func() rideType + // blockRewardDistributionActivatedFunc mocks the blockRewardDistributionActivated method. + blockRewardDistributionActivatedFunc func() bool + // blockV5ActivatedFunc mocks the blockV5Activated method. blockV5ActivatedFunc func() bool @@ -176,6 +182,9 @@ type mockRideEnvironment struct { // block holds details about calls to the block method. block []struct { } + // blockRewardDistributionActivated holds details about calls to the blockRewardDistributionActivated method. + blockRewardDistributionActivated []struct { + } // blockV5Activated holds details about calls to the blockV5Activated method. blockV5Activated []struct { } @@ -259,6 +268,7 @@ type mockRideEnvironment struct { } } lockblock sync.RWMutex + lockblockRewardDistributionActivated sync.RWMutex lockblockV5Activated sync.RWMutex lockcheckMessageLength sync.RWMutex lockcomplexityCalculator sync.RWMutex @@ -311,6 +321,33 @@ func (mock *mockRideEnvironment) blockCalls() []struct { return calls } +// blockRewardDistributionActivated calls blockRewardDistributionActivatedFunc. +func (mock *mockRideEnvironment) blockRewardDistributionActivated() bool { + if mock.blockRewardDistributionActivatedFunc == nil { + panic("mockRideEnvironment.blockRewardDistributionActivatedFunc: method is nil but environment.blockRewardDistributionActivated was just called") + } + callInfo := struct { + }{} + mock.lockblockRewardDistributionActivated.Lock() + mock.calls.blockRewardDistributionActivated = append(mock.calls.blockRewardDistributionActivated, callInfo) + mock.lockblockRewardDistributionActivated.Unlock() + return mock.blockRewardDistributionActivatedFunc() +} + +// blockRewardDistributionActivatedCalls gets all the calls that were made to blockRewardDistributionActivated. +// Check the length with: +// +// len(mockedenvironment.blockRewardDistributionActivatedCalls()) +func (mock *mockRideEnvironment) blockRewardDistributionActivatedCalls() []struct { +} { + var calls []struct { + } + mock.lockblockRewardDistributionActivated.RLock() + calls = mock.calls.blockRewardDistributionActivated + mock.lockblockRewardDistributionActivated.RUnlock() + return calls +} + // blockV5Activated calls blockV5ActivatedFunc. func (mock *mockRideEnvironment) blockV5Activated() bool { if mock.blockV5ActivatedFunc == nil { diff --git a/pkg/ride/test_helpers_test.go b/pkg/ride/test_helpers_test.go index 074ddc145..ecccd32db 100644 --- a/pkg/ride/test_helpers_test.go +++ b/pkg/ride/test_helpers_test.go @@ -139,6 +139,9 @@ func newTestEnv(t *testing.T) *testEnv { consensusImprovementsActivatedFunc: func() bool { return false }, + blockRewardDistributionActivatedFunc: func() bool { + return false + }, invokeExpressionActivatedFunc: func() bool { return false }, @@ -411,6 +414,13 @@ func (e *testEnv) withRideV6Activated() *testEnv { return e } +func (e *testEnv) withBlockRewardDistribution() *testEnv { + e.me.blockRewardDistributionActivatedFunc = func() bool { + return true + } + return e +} + func (e *testEnv) withInvokeExpressionActivated() *testEnv { e.me.invokeExpressionActivatedFunc = func() bool { return true diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index 15cff4859..a54e781a0 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -5015,6 +5015,170 @@ func TestInvokeDappAttachedPaymentsLimitAfterV6(t *testing.T) { require.EqualError(t, err, "reentrantInvoke: failed to apply attached payments: failed to validate total actions count: number of attached payments (101) produced by script is more than allowed 100") } +func TestInvokeActionsCountRestrictionsV6ToV5WithBlockRewardDistribution(t *testing.T) { + dApp1 := newTestAccount(t, "DAPP1") // 3MzDtgL5yw73C2xVLnLJCrT5gCL4357a4sz + dApp2 := newTestAccount(t, "DAPP2") // 3N7Te7NXtGVoQqFqktwrFhQWAkc6J8vfPQ1 + dApp3 := newTestAccount(t, "DAPP3") // 3N186hYM5PFwGdkVUsLJaBvpPEECrSj5CJh + sender := newTestAccount(t, "SENDER") // 3N8CkZAyS4XcDoJTJoKNuNk2xmNKmQj7myW + + /* On dApp1 address + {-# STDLIB_VERSION 6 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + let dApp2 = Address(base58'3N7Te7NXtGVoQqFqktwrFhQWAkc6J8vfPQ1') # V6 script produces 10 transfer actions + let dApp3 = Address(base58'3N186hYM5PFwGdkVUsLJaBvpPEECrSj5CJh') # V5 script produces no actions + + @Callable(i) + func call() = { + strict a1 = invoke(dApp2, "call", [], []) # 10 actions + strict b1 = invoke(dApp3, "call", [], []) # check V5 - OK + strict a2 = invoke(dApp2, "call", [], []) # 20 actions + strict b2 = invoke(dApp3, "call", [], []) # check V5 - OK + strict a3 = invoke(dApp2, "call", [], []) # 30 actions + strict b3 = invoke(dApp3, "call", [], []) # check V5 - OK + strict a4 = invoke(dApp2, "call", [], []) # 40 actions + strict b4 = invoke(dApp3, "call", [], []) # check V5 - OK + [] + } + */ + _, tree1 := parseBase64Script(t, "BgIECAISAAIABWRBcHAyCQEHQWRkcmVzcwEBGgFUwHIGfTfL6MC+bgzmzz/fWbF5GHfdVq+uAAVkQXBwMwkBB0FkZHJlc3MBARoBVHrvJZrEY3NpLnBpk6ugJuX5CI8UJdzjLgEBaQEEY2FsbAAEAmExCQD8BwQFBWRBcHAyAgRjYWxsBQNuaWwFA25pbAMJAAACBQJhMQUCYTEEAmIxCQD8BwQFBWRBcHAzAgRjYWxsBQNuaWwFA25pbAMJAAACBQJiMQUCYjEEAmEyCQD8BwQFBWRBcHAyAgRjYWxsBQNuaWwFA25pbAMJAAACBQJhMgUCYTIEAmIyCQD8BwQFBWRBcHAzAgRjYWxsBQNuaWwFA25pbAMJAAACBQJiMgUCYjIEAmEzCQD8BwQFBWRBcHAyAgRjYWxsBQNuaWwFA25pbAMJAAACBQJhMwUCYTMEAmIzCQD8BwQFBWRBcHAzAgRjYWxsBQNuaWwFA25pbAMJAAACBQJiMwUCYjMEAmE0CQD8BwQFBWRBcHAyAgRjYWxsBQNuaWwFA25pbAMJAAACBQJhNAUCYTQEAmI0CQD8BwQFBWRBcHAzAgRjYWxsBQNuaWwFA25pbAMJAAACBQJiNAUCYjQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgCZPou1") + + /* On dApp2 address + {-# STDLIB_VERSION 6 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + @Callable(i) + func call() = [ + ScriptTransfer(i.caller, 1, unit), + ScriptTransfer(i.caller, 2, unit), + ScriptTransfer(i.caller, 3, unit), + ScriptTransfer(i.caller, 4, unit), + ScriptTransfer(i.caller, 5, unit), + ScriptTransfer(i.caller, 6, unit), + ScriptTransfer(i.caller, 7, unit), + ScriptTransfer(i.caller, 8, unit), + ScriptTransfer(i.caller, 9, unit), + ScriptTransfer(i.caller, 10, unit) + ] + */ + _, tree2 := parseBase64Script(t, "BgIECAISAAABAWkBBGNhbGwACQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgABBQR1bml0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgACBQR1bml0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgADBQR1bml0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgAEBQR1bml0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgAFBQR1bml0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgAGBQR1bml0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgAHBQR1bml0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgAIBQR1bml0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgAJBQR1bml0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgAKBQR1bml0BQNuaWwAdHE1Mw==") + + /* On dApp3 address + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + @Callable(i) + func call() = [] + */ + _, tree3 := parseBase64Script(t, "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAAEY2FsbAAAAAAFAAAAA25pbAAAAACkYp5K") + + env := newTestEnv(t).withLibVersion(ast.LibV6).withComplexityLimit(ast.LibV6, 2000). + withBlockV5Activated().withProtobufTx(). + withDataEntriesSizeV2().withMessageLengthV3(). + withValidateInternalPayments().withThis(dApp1). + withDApp(dApp1).withAdditionalDApp(dApp2).withAdditionalDApp(dApp3).withSender(sender). + withInvocation("call"). + withTree(dApp1, tree1).withTree(dApp2, tree2).withTree(dApp3, tree3). + withWavesBalance(dApp1, 0).withWavesBalance(dApp2, 1000_00000000).withWavesBalance(dApp3, 0). + withWrappedState().withBlockRewardDistribution() + + res, err := CallFunction(env.toEnv(), tree1, proto.NewFunctionCall("call", proto.Arguments{})) + assert.NotNil(t, res) + assert.NoError(t, err) +} + +func TestInvokeActionsCountRestrictionsV6ToV5WithBlockRewardDistributionFailed(t *testing.T) { + dApp1 := newTestAccount(t, "DAPP1") // 3MzDtgL5yw73C2xVLnLJCrT5gCL4357a4sz + dApp2 := newTestAccount(t, "DAPP2") // 3N7Te7NXtGVoQqFqktwrFhQWAkc6J8vfPQ1 + dApp3 := newTestAccount(t, "DAPP3") // 3N186hYM5PFwGdkVUsLJaBvpPEECrSj5CJh + sender := newTestAccount(t, "SENDER") // 3N8CkZAyS4XcDoJTJoKNuNk2xmNKmQj7myW + + /* On dApp1 address + {-# STDLIB_VERSION 6 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + let dApp2 = Address(base58'3N7Te7NXtGVoQqFqktwrFhQWAkc6J8vfPQ1') # V6 script produces 10 transfer actions + let dApp3 = Address(base58'3N186hYM5PFwGdkVUsLJaBvpPEECrSj5CJh') # V5 script produces no actions + + @Callable(i) + func call() = { + strict a1 = invoke(dApp2, "call", [], []) + strict b1 = invoke(dApp3, "call", [], []) + strict a2 = invoke(dApp2, "call", [], []) + strict b2 = invoke(dApp3, "call", [], []) + strict a3 = invoke(dApp2, "call", [], []) + strict b3 = invoke(dApp3, "call", [], []) + strict a4 = invoke(dApp2, "call", [], []) + strict b4 = invoke(dApp3, "call", [], []) + strict a5 = invoke(dApp2, "call", [], []) + strict b5 = invoke(dApp3, "call", [], []) + strict a6 = invoke(dApp2, "call", [], []) + strict b6 = invoke(dApp3, "call", [], []) + strict a7 = invoke(dApp2, "call", [], []) + strict b7 = invoke(dApp3, "call", [], []) + strict a8 = invoke(dApp2, "call", [], []) + strict b8 = invoke(dApp3, "call", [], []) + strict a9 = invoke(dApp2, "call", [], []) + strict b9 = invoke(dApp3, "call", [], []) + strict a10 = invoke(dApp2, "call", [], []) + strict b10 = invoke(dApp3, "call", [], []) + strict a11 = invoke(dApp2, "call", [], []) + strict b11 = invoke(dApp3, "call", [], []) + [] + } + */ + _, tree1 := parseBase64Script(t, "BgIECAISAAIABWRBcHAyCQEHQWRkcmVzcwEBGgFUwHIGfTfL6MC+bgzmzz/fWbF5GHfdVq+uAAVkQXBwMwkBB0FkZHJlc3MBARoBVHrvJZrEY3NpLnBpk6ugJuX5CI8UJdzjLgEBaQEEY2FsbAAEAmExCQD8BwQFBWRBcHAyAgRjYWxsBQNuaWwFA25pbAMJAAACBQJhMQUCYTEEAmIxCQD8BwQFBWRBcHAzAgRjYWxsBQNuaWwFA25pbAMJAAACBQJiMQUCYjEEAmEyCQD8BwQFBWRBcHAyAgRjYWxsBQNuaWwFA25pbAMJAAACBQJhMgUCYTIEAmIyCQD8BwQFBWRBcHAzAgRjYWxsBQNuaWwFA25pbAMJAAACBQJiMgUCYjIEAmEzCQD8BwQFBWRBcHAyAgRjYWxsBQNuaWwFA25pbAMJAAACBQJhMwUCYTMEAmIzCQD8BwQFBWRBcHAzAgRjYWxsBQNuaWwFA25pbAMJAAACBQJiMwUCYjMEAmE0CQD8BwQFBWRBcHAyAgRjYWxsBQNuaWwFA25pbAMJAAACBQJhNAUCYTQEAmI0CQD8BwQFBWRBcHAzAgRjYWxsBQNuaWwFA25pbAMJAAACBQJiNAUCYjQEAmE1CQD8BwQFBWRBcHAyAgRjYWxsBQNuaWwFA25pbAMJAAACBQJhNQUCYTUEAmI1CQD8BwQFBWRBcHAzAgRjYWxsBQNuaWwFA25pbAMJAAACBQJiNQUCYjUEAmE2CQD8BwQFBWRBcHAyAgRjYWxsBQNuaWwFA25pbAMJAAACBQJhNgUCYTYEAmI2CQD8BwQFBWRBcHAzAgRjYWxsBQNuaWwFA25pbAMJAAACBQJiNgUCYjYEAmE3CQD8BwQFBWRBcHAyAgRjYWxsBQNuaWwFA25pbAMJAAACBQJhNwUCYTcEAmI3CQD8BwQFBWRBcHAzAgRjYWxsBQNuaWwFA25pbAMJAAACBQJiNwUCYjcEAmE4CQD8BwQFBWRBcHAyAgRjYWxsBQNuaWwFA25pbAMJAAACBQJhOAUCYTgEAmI4CQD8BwQFBWRBcHAzAgRjYWxsBQNuaWwFA25pbAMJAAACBQJiOAUCYjgEAmE5CQD8BwQFBWRBcHAyAgRjYWxsBQNuaWwFA25pbAMJAAACBQJhOQUCYTkEAmI5CQD8BwQFBWRBcHAzAgRjYWxsBQNuaWwFA25pbAMJAAACBQJiOQUCYjkEA2ExMAkA/AcEBQVkQXBwMgIEY2FsbAUDbmlsBQNuaWwDCQAAAgUDYTEwBQNhMTAEA2IxMAkA/AcEBQVkQXBwMwIEY2FsbAUDbmlsBQNuaWwDCQAAAgUDYjEwBQNiMTAEA2ExMQkA/AcEBQVkQXBwMgIEY2FsbAUDbmlsBQNuaWwDCQAAAgUDYTExBQNhMTEEA2IxMQkA/AcEBQVkQXBwMwIEY2FsbAUDbmlsBQNuaWwDCQAAAgUDYjExBQNiMTEFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgBfLydR") + + /* On dApp2 address + {-# STDLIB_VERSION 6 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + @Callable(i) + func call() = [ + ScriptTransfer(i.caller, 1, unit), + ScriptTransfer(i.caller, 2, unit), + ScriptTransfer(i.caller, 3, unit), + ScriptTransfer(i.caller, 4, unit), + ScriptTransfer(i.caller, 5, unit), + ScriptTransfer(i.caller, 6, unit), + ScriptTransfer(i.caller, 7, unit), + ScriptTransfer(i.caller, 8, unit), + ScriptTransfer(i.caller, 9, unit), + ScriptTransfer(i.caller, 10, unit) + ] + */ + _, tree2 := parseBase64Script(t, "BgIECAISAAABAWkBBGNhbGwACQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgABBQR1bml0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgACBQR1bml0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgADBQR1bml0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgAEBQR1bml0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgAFBQR1bml0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgAGBQR1bml0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgAHBQR1bml0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgAIBQR1bml0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgAJBQR1bml0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgAKBQR1bml0BQNuaWwAdHE1Mw==") + + /* On dApp3 address + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + @Callable(i) + func call() = [] + */ + _, tree3 := parseBase64Script(t, "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAAEY2FsbAAAAAAFAAAAA25pbAAAAACkYp5K") + + env := newTestEnv(t).withLibVersion(ast.LibV6).withComplexityLimit(ast.LibV6, 2000). + withBlockV5Activated().withProtobufTx(). + withDataEntriesSizeV2().withMessageLengthV3(). + withValidateInternalPayments().withThis(dApp1). + withDApp(dApp1).withAdditionalDApp(dApp2).withAdditionalDApp(dApp3).withSender(sender). + withInvocation("call"). + withTree(dApp1, tree1).withTree(dApp2, tree2).withTree(dApp3, tree3). + withWavesBalance(dApp1, 0).withWavesBalance(dApp2, 1000_00000000).withWavesBalance(dApp3, 0). + withWrappedState().withBlockRewardDistribution() + + res, err := CallFunction(env.toEnv(), tree1, proto.NewFunctionCall("call", proto.Arguments{})) + assert.Nil(t, res) + require.EqualError(t, err, "invoke: failed to apply actions: failed to validate total actions count: number of transfer group actions (101) produced by script is more than allowed 100") +} + func TestInvokeDappFromDappWithZeroPayments(t *testing.T) { dApp1 := newTestAccount(t, "DAPP1") // 3MzDtgL5yw73C2xVLnLJCrT5gCL4357a4sz dApp2 := newTestAccount(t, "DAPP2") // 3N7Te7NXtGVoQqFqktwrFhQWAkc6J8vfPQ1 diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 6b5efbacd..872dfa47d 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -399,18 +399,19 @@ func (a *txAppender) verifyWavesTxSigAndData(tx proto.Transaction, params *appen // appendTxParams contains params which are necessary for tx or block appending // TODO: create features provider instead of passing new params type appendTxParams struct { - chans *verifierChans // can be nil if validatingUtx == true - checkerInfo *checkerInfo - blockInfo *proto.BlockInfo - block *proto.BlockHeader - acceptFailed bool - blockV5Activated bool - rideV5Activated bool - rideV6Activated bool - consensusImprovementsActivated bool - invokeExpressionActivated bool // TODO: check feature naming - validatingUtx bool // if validatingUtx == false then chans MUST be initialized with non nil value - stateActionsCounterInBlock *proto.StateActionsCounter + chans *verifierChans // can be nil if validatingUtx == true + checkerInfo *checkerInfo + blockInfo *proto.BlockInfo + block *proto.BlockHeader + acceptFailed bool + blockV5Activated bool + rideV5Activated bool + rideV6Activated bool + consensusImprovementsActivated bool + blockRewardDistributionActivated bool + invokeExpressionActivated bool // TODO: check feature naming + validatingUtx bool // if validatingUtx == false then chans MUST be initialized with non nil value + stateActionsCounterInBlock *proto.StateActionsCounter } func (a *txAppender) handleInvokeOrExchangeTransaction(tx proto.Transaction, fallibleInfo *fallibleValidationParams) (*applicationResult, error) { @@ -484,7 +485,7 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro fallibleInfo := &fallibleValidationParams{appendTxParams: params, senderScripted: accountHasVerifierScript, senderAddress: senderAddr} applicationRes, err = a.handleInvokeOrExchangeTransaction(tx, fallibleInfo) if err != nil { - return errors.Errorf("failed to handle invoke or exchange transaction, %v", err) + return errors.Wrap(err, "failed to handle invoke or exchange transaction") } // Exchange and Invoke balances are validated in UTX when acceptFailed is false. // When acceptFailed is true, balances are validated inside handleFallible(). @@ -496,15 +497,14 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro } ethTx.TxKind, err = a.ethInfo.ethereumTransactionKind(ethTx, params) if err != nil { - return errors.Errorf("failed to guess ethereum transaction kind, %v", err) + return errors.Wrap(err, "failed to guess ethereum transaction kind") } switch ethTx.TxKind.(type) { case *proto.EthereumTransferWavesTxKind, *proto.EthereumTransferAssetsErc20TxKind: applicationRes, err = a.handleDefaultTransaction(tx, params, accountHasVerifierScript) if err != nil { - return errors.Errorf("failed to handle ethereum transaction (type %s) with id %s, on height %d: %v", - ethTx.TxKind.String(), ethTx.ID.String(), params.checkerInfo.height+1, err, - ) + return errors.Wrapf(err, "failed to handle ethereum transaction (type %s) with id %s, on height %d", + ethTx.TxKind.String(), ethTx.ID.String(), params.checkerInfo.height+1) } // In UTX balances are always validated. needToValidateBalanceDiff = params.validatingUtx @@ -516,10 +516,8 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro } 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", - ethTx.TxKind.String(), ethTx.ID.String(), params.checkerInfo.height+1, err, - ) + return errors.Wrapf(err, "failed to handle ethereum invoke script transaction (type %s) with id %s, on height %d", + ethTx.TxKind.String(), ethTx.ID.String(), params.checkerInfo.height+1) } } default: @@ -576,13 +574,18 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { if err != nil { return err } + blockRewardDistribution, err := a.stor.features.newestIsActivated(int16(settings.BlockRewardDistribution)) + if err != nil { + return err + } checkerInfo := &checkerInfo{ - currentTimestamp: params.block.Timestamp, - blockID: params.block.BlockID(), - blockVersion: params.block.Version, - height: params.height, - rideV5Activated: rideV5Activated, - rideV6Activated: rideV6Activated, + currentTimestamp: params.block.Timestamp, + blockID: params.block.BlockID(), + blockVersion: params.block.Version, + height: params.height, + rideV5Activated: rideV5Activated, + rideV6Activated: rideV6Activated, + blockRewardDistribution: blockRewardDistribution, } hasParent := params.parent != nil if hasParent { @@ -612,6 +615,10 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { if err != nil { return err } + blockRewardDistributionActivated, err := a.stor.features.newestIsActivated(int16(settings.BlockRewardDistribution)) + if err != nil { + return err + } invokeExpressionActivated, err := a.stor.features.newestIsActivated(int16(settings.InvokeExpression)) if err != nil { return err @@ -620,18 +627,19 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { // Check and append transactions. for _, tx := range params.transactions { appendTxArgs := &appendTxParams{ - chans: params.chans, - checkerInfo: checkerInfo, - blockInfo: blockInfo, - block: params.block, - acceptFailed: blockV5Activated, - blockV5Activated: blockV5Activated, - rideV5Activated: rideV5Activated, - rideV6Activated: rideV6Activated, - consensusImprovementsActivated: consensusImprovementsActivated, - invokeExpressionActivated: invokeExpressionActivated, - validatingUtx: false, - stateActionsCounterInBlock: stateActionsCounterInBlock, + chans: params.chans, + checkerInfo: checkerInfo, + blockInfo: blockInfo, + block: params.block, + acceptFailed: blockV5Activated, + blockV5Activated: blockV5Activated, + rideV5Activated: rideV5Activated, + rideV6Activated: rideV6Activated, + consensusImprovementsActivated: consensusImprovementsActivated, + blockRewardDistributionActivated: blockRewardDistributionActivated, + invokeExpressionActivated: invokeExpressionActivated, + validatingUtx: false, + stateActionsCounterInBlock: stateActionsCounterInBlock, } if err := a.appendTx(tx, appendTxArgs); err != nil { return err @@ -832,15 +840,20 @@ func (a *txAppender) validateNextTx(tx proto.Transaction, currentTimestamp, pare if err != nil { return errs.Extend(err, "failed to check 'RideV6' is activated") } + blockRewardDistribution, err := a.stor.features.newestIsActivated(int16(settings.BlockRewardDistribution)) + if err != nil { + return errs.Extend(err, "failed to check 'BlockRewardDistribution' is activated") + } blockInfo.Timestamp = currentTimestamp checkerInfo := &checkerInfo{ - currentTimestamp: currentTimestamp, - parentTimestamp: parentTimestamp, - blockID: block.BlockID(), - blockVersion: version, - height: blockInfo.Height, - rideV5Activated: rideV5Activated, - rideV6Activated: rideV6Activated, + currentTimestamp: currentTimestamp, + parentTimestamp: parentTimestamp, + blockID: block.BlockID(), + blockVersion: version, + height: blockInfo.Height, + rideV5Activated: rideV5Activated, + rideV6Activated: rideV6Activated, + blockRewardDistribution: blockRewardDistribution, } blockV5Activated, err := a.stor.features.newestIsActivated(int16(settings.BlockV5)) if err != nil { @@ -850,22 +863,27 @@ func (a *txAppender) validateNextTx(tx proto.Transaction, currentTimestamp, pare if err != nil { return errs.Extend(err, "failed to check 'ConsensusImprovements' is activated") } + blockRewardDistributionActivated, err := a.stor.features.newestIsActivated(int16(settings.BlockRewardDistribution)) + if err != nil { + return errs.Extend(err, "failed to check 'BlockRewardDistribution' is activated") + } invokeExpressionActivated, err := a.stor.features.newestIsActivated(int16(settings.InvokeExpression)) if err != nil { return errs.Extend(err, "failed to check 'InvokeExpression' is activated") // TODO: check feature naming in err message } appendTxArgs := &appendTxParams{ - chans: nil, // nil because validatingUtx == true - checkerInfo: checkerInfo, - blockInfo: blockInfo, - block: block, - acceptFailed: acceptFailed, - blockV5Activated: blockV5Activated, - rideV5Activated: rideV5Activated, - rideV6Activated: rideV6Activated, - consensusImprovementsActivated: consensusImprovementsActivated, - invokeExpressionActivated: invokeExpressionActivated, - validatingUtx: true, + chans: nil, // nil because validatingUtx == true + checkerInfo: checkerInfo, + blockInfo: blockInfo, + block: block, + acceptFailed: acceptFailed, + blockV5Activated: blockV5Activated, + rideV5Activated: rideV5Activated, + rideV6Activated: rideV6Activated, + consensusImprovementsActivated: consensusImprovementsActivated, + blockRewardDistributionActivated: blockRewardDistributionActivated, + invokeExpressionActivated: invokeExpressionActivated, + validatingUtx: true, // it's correct to use new counter because there's no block exists, but this field is necessary in tx performer stateActionsCounterInBlock: new(proto.StateActionsCounter), } diff --git a/pkg/state/eth_info.go b/pkg/state/eth_info.go index 372468e2a..81b8b1983 100644 --- a/pkg/state/eth_info.go +++ b/pkg/state/eth_info.go @@ -53,11 +53,10 @@ func (e *ethInfo) ethereumTransactionKind(ethTx *proto.EthereumTransaction, para case EthereumTransferWavesKind: return proto.NewEthereumTransferWavesTxKind(), nil case EthereumTransferAssetsKind: - db := ethabi.NewErc20MethodsMap() - decodedData, err := db.ParseCallDataRide(ethTx.Data()) + decodedData, err := db.ParseCallDataRide(ethTx.Data(), params.blockRewardDistributionActivated) if err != nil { - return nil, errors.Errorf("failed to parse ethereum data") + return nil, errors.Wrap(err, "failed to parse ethereum data") } if len(decodedData.Inputs) != ethabi.NumberOfERC20TransferArguments { return nil, errors.Errorf("the number of arguments of erc20 function is %d, but expected it to be %d", len(decodedData.Inputs), ethabi.NumberOfERC20TransferArguments) @@ -87,7 +86,7 @@ func (e *ethInfo) ethereumTransactionKind(ethTx *proto.EthereumTransaction, para if err != nil { return nil, err } - decodedData, err := db.ParseCallDataRide(ethTx.Data()) + decodedData, err := db.ParseCallDataRide(ethTx.Data(), params.blockRewardDistributionActivated) if err != nil { return nil, errors.Wrap(err, "failed to parse ethereum data") } diff --git a/pkg/state/ethereum_tx_test.go b/pkg/state/ethereum_tx_test.go index a388b25f8..6f51c47ba 100644 --- a/pkg/state/ethereum_tx_test.go +++ b/pkg/state/ethereum_tx_test.go @@ -167,7 +167,7 @@ func TestEthereumTransferAssets(t *testing.T) { db := ethabi.NewErc20MethodsMap() assert.NotNil(t, tx.Data()) - decodedData, err := db.ParseCallDataRide(tx.Data()) + decodedData, err := db.ParseCallDataRide(tx.Data(), true) assert.NoError(t, err) lessenDecodedDataAmount(t, decodedData) diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index b7d5243fc..5577b546f 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -1052,6 +1052,7 @@ func (ia *invokeApplier) validateActionSmartAsset(asset crypto.Digest, action pr params.blockV5Activated, params.rideV6Activated, params.consensusImprovementsActivated, + params.blockRewardDistributionActivated, params.invokeExpressionActivated, ) if err != nil { diff --git a/pkg/state/script_caller.go b/pkg/state/script_caller.go index 31a774a58..ed94df7ee 100644 --- a/pkg/state/script_caller.go +++ b/pkg/state/script_caller.go @@ -59,6 +59,7 @@ func (a *scriptCaller) callAccountScriptWithOrder(order proto.Order, lastBlockIn info.blockV5Activated, info.rideV6Activated, info.consensusImprovementsActivated, + info.blockRewardDistributionActivated, info.invokeExpressionActivated, ) if err != nil { @@ -120,6 +121,7 @@ func (a *scriptCaller) callAccountScriptWithTx(tx proto.Transaction, params *app params.blockV5Activated, params.rideV6Activated, params.consensusImprovementsActivated, + params.blockRewardDistributionActivated, params.invokeExpressionActivated, ) if err != nil { @@ -217,6 +219,7 @@ func (a *scriptCaller) callAssetScriptWithScriptTransfer(tr *proto.FullScriptTra params.blockV5Activated, params.rideV6Activated, params.consensusImprovementsActivated, + params.blockRewardDistributionActivated, params.invokeExpressionActivated, ) if err != nil { @@ -237,6 +240,7 @@ func (a *scriptCaller) callAssetScript(tx proto.Transaction, assetID crypto.Dige params.blockV5Activated, params.rideV6Activated, params.consensusImprovementsActivated, + params.blockRewardDistributionActivated, params.invokeExpressionActivated, ) if err != nil { @@ -257,6 +261,7 @@ func (a *scriptCaller) invokeFunction(tree *ast.Tree, tx proto.Transaction, info info.blockV5Activated, info.rideV6Activated, info.consensusImprovementsActivated, + info.blockRewardDistributionActivated, info.invokeExpressionActivated, ) if err != nil { @@ -374,7 +379,7 @@ func (a *scriptCaller) invokeFunction(tree *ast.Tree, tx proto.Transaction, info } decodedData := transaction.TxKind.DecodedData() - arguments, err := ride.ConvertDecodedEthereumArgumentsToProtoArguments(decodedData.Inputs) + arguments, err := proto.ConvertDecodedEthereumArgumentsToProtoArguments(decodedData.Inputs) if err != nil { return nil, errors.Errorf("failed to convert ethereum arguments, %v", err) } diff --git a/pkg/state/transaction_checker.go b/pkg/state/transaction_checker.go index 2df0788c5..a6d008980 100644 --- a/pkg/state/transaction_checker.go +++ b/pkg/state/transaction_checker.go @@ -11,6 +11,7 @@ import ( "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/errs" "github.com/wavesplatform/gowaves/pkg/proto" + "github.com/wavesplatform/gowaves/pkg/proto/ethabi" "github.com/wavesplatform/gowaves/pkg/ride" "github.com/wavesplatform/gowaves/pkg/ride/ast" "github.com/wavesplatform/gowaves/pkg/ride/meta" @@ -23,13 +24,14 @@ const ( ) type checkerInfo struct { - currentTimestamp uint64 - parentTimestamp uint64 - blockID proto.BlockID - blockVersion proto.BlockVersion - height uint64 - rideV5Activated bool - rideV6Activated bool + currentTimestamp uint64 + parentTimestamp uint64 + blockID proto.BlockID + blockVersion proto.BlockVersion + height uint64 + rideV5Activated bool + rideV6Activated bool + blockRewardDistribution bool } func (i *checkerInfo) estimatorVersion() int { @@ -398,12 +400,16 @@ func (tc *transactionChecker) checkEthereumTransactionWithProofs(transaction pro return nil, errs.Extend(err, "invalid timestamp in ethereum transaction") } + needToValidateNonEmptyCallData := info.blockRewardDistribution var smartAssets []crypto.Digest switch kind := tx.TxKind.(type) { case *proto.EthereumTransferWavesTxKind: if tx.Value() == nil { return nil, errors.New("amount of ethereum transfer waves is nil") } + if l := len(tx.Data()); l != 0 { + return nil, errors.Errorf("ethereum call data must be empty for waves transfer, but size is %d", l) + } res, err := proto.EthereumWeiToWavelet(tx.Value()) if err != nil { return nil, errors.Errorf("failed to convert wei amount from ethreum transaction to wavelets. value is %s", tx.Value().String()) @@ -415,6 +421,10 @@ func (tc *transactionChecker) checkEthereumTransactionWithProofs(transaction pro if kind.Arguments.Amount == 0 { return nil, errors.New("the amount of ethereum transfer assets is 0, which is forbidden") } + if l := len(tx.Data()); needToValidateNonEmptyCallData && l != ethabi.ERC20TransferCallDataSize { + return nil, errors.Errorf("ethereum call data must be %d size for assset transfer, but size is %d", + ethabi.ERC20TransferCallDataSize, l) + } allAssets := []proto.OptionalAsset{kind.Asset} smartAssets, err = tc.smartAssets(allAssets) if err != nil { @@ -422,12 +432,21 @@ func (tc *transactionChecker) checkEthereumTransactionWithProofs(transaction pro } case *proto.EthereumInvokeScriptTxKind: var ( - decodedData = tx.TxKind.DecodedData() + decodedData = kind.DecodedData() abiPayments = decodedData.Payments ) - if len(abiPayments) > 10 { + if len(abiPayments) > maxPaymentsCountSinceRideV5Activation { return nil, errors.New("no more than 10 payments is allowed since RideV5 activation") } + if needToValidateNonEmptyCallData { + dApp, err := tx.To().ToWavesAddress(tc.settings.AddressSchemeCharacter) + if err != nil { + return nil, errors.Wrapf(err, "failed to convert eth addr %q to waves addr", tx.To().String()) + } + if err := kind.ValidateCallData(dApp); err != nil { + return nil, errors.Wrap(err, "failed to validate callData") + } + } paymentAssets := make([]proto.OptionalAsset, 0, len(abiPayments)) for _, p := range abiPayments { @@ -1312,6 +1331,8 @@ func (tc *transactionChecker) checkSetAssetScriptWithProofs(transaction proto.Tr return smartAssets, nil } +const maxPaymentsCountSinceRideV5Activation = 10 + func (tc *transactionChecker) checkInvokeScriptWithProofs(transaction proto.Transaction, info *checkerInfo) ([]crypto.Digest, error) { tx, ok := transaction.(*proto.InvokeScriptWithProofs) if !ok { @@ -1344,7 +1365,7 @@ func (tc *transactionChecker) checkInvokeScriptWithProofs(transaction proto.Tran return nil, errors.New("no more than one payment is allowed") case l > 2 && multiPaymentActivated && !rideV5activated: return nil, errors.New("no more than two payments is allowed") - case l > 10 && rideV5activated: + case l > maxPaymentsCountSinceRideV5Activation && rideV5activated: return nil, errors.New("no more than ten payments is allowed since RideV5 activation") } var paymentAssets []proto.OptionalAsset From 5fd430e56a826ca83a89bd92cabfca81421e4ad5 Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Mon, 22 May 2023 20:33:12 +0400 Subject: [PATCH 028/139] Ride add rewards to block info (#1096) * add feature BlockRewardDistribution * fix tests * Improvement of the test on reward distribution to check that remainder of division goes to miner. * refactor after rewiev * fix feature info and add reward addresses in testnet and stagenet configs * change count actions with feature BlockRewardDistribution activated * Ride version 7 added. Extended version of BlockInfo ride object added. Ride types representation in objects stdlib description changed to simple string. Parsing of types added to code generation and updated in compiler. Code generation updated to support Tuple types. * Fixed code generation for RideV7. Fixed compilation of V7 scripts. Added rewards structure and function to SmartState to get the block rewards. Added test on script accessing new rewards field on BlockInfo. * Fixed FunctionCall usage in tests * Fixed sorting of rewards with stable sort. * Script activation check added for RideV7. * Code improvements * Restored recursive check of list types in generated code. * Generation of simplified code for tuple type checks. * Duplicated tests removed * Fixed lib version check in Ride compiler --------- Co-authored-by: Anton Ilin Co-authored-by: Anton Ilin <48175203+Anton-Rampage@users.noreply.github.com> --- pkg/proto/reward.go | 45 + pkg/ride/ast/attributes.go | 5 +- pkg/ride/compiler/ast_parser.go | 10 +- pkg/ride/compiler/ast_parser_test.go | 4 +- pkg/ride/compiler/stdlib/funcs.json | 4 + pkg/ride/compiler/stdlib/ride_objects.json | 1362 +++++------------ pkg/ride/compiler/stdlib/structs.go | 38 +- pkg/ride/compiler/stdlib/types.go | 160 +- pkg/ride/compiler/stdlib/vars.json | 1 + pkg/ride/constants.gen.go | 23 + pkg/ride/constraints.go | 2 +- pkg/ride/constructors.gen.go | 245 +-- pkg/ride/converters.go | 28 +- pkg/ride/environment.go | 4 + pkg/ride/functions.gen.go | 62 + pkg/ride/functions_proto.go | 17 +- .../generate/internal/constants_generation.go | 5 + .../internal/constructors_generation.go | 86 +- .../generate/internal/functions_generation.go | 25 + .../generate/internal/generator_config.go | 123 +- .../generate/internal/objects_generation.go | 44 +- pkg/ride/objects.gen.go | 108 ++ pkg/ride/selectors.go | 17 + pkg/ride/smart_state_moq_test.go | 50 + pkg/ride/test_helpers_test.go | 21 + pkg/ride/tree_estimatorV1.go | 2 + pkg/ride/tree_estimatorV2.go | 2 + pkg/ride/tree_estimatorV3.go | 2 + pkg/ride/tree_estimatorV4.go | 2 + pkg/ride/tree_evaluation_test.go | 75 +- pkg/ride/tree_evaluator.go | 2 + pkg/state/smart_state_moq_test.go | 50 + pkg/state/state.go | 25 + pkg/state/transaction_checker.go | 11 +- pkg/types/types.go | 1 + 35 files changed, 1303 insertions(+), 1358 deletions(-) create mode 100644 pkg/proto/reward.go diff --git a/pkg/proto/reward.go b/pkg/proto/reward.go new file mode 100644 index 000000000..f872fe417 --- /dev/null +++ b/pkg/proto/reward.go @@ -0,0 +1,45 @@ +package proto + +import ( + "bytes" + "sort" +) + +type Reward struct { + address WavesAddress + amount uint64 +} + +func NewReward(address WavesAddress, amount uint64) Reward { + return Reward{address: address, amount: amount} +} + +func (r *Reward) Address() WavesAddress { + return r.address +} + +func (r *Reward) Amount() uint64 { + return r.amount +} + +type Rewards []Reward + +func (r *Rewards) Sorted() Rewards { + rewards := *r + sort.Stable(rewardsByAddress(rewards)) + return rewards +} + +type rewardsByAddress []Reward + +func (r rewardsByAddress) Len() int { return len(r) } +func (r rewardsByAddress) Swap(i, j int) { r[i], r[j] = r[j], r[i] } + +func (r rewardsByAddress) Less(i, j int) bool { + //TODO: Consider adding second sort order by amount, which is not scala implementation compatible for now. + // In scala implementation they depend on stability of sort and add miner on the last position. + // if r[i].address.Equal(r[j].address) { + // return r[i].amount < r[j].amount + // } + return bytes.Compare(r[i].address.Bytes(), r[j].address.Bytes()) < 0 +} diff --git a/pkg/ride/ast/attributes.go b/pkg/ride/ast/attributes.go index 9f33a4fe2..9a0ee2c20 100644 --- a/pkg/ride/ast/attributes.go +++ b/pkg/ride/ast/attributes.go @@ -47,17 +47,18 @@ const ( LibV4 LibV5 LibV6 + LibV7 ) // CurrentMaxLibraryVersion reports the max lib version. Update it when a new version was added. func CurrentMaxLibraryVersion() LibraryVersion { - return LibV6 + return LibV7 } func NewLibraryVersion(b byte) (LibraryVersion, error) { lv := LibraryVersion(b) switch lv { - case LibV1, LibV2, LibV3, LibV4, LibV5, LibV6: + case LibV1, LibV2, LibV3, LibV4, LibV5, LibV6, LibV7: return lv, nil default: return 0, errors.Errorf("unsupported library version '%d'", b) diff --git a/pkg/ride/compiler/ast_parser.go b/pkg/ride/compiler/ast_parser.go index 9afa84845..c98865959 100644 --- a/pkg/ride/compiler/ast_parser.go +++ b/pkg/ride/compiler/ast_parser.go @@ -136,7 +136,7 @@ func (p *astParser) loadBuildInVarsToStackByVersion() { Type: txType, }) } - if p.tree.LibVersion == ast.LibV5 || p.tree.LibVersion == ast.LibV6 || p.tree.LibVersion == ast.LibV4 { + if p.tree.LibVersion >= ast.LibV4 && p.tree.LibVersion <= ast.LibV7 { if p.scriptType == assetScript { p.stack.pushVariable(s.Variable{ Name: "this", @@ -1369,7 +1369,7 @@ func (p *astParser) ruleGettableExprHandler(node *node32) (ast.Node, s.Type) { falseExpr = ast.NewReferenceNode("unit") varType = s.UnionType{Types: []s.Type{t, s.SimpleType{Type: "Unit"}}} case ruleExactAsString: - if int(p.tree.LibVersion) >= int(ast.LibV6) { + if p.tree.LibVersion >= ast.LibV6 { falseExpr = ast.NewFunctionCallNode( ast.NativeFunction("2"), []ast.Node{ @@ -1416,7 +1416,7 @@ func (p *astParser) ruleGettableExprHandler(node *node32) (ast.Node, s.Type) { expr = newExpr case ruleListAccess: listNode := curNode.up - if l, ok := varType.(s.ListType); !ok { + if l, ok := varType.(s.ListType); !ok && varType != nil { p.addError(listNode.token32, "Type must be 'List' but got '%s'", varType.String()) } else { if listNode.pegRule == rule_ { @@ -1879,7 +1879,7 @@ func (p *astParser) loadMeta(name string, argsTypes []s.Type) error { switch p.tree.LibVersion { case ast.LibV1, ast.LibV2, ast.LibV3, ast.LibV4, ast.LibV5: return p.loadMetaBeforeV6(name, argsTypes) - case ast.LibV6: + case ast.LibV6, ast.LibV7: return p.loadMetaV6(name, argsTypes) } return nil @@ -2014,7 +2014,7 @@ func (p *astParser) ruleAnnotatedFunc(node *node32) { if !s.CallableRetV4.EqualWithEntry(retType) && !s.ThrowType.Equal(retType) { p.addError(curNode.token32, "CallableFunc must return %s,but return %s", s.CallableRetV4.String(), retType.String()) } - case ast.LibV5, ast.LibV6: + case ast.LibV5, ast.LibV6, ast.LibV7: if !s.CallableRetV5.EqualWithEntry(retType) && !s.ThrowType.Equal(retType) { p.addError(curNode.token32, "CallableFunc must return %s, but return %s", s.CallableRetV5.String(), retType.String()) } diff --git a/pkg/ride/compiler/ast_parser_test.go b/pkg/ride/compiler/ast_parser_test.go index 868f89f9f..0178389b3 100644 --- a/pkg/ride/compiler/ast_parser_test.go +++ b/pkg/ride/compiler/ast_parser_test.go @@ -73,9 +73,9 @@ func TestDirectivesCompileFail(t *testing.T) { errorMsg []string }{ {` -{-# STDLIB_VERSION 7 #-} +{-# STDLIB_VERSION 8 #-} {-# CONTENT_TYPE DAPP #-} -{-# SCRIPT_TYPE ACCOUNT #-}`, []string{"(2:20, 2:21): Invalid directive 'STDLIB_VERSION': unsupported library version '7'"}}, +{-# SCRIPT_TYPE ACCOUNT #-}`, []string{"(2:20, 2:21): Invalid directive 'STDLIB_VERSION': unsupported library version '8'"}}, {` {-# STDLIB_VERSION 0 #-} {-# CONTENT_TYPE DAPP #-} diff --git a/pkg/ride/compiler/stdlib/funcs.json b/pkg/ride/compiler/stdlib/funcs.json index 1a14f31e1..ac2b23f1f 100644 --- a/pkg/ride/compiler/stdlib/funcs.json +++ b/pkg/ride/compiler/stdlib/funcs.json @@ -2607,6 +2607,10 @@ ] }, "remove": [] + }, + { + "new": {}, + "remove": [] } ] } \ No newline at end of file diff --git a/pkg/ride/compiler/stdlib/ride_objects.json b/pkg/ride/compiler/stdlib/ride_objects.json index 1cf0e4a55..1fff2fe74 100644 --- a/pkg/ride/compiler/stdlib/ride_objects.json +++ b/pkg/ride/compiler/stdlib/ride_objects.json @@ -8,82 +8,61 @@ "fields": [ { "name": "description", - "types": [ - "String" - ], + "type": "String", "order": 0, "constructorOrder": 9 }, { "name": "name", - "types": [ - "String" - ], + "type": "String", "order": 8, "constructorOrder": 8 }, { "name": "issuerPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 3, "constructorOrder": 4 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 5, "constructorOrder": 0 }, { "name": "minSponsoredFee", - "types": [ - "Int", - "Unit" - ], + "type": "Int|Unit", "order": 4, "constructorOrder": 7 }, { "name": "decimals", - "types": [ - "Int" - ], + "type": "Int", "order": 6, "constructorOrder": 2 }, { "name": "quantity", - "types": [ - "Int" - ], + "type": "Int", "order": 9, "constructorOrder": 1 }, { "name": "issuer", - "types": [ - "Address" - ], + "type": "Address", "order": 1, "constructorOrder": 3 }, { "name": "reissuable", - "types": [ - "Boolean" - ], + "type": "Boolean", "order": 7, "constructorOrder": 5 }, { "name": "scripted", - "types": [ - "Boolean" - ], + "type": "Boolean", "order": 2, "constructorOrder": 6 } @@ -94,65 +73,49 @@ "fields": [ { "name": "issuerPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 2, "constructorOrder": 4 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 3, "constructorOrder": 0 }, { "name": "quantity", - "types": [ - "Int" - ], + "type": "Int", "order": 6, "constructorOrder": 1 }, { "name": "decimals", - "types": [ - "Int" - ], + "type": "Int", "order": 4, "constructorOrder": 2 }, { "name": "issuer", - "types": [ - "Address" - ], + "type": "Address", "order": 0, "constructorOrder": 3 }, { "name": "scripted", - "types": [ - "Boolean" - ], + "type": "Boolean", "order": 1, "constructorOrder": 6 }, { "name": "sponsored", - "types": [ - "Boolean" - ], + "type": "Boolean", "order": 7, "constructorOrder": 7 }, { "name": "reissuable", - "types": [ - "Boolean" - ], + "type": "Boolean", "order": 5, "constructorOrder": 5 } @@ -168,19 +131,13 @@ "fields": [ { "name": "amountAsset", - "types": [ - "Unit", - "ByteVector" - ], + "type": "Unit|ByteVector", "order": 0, "constructorOrder": 0 }, { "name": "priceAsset", - "types": [ - "Unit", - "ByteVector" - ], + "type": "Unit|ByteVector", "order": 1, "constructorOrder": 1 } @@ -196,18 +153,13 @@ "fields": [ { "name": "assetId", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 0, "constructorOrder": 0 }, { "name": "amount", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 1 } @@ -223,33 +175,25 @@ "fields": [ { "name": "available", - "types": [ - "Int" - ], + "type": "Int", "order": 0, "constructorOrder": 0 }, { "name": "regular", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 1 }, { "name": "generating", - "types": [ - "Int" - ], + "type": "Int", "order": 2, "constructorOrder": 2 }, { "name": "effective", - "types": [ - "Int" - ], + "type": "Int", "order": 3, "constructorOrder": 3 } @@ -265,17 +209,13 @@ "fields": [ { "name": "key", - "types": [ - "String" - ], + "type": "String", "order": 0, "constructorOrder": 0 }, { "name": "value", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 1, "constructorOrder": 1 } @@ -291,49 +231,37 @@ "fields": [ { "name": "generationSignature", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 5, "constructorOrder": 3 }, { "name": "generatorPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 6, "constructorOrder": 5 }, { "name": "baseTarget", - "types": [ - "Int" - ], + "type": "Int", "order": 0, "constructorOrder": 2 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 2, "constructorOrder": 0 }, { "name": "height", - "types": [ - "Int" - ], + "type": "Int", "order": 4, "constructorOrder": 1 }, { "name": "generator", - "types": [ - "Address" - ], + "type": "Address", "order": 1, "constructorOrder": 4 } @@ -344,62 +272,100 @@ "fields": [ { "name": "vrf", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 3, "constructorOrder": 6 }, { "name": "generationSignature", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 5, "constructorOrder": 3 }, { "name": "generatorPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 6, "constructorOrder": 5 }, { "name": "baseTarget", - "types": [ - "Int" - ], + "type": "Int", "order": 0, "constructorOrder": 2 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 2, "constructorOrder": 0 }, { "name": "height", - "types": [ - "Int" - ], + "type": "Int", "order": 4, "constructorOrder": 1 }, { "name": "generator", - "types": [ - "Address" - ], + "type": "Address", "order": 1, "constructorOrder": 4 } ] + }, + { + "version": 7, + "fields": [ + { + "name": "vrf", + "type": "ByteVector|Unit", + "order": 3, + "constructorOrder": 6 + }, + { + "name": "generationSignature", + "type": "ByteVector", + "order": 5, + "constructorOrder": 3 + }, + { + "name": "generatorPublicKey", + "type": "ByteVector", + "order": 6, + "constructorOrder": 5 + }, + { + "name": "baseTarget", + "type": "Int", + "order": 0, + "constructorOrder": 2 + }, + { + "name": "timestamp", + "type": "Int", + "order": 2, + "constructorOrder": 0 + }, + { + "name": "height", + "type": "Int", + "order": 4, + "constructorOrder": 1 + }, + { + "name": "generator", + "type": "Address", + "order": 1, + "constructorOrder": 4 + }, + { + "name": "rewards", + "type": "List[(Address,Int)]", + "order": 7, + "constructorOrder": 7 + } + ] } ] }, @@ -411,17 +377,13 @@ "fields": [ { "name": "key", - "types": [ - "String" - ], + "type": "String", "order": 0, "constructorOrder": 0 }, { "name": "value", - "types": [ - "Boolean" - ], + "type": "Boolean", "order": 1, "constructorOrder": 1 } @@ -437,17 +399,13 @@ "fields": [ { "name": "assetId", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 0, "constructorOrder": 0 }, { "name": "quantity", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 1 } @@ -464,20 +422,13 @@ "fields": [ { "name": "value", - "types": [ - "Int", - "ByteVector", - "Boolean", - "String" - ], + "type": "Int|ByteVector|Boolean|String", "order": 1, "constructorOrder": 1 }, { "name": "key", - "types": [ - "String" - ], + "type": "String", "order": 0, "constructorOrder": 0 } @@ -493,9 +444,7 @@ "fields": [ { "name": "key", - "types": [ - "String" - ], + "type": "String", "order": 0, "constructorOrder": 0 } @@ -511,17 +460,13 @@ "fields": [ { "name": "key", - "types": [ - "String" - ], + "type": "String", "order": 0, "constructorOrder": 0 }, { "name": "value", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 1 } @@ -537,51 +482,37 @@ "fields": [ { "name": "payment", - "types": [ - "AttachedPayment", - "Unit" - ], + "type": "AttachedPayment|Unit", "order": 1, "constructorOrder": 0 }, { "name": "callerPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 2, "constructorOrder": 2 }, { "name": "feeAssetId", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 3, "constructorOrder": 5 }, { "name": "transactionId", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 5, "constructorOrder": 3 }, { "name": "caller", - "types": [ - "Address" - ], + "type": "Address", "order": 6, "constructorOrder": 1 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 7, "constructorOrder": 4 } @@ -592,50 +523,37 @@ "fields": [ { "name": "payments", - "types": [ - "List[AttachedPayment]" - ], + "type": "List[AttachedPayment]", "order": 1, "constructorOrder": 0 }, { "name": "callerPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 2, "constructorOrder": 2 }, { "name": "feeAssetId", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 3, "constructorOrder": 5 }, { "name": "transactionId", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 5, "constructorOrder": 3 }, { "name": "caller", - "types": [ - "Address" - ], + "type": "Address", "order": 6, "constructorOrder": 1 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 7, "constructorOrder": 4 } @@ -646,67 +564,49 @@ "fields": [ { "name": "originCaller", - "types": [ - "Address" - ], + "type": "Address", "order": 0, "constructorOrder": 6 }, { "name": "payments", - "types": [ - "List[AttachedPayment]" - ], + "type": "List[AttachedPayment]", "order": 1, "constructorOrder": 0 }, { "name": "callerPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 2, "constructorOrder": 2 }, { "name": "feeAssetId", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 3, "constructorOrder": 5 }, { "name": "originCallerPublicKey", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 4, "constructorOrder": 7 }, { "name": "transactionId", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 5, "constructorOrder": 3 }, { "name": "caller", - "types": [ - "Address" - ], + "type": "Address", "order": 6, "constructorOrder": 1 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 7, "constructorOrder": 4 } @@ -722,58 +622,43 @@ "fields": [ { "name": "compiledScript", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 4, "constructorOrder": 5 }, { "name": "name", - "types": [ - "String" - ], + "type": "String", "order": 5, "constructorOrder": 0 }, { "name": "description", - "types": [ - "String" - ], + "type": "String", "order": 2, "constructorOrder": 1 }, { "name": "nonce", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 6 }, { "name": "decimals", - "types": [ - "Int" - ], + "type": "Int", "order": 3, "constructorOrder": 3 }, { "name": "quantity", - "types": [ - "Int" - ], + "type": "Int", "order": 6, "constructorOrder": 2 }, { "name": "isReissuable", - "types": [ - "Boolean" - ], + "type": "Boolean", "order": 0, "constructorOrder": 4 } @@ -789,9 +674,7 @@ "fields": [ { "name": "leaseId", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 0, "constructorOrder": 0 } @@ -807,27 +690,19 @@ "fields": [ { "name": "recipient", - "types": [ - "Alias", - "Address", - "AddressLike" - ], + "type": "Alias|Address|AddressLike", "order": 0, "constructorOrder": 0 }, { "name": "amount", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 1 }, { "name": "nonce", - "types": [ - "Int" - ], + "type": "Int", "order": 2, "constructorOrder": 2 } @@ -843,114 +718,85 @@ "fields": [ { "name": "assetPair", - "types": [ - "Type" - ], + "type": "Type", "order": 0, "constructorOrder": 2 }, { "name": "orderType", - "types": [ - "Type" - ], + "type": "Type", "order": 9, "constructorOrder": 3 }, { "name": "matcherFeeAssetId", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 4, "constructorOrder": 9 }, { "name": "proofs", - "types": [ - "List[ByteVector]" - ], + "type": "List[ByteVector]", "order": 10, "constructorOrder": 13 }, { "name": "bodyBytes", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 2, "constructorOrder": 12 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 5, "constructorOrder": 0 }, { "name": "senderPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 6, "constructorOrder": 11 }, { "name": "matcherPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 7, "constructorOrder": 1 }, { "name": "amount", - "types": [ - "Int" - ], + "type": "Int", "order": 3, "constructorOrder": 5 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 6 }, { "name": "expiration", - "types": [ - "Int" - ], + "type": "Int", "order": 11, "constructorOrder": 7 }, { "name": "matcherFee", - "types": [ - "Int" - ], + "type": "Int", "order": 12, "constructorOrder": 8 }, { "name": "price", - "types": [ - "Int" - ], + "type": "Int", "order": 13, "constructorOrder": 4 }, { "name": "sender", - "types": [ - "Address" - ], + "type": "Address", "order": 8, "constructorOrder": 10 } @@ -967,25 +813,19 @@ "fields": [ { "name": "assetId", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 0, "constructorOrder": 0 }, { "name": "quantity", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 1 }, { "name": "isReissuable", - "types": [ - "Boolean" - ], + "type": "Boolean", "order": 2, "constructorOrder": 2 } @@ -1002,17 +842,13 @@ "fields": [ { "name": "writeSet", - "types": [ - "WriteSet" - ], + "type": "WriteSet", "order": 0, "constructorOrder": 0 }, { "name": "transferSet", - "types": [ - "TransferSet" - ], + "type": "TransferSet", "order": 1, "constructorOrder": 1 } @@ -1028,28 +864,19 @@ "fields": [ { "name": "asset", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 2, "constructorOrder": 2 }, { "name": "recipient", - "types": [ - "Alias", - "Address", - "AddressLike" - ], + "type": "Alias|Address|AddressLike", "order": 0, "constructorOrder": 0 }, { "name": "amount", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 1 } @@ -1065,17 +892,13 @@ "fields": [ { "name": "assetId", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 0, "constructorOrder": 0 }, { "name": "minSponsoredAssetFee", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 1 } @@ -1091,17 +914,13 @@ "fields": [ { "name": "key", - "types": [ - "String" - ], + "type": "String", "order": 0, "constructorOrder": 0 }, { "name": "value", - "types": [ - "String" - ], + "type": "String", "order": 1, "constructorOrder": 1 } @@ -1117,19 +936,13 @@ "fields": [ { "name": "recipient", - "types": [ - "Alias", - "Address", - "AddressLike" - ], + "type": "Alias|Address|AddressLike", "order": 0, "constructorOrder": 0 }, { "name": "amount", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 1 } @@ -1146,9 +959,7 @@ "fields": [ { "name": "transfers", - "types": [ - "List[ScriptTransfer]" - ], + "type": "List[ScriptTransfer]", "order": 0, "constructorOrder": 0 } @@ -1165,9 +976,7 @@ "fields": [ { "name": "data", - "types": [ - "List[DataEntry]" - ], + "type": "List[DataEntry]", "order": 0, "constructorOrder": 0 } @@ -1183,81 +992,61 @@ "fields": [ { "name": "bodyBytes", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 2, "constructorOrder": 8 }, { "name": "proofs", - "types": [ - "List[ByteVector]" - ], + "type": "List[ByteVector]", "order": 8, "constructorOrder": 9 }, { "name": "senderPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 6, "constructorOrder": 7 }, { "name": "assetId", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 3, "constructorOrder": 1 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 5, "constructorOrder": 2 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 4 }, { "name": "version", - "types": [ - "Int" - ], + "type": "Int", "order": 4, "constructorOrder": 5 }, { "name": "quantity", - "types": [ - "Int" - ], + "type": "Int", "order": 0, "constructorOrder": 0 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 9, "constructorOrder": 3 }, { "name": "sender", - "types": [ - "Address" - ], + "type": "Address", "order": 7, "constructorOrder": 6 } @@ -1274,73 +1063,55 @@ "fields": [ { "name": "proofs", - "types": [ - "List[ByteVector]" - ], + "type": "List[ByteVector]", "order": 5, "constructorOrder": 8 }, { "name": "alias", - "types": [ - "String" - ], + "type": "String", "order": 7, "constructorOrder": 0 }, { "name": "bodyBytes", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 1, "constructorOrder": 7 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 2, "constructorOrder": 1 }, { "name": "senderPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 3, "constructorOrder": 6 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 0, "constructorOrder": 3 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 6, "constructorOrder": 2 }, { "name": "version", - "types": [ - "Int" - ], + "type": "Int", "order": 8, "constructorOrder": 4 }, { "name": "sender", - "types": [ - "Address" - ], + "type": "Address", "order": 4, "constructorOrder": 5 } @@ -1357,73 +1128,55 @@ "fields": [ { "name": "proofs", - "types": [ - "List[ByteVector]" - ], + "type": "List[ByteVector]", "order": 7, "constructorOrder": 8 }, { "name": "bodyBytes", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 1, "constructorOrder": 7 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 4, "constructorOrder": 1 }, { "name": "senderPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 5, "constructorOrder": 6 }, { "name": "data", - "types": [ - "List[BinaryEntry|BooleanEntry|DeleteEntry|IntegerEntry|StringEntry]" - ], + "type": "List[BinaryEntry|BooleanEntry|DeleteEntry|IntegerEntry|StringEntry]", "order": 2, "constructorOrder": 0 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 0, "constructorOrder": 3 }, { "name": "version", - "types": [ - "Int" - ], + "type": "Int", "order": 3, "constructorOrder": 4 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 8, "constructorOrder": 2 }, { "name": "sender", - "types": [ - "Address" - ], + "type": "Address", "order": 6, "constructorOrder": 5 } @@ -1440,113 +1193,85 @@ "fields": [ { "name": "proofs", - "types": [ - "List[ByteVector]" - ], + "type": "List[ByteVector]", "order": 12, "constructorOrder": 13 }, { "name": "buyOrder", - "types": [ - "Type" - ], + "type": "Type", "order": 2, "constructorOrder": 0 }, { "name": "sellOrder", - "types": [ - "Type" - ], + "type": "Type", "order": 7, "constructorOrder": 1 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 6, "constructorOrder": 6 }, { "name": "bodyBytes", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 1, "constructorOrder": 12 }, { "name": "senderPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 8, "constructorOrder": 11 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 0, "constructorOrder": 8 }, { "name": "price", - "types": [ - "Int" - ], + "type": "Int", "order": 3, "constructorOrder": 2 }, { "name": "amount", - "types": [ - "Int" - ], + "type": "Int", "order": 4, "constructorOrder": 3 }, { "name": "version", - "types": [ - "Int" - ], + "type": "Int", "order": 5, "constructorOrder": 9 }, { "name": "buyMatcherFee", - "types": [ - "Int" - ], + "type": "Int", "order": 9, "constructorOrder": 4 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 11, "constructorOrder": 7 }, { "name": "sellMatcherFee", - "types": [ - "Int" - ], + "type": "Int", "order": 13, "constructorOrder": 5 }, { "name": "sender", - "types": [ - "Address" - ], + "type": "Address", "order": 10, "constructorOrder": 10 } @@ -1563,51 +1288,37 @@ "fields": [ { "name": "recipient", - "types": [ - "Alias", - "Address", - "AddressLike" - ], + "type": "Alias|Address|AddressLike", "order": 0, "constructorOrder": 1 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 4, "constructorOrder": 2 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 4 }, { "name": "amount", - "types": [ - "Int" - ], + "type": "Int", "order": 2, "constructorOrder": 0 }, { "name": "version", - "types": [ - "Int" - ], + "type": "Int", "order": 3, "constructorOrder": 5 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 5, "constructorOrder": 3 } @@ -1623,82 +1334,61 @@ "fields": [ { "name": "proofs", - "types": [ - "List[ByteVector]" - ], + "type": "List[ByteVector]", "order": 8, "constructorOrder": 9 }, { "name": "feeAssetId", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 2, "constructorOrder": 1 }, { "name": "bodyBytes", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 1, "constructorOrder": 8 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 4, "constructorOrder": 2 }, { "name": "expression", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 5, "constructorOrder": 0 }, { "name": "senderPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 6, "constructorOrder": 7 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 0, "constructorOrder": 4 }, { "name": "version", - "types": [ - "Int" - ], + "type": "Int", "order": 3, "constructorOrder": 5 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 9, "constructorOrder": 3 }, { "name": "sender", - "types": [ - "Address" - ], + "type": "Address", "order": 7, "constructorOrder": 6 } @@ -1715,109 +1405,79 @@ "fields": [ { "name": "proofs", - "types": [ - "List[ByteVector]" - ], + "type": "List[ByteVector]", "order": 5, "constructorOrder": 12 }, { "name": "feeAssetId", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 3, "constructorOrder": 1 }, { "name": "dApp", - "types": [ - "Alias", - "Address", - "AddressLike" - ], + "type": "Alias|Address|AddressLike", "order": 7, "constructorOrder": 0 }, { "name": "function", - "types": [ - "String" - ], + "type": "String", "order": 10, "constructorOrder": 2 }, { "name": "bodyBytes", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 2, "constructorOrder": 10 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 4, "constructorOrder": 4 }, { "name": "senderPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 9, "constructorOrder": 9 }, { "name": "payment", - "types": [ - "AttachedPayment", - "Unit" - ], + "type": "AttachedPayment|Unit", "order": 0, "constructorOrder": 11 }, { "name": "args", - "types": [ - "List[Boolean|ByteVector|Int|List[Boolean|ByteVector|Int|String]|String]" - ], + "type": "List[Boolean|ByteVector|Int|List[Boolean|ByteVector|Int|String]|String]", "order": 12, "constructorOrder": 3 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 6 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 6, "constructorOrder": 5 }, { "name": "version", - "types": [ - "Int" - ], + "type": "Int", "order": 8, "constructorOrder": 7 }, { "name": "sender", - "types": [ - "Address" - ], + "type": "Address", "order": 11, "constructorOrder": 8 } @@ -1829,108 +1489,79 @@ "fields": [ { "name": "proofs", - "types": [ - "List[ByteVector]" - ], + "type": "List[ByteVector]", "order": 5, "constructorOrder": 12 }, { "name": "feeAssetId", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 3, "constructorOrder": 1 }, { "name": "dApp", - "types": [ - "Alias", - "Address", - "AddressLike" - ], + "type": "Alias|Address|AddressLike", "order": 7, "constructorOrder": 0 }, { "name": "function", - "types": [ - "String" - ], + "type": "String", "order": 10, "constructorOrder": 2 }, { "name": "bodyBytes", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 2, "constructorOrder": 10 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 4, "constructorOrder": 4 }, { "name": "senderPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 9, "constructorOrder": 9 }, { "name": "payments", - "types": [ - "List[AttachedPayment]" - ], + "type": "List[AttachedPayment]", "order": 0, "constructorOrder": 11 }, { "name": "args", - "types": [ - "List[Boolean|ByteVector|Int|List[Boolean|ByteVector|Int|String]|String]" - ], + "type": "List[Boolean|ByteVector|Int|List[Boolean|ByteVector|Int|String]|String]", "order": 12, "constructorOrder": 3 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 6 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 6, "constructorOrder": 5 }, { "name": "version", - "types": [ - "Int" - ], + "type": "Int", "order": 8, "constructorOrder": 7 }, { "name": "sender", - "types": [ - "Address" - ], + "type": "Address", "order": 11, "constructorOrder": 8 } @@ -1947,114 +1578,85 @@ "fields": [ { "name": "proofs", - "types": [ - "List[ByteVector]" - ], + "type": "List[ByteVector]", "order": 12, "constructorOrder": 13 }, { "name": "script", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 7, "constructorOrder": 5 }, { "name": "description", - "types": [ - "String" - ], + "type": "String", "order": 2, "constructorOrder": 2 }, { "name": "name", - "types": [ - "String" - ], + "type": "String", "order": 10, "constructorOrder": 1 }, { "name": "bodyBytes", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 1, "constructorOrder": 12 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 4, "constructorOrder": 6 }, { "name": "senderPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 5, "constructorOrder": 11 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 0, "constructorOrder": 8 }, { "name": "version", - "types": [ - "Int" - ], + "type": "Int", "order": 3, "constructorOrder": 9 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 9, "constructorOrder": 7 }, { "name": "quantity", - "types": [ - "Int" - ], + "type": "Int", "order": 11, "constructorOrder": 0 }, { "name": "decimals", - "types": [ - "Int" - ], + "type": "Int", "order": 13, "constructorOrder": 4 }, { "name": "reissuable", - "types": [ - "Boolean" - ], + "type": "Boolean", "order": 8, "constructorOrder": 3 }, { "name": "sender", - "types": [ - "Address" - ], + "type": "Address", "order": 6, "constructorOrder": 10 } @@ -2071,73 +1673,55 @@ "fields": [ { "name": "proofs", - "types": [ - "List[ByteVector]" - ], + "type": "List[ByteVector]", "order": 7, "constructorOrder": 8 }, { "name": "bodyBytes", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 1, "constructorOrder": 7 }, { "name": "senderPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 4, "constructorOrder": 6 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 3, "constructorOrder": 1 }, { "name": "leaseId", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 5, "constructorOrder": 0 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 0, "constructorOrder": 3 }, { "name": "version", - "types": [ - "Int" - ], + "type": "Int", "order": 2, "constructorOrder": 4 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 8, "constructorOrder": 2 }, { "name": "sender", - "types": [ - "Address" - ], + "type": "Address", "order": 6, "constructorOrder": 5 } @@ -2154,83 +1738,61 @@ "fields": [ { "name": "proofs", - "types": [ - "List[ByteVector]" - ], + "type": "List[ByteVector]", "order": 8, "constructorOrder": 9 }, { "name": "recipient", - "types": [ - "Alias", - "Address", - "AddressLike" - ], + "type": "Alias|Address|AddressLike", "order": 0, "constructorOrder": 1 }, { "name": "bodyBytes", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 2, "constructorOrder": 8 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 5, "constructorOrder": 2 }, { "name": "senderPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 6, "constructorOrder": 7 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 4 }, { "name": "amount", - "types": [ - "Int" - ], + "type": "Int", "order": 3, "constructorOrder": 0 }, { "name": "version", - "types": [ - "Int" - ], + "type": "Int", "order": 4, "constructorOrder": 5 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 9, "constructorOrder": 3 }, { "name": "sender", - "types": [ - "Address" - ], + "type": "Address", "order": 7, "constructorOrder": 6 } @@ -2247,106 +1809,79 @@ "fields": [ { "name": "proofs", - "types": [ - "List[ByteVector]" - ], + "type": "List[ByteVector]", "order": 9, "constructorOrder": 12 }, { "name": "assetId", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 3, "constructorOrder": 0 }, { "name": "bodyBytes", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 2, "constructorOrder": 11 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 4, "constructorOrder": 5 }, { "name": "senderPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 5, "constructorOrder": 10 }, { "name": "attachment", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 6, "constructorOrder": 4 }, { "name": "transfers", - "types": [ - "List[Transfer]" - ], + "type": "List[Transfer]", "order": 8, "constructorOrder": 2 }, { "name": "transferCount", - "types": [ - "Int" - ], + "type": "Int", "order": 0, "constructorOrder": 3 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 7 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 10, "constructorOrder": 6 }, { "name": "totalAmount", - "types": [ - "Int" - ], + "type": "Int", "order": 11, "constructorOrder": 1 }, { "name": "version", - "types": [ - "Int" - ], + "type": "Int", "order": 12, "constructorOrder": 8 }, { "name": "sender", - "types": [ - "Address" - ], + "type": "Address", "order": 7, "constructorOrder": 9 } @@ -2363,83 +1898,61 @@ "fields": [ { "name": "proofs", - "types": [ - "List[ByteVector]" - ], + "type": "List[ByteVector]", "order": 8, "constructorOrder": 9 }, { "name": "recipient", - "types": [ - "Alias", - "Address", - "AddressLike" - ], + "type": "Alias|Address|AddressLike", "order": 0, "constructorOrder": 1 }, { "name": "bodyBytes", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 2, "constructorOrder": 8 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 5, "constructorOrder": 2 }, { "name": "senderPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 6, "constructorOrder": 7 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 4 }, { "name": "amount", - "types": [ - "Int" - ], + "type": "Int", "order": 3, "constructorOrder": 0 }, { "name": "version", - "types": [ - "Int" - ], + "type": "Int", "order": 4, "constructorOrder": 5 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 9, "constructorOrder": 3 }, { "name": "sender", - "types": [ - "Address" - ], + "type": "Address", "order": 7, "constructorOrder": 6 } @@ -2456,89 +1969,67 @@ "fields": [ { "name": "bodyBytes", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 2, "constructorOrder": 9 }, { "name": "proofs", - "types": [ - "List[ByteVector]" - ], + "type": "List[ByteVector]", "order": 8, "constructorOrder": 10 }, { "name": "senderPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 6, "constructorOrder": 8 }, { "name": "assetId", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 3, "constructorOrder": 1 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 5, "constructorOrder": 3 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 5 }, { "name": "version", - "types": [ - "Int" - ], + "type": "Int", "order": 4, "constructorOrder": 6 }, { "name": "quantity", - "types": [ - "Int" - ], + "type": "Int", "order": 0, "constructorOrder": 0 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 10, "constructorOrder": 4 }, { "name": "sender", - "types": [ - "Address" - ], + "type": "Address", "order": 7, "constructorOrder": 7 }, { "name": "reissuable", - "types": [ - "Boolean" - ], + "type": "Boolean", "order": 9, "constructorOrder": 2 } @@ -2555,82 +2046,61 @@ "fields": [ { "name": "proofs", - "types": [ - "List[ByteVector]" - ], + "type": "List[ByteVector]", "order": 8, "constructorOrder": 9 }, { "name": "script", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 7, "constructorOrder": 0 }, { "name": "bodyBytes", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 1, "constructorOrder": 8 }, { "name": "assetId", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 2, "constructorOrder": 1 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 4, "constructorOrder": 2 }, { "name": "senderPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 5, "constructorOrder": 7 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 0, "constructorOrder": 4 }, { "name": "version", - "types": [ - "Int" - ], + "type": "Int", "order": 3, "constructorOrder": 5 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 9, "constructorOrder": 3 }, { "name": "sender", - "types": [ - "Address" - ], + "type": "Address", "order": 6, "constructorOrder": 6 } @@ -2647,74 +2117,55 @@ "fields": [ { "name": "proofs", - "types": [ - "List[ByteVector]" - ], + "type": "List[ByteVector]", "order": 7, "constructorOrder": 8 }, { "name": "script", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 6, "constructorOrder": 0 }, { "name": "bodyBytes", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 1, "constructorOrder": 7 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 3, "constructorOrder": 1 }, { "name": "senderPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 4, "constructorOrder": 6 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 0, "constructorOrder": 3 }, { "name": "version", - "types": [ - "Int" - ], + "type": "Int", "order": 2, "constructorOrder": 4 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 8, "constructorOrder": 2 }, { "name": "sender", - "types": [ - "Address" - ], + "type": "Address", "order": 5, "constructorOrder": 5 } @@ -2731,82 +2182,61 @@ "fields": [ { "name": "proofs", - "types": [ - "List[ByteVector]" - ], + "type": "List[ByteVector]", "order": 7, "constructorOrder": 9 }, { "name": "minSponsoredAssetFee", - "types": [ - "Int", - "Unit" - ], + "type": "Int|Unit", "order": 8, "constructorOrder": 1 }, { "name": "bodyBytes", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 1, "constructorOrder": 8 }, { "name": "assetId", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 2, "constructorOrder": 0 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 4, "constructorOrder": 2 }, { "name": "senderPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 5, "constructorOrder": 7 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 0, "constructorOrder": 4 }, { "name": "version", - "types": [ - "Int" - ], + "type": "Int", "order": 3, "constructorOrder": 5 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 9, "constructorOrder": 3 }, { "name": "sender", - "types": [ - "Address" - ], + "type": "Address", "order": 6, "constructorOrder": 6 } @@ -2823,112 +2253,79 @@ "fields": [ { "name": "assetId", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 3, "constructorOrder": 2 }, { "name": "bodyBytes", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 2, "constructorOrder": 11 }, { "name": "feeAssetId", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 4, "constructorOrder": 0 }, { "name": "version", - "types": [ - "Int", - "Unit" - ], + "type": "Int|Unit", "order": 6, "constructorOrder": 8 }, { "name": "attachment", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 9, "constructorOrder": 4 }, { "name": "proofs", - "types": [ - "List[ByteVector]" - ], + "type": "List[ByteVector]", "order": 11, "constructorOrder": 12 }, { "name": "fee", - "types": [ - "Int", - "Unit" - ], + "type": "Int|Unit", "order": 12, "constructorOrder": 6 }, { "name": "recipient", - "types": [ - "Alias", - "Address", - "AddressLike" - ], + "type": "Alias|Address|AddressLike", "order": 0, "constructorOrder": 3 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 7, "constructorOrder": 5 }, { "name": "senderPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 8, "constructorOrder": 10 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 7 }, { "name": "amount", - "types": [ - "Int" - ], + "type": "Int", "order": 5, "constructorOrder": 1 }, { "name": "sender", - "types": [ - "Address" - ], + "type": "Address", "order": 10, "constructorOrder": 9 } @@ -2945,90 +2342,67 @@ "fields": [ { "name": "proofs", - "types": [ - "List[ByteVector]" - ], + "type": "List[ByteVector]", "order": 9, "constructorOrder": 10 }, { "name": "assetId", - "types": [ - "ByteVector", - "Unit" - ], + "type": "ByteVector|Unit", "order": 3, "constructorOrder": 0 }, { "name": "name", - "types": [ - "String" - ], + "type": "String", "order": 0, "constructorOrder": 1 }, { "name": "description", - "types": [ - "String" - ], + "type": "String", "order": 4, "constructorOrder": 2 }, { "name": "bodyBytes", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 2, "constructorOrder": 9 }, { "name": "id", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 6, "constructorOrder": 3 }, { "name": "senderPublicKey", - "types": [ - "ByteVector" - ], + "type": "ByteVector", "order": 7, "constructorOrder": 8 }, { "name": "timestamp", - "types": [ - "Int" - ], + "type": "Int", "order": 1, "constructorOrder": 5 }, { "name": "version", - "types": [ - "Int" - ], + "type": "Int", "order": 5, "constructorOrder": 6 }, { "name": "fee", - "types": [ - "Int" - ], + "type": "Int", "order": 10, "constructorOrder": 4 }, { "name": "sender", - "types": [ - "Address" - ], + "type": "Address", "order": 8, "constructorOrder": 7 } diff --git a/pkg/ride/compiler/stdlib/structs.go b/pkg/ride/compiler/stdlib/structs.go index a7716f520..8b1f93ad7 100644 --- a/pkg/ride/compiler/stdlib/structs.go +++ b/pkg/ride/compiler/stdlib/structs.go @@ -9,9 +9,9 @@ import ( ) type actionField struct { - Name string `json:"name"` - Types []string `json:"types"` - ConstructorOrder int `json:"constructorOrder"` // order for constructor + Name string `json:"name"` + Type string `json:"type"` + ConstructorOrder int `json:"constructorOrder"` // order for constructor } type actionsObject struct { @@ -119,21 +119,6 @@ func ObjectsByVersion() map[ast.LibraryVersion]ObjectsSignatures { return objectsByVersion } -func parseObjectFieldsTypes(rawTypes []string) Type { - var types []string - for _, t := range rawTypes { - // AddressLike Type doesn't exist in ride, it only uses in evaluator - if t == "AddressLike" { - continue - } - types = append(types, t) - } - - resRawType := strings.Join(types, "|") - - return ParseType(resRawType) -} - func appendRemainingStructs(s *rideObjects) { remainingObjects := []rideObject{ { @@ -144,8 +129,8 @@ func appendRemainingStructs(s *rideObjects) { Deleted: nil, Fields: []actionField{ { - Name: "bytes", - Types: []string{"ByteVector"}, + Name: "bytes", + Type: "ByteVector", }, }, }, @@ -159,8 +144,8 @@ func appendRemainingStructs(s *rideObjects) { Deleted: nil, Fields: []actionField{ { - Name: "alias", - Types: []string{"String"}, + Name: "alias", + Type: "String", }, }, }, @@ -177,16 +162,16 @@ func changeRideTypeFields(name string, fields []actionField) []actionField { for i := range fields { switch fields[i].Name { case "assetPair": - fields[i].Types = []string{"AssetPair"} + fields[i].Type = "AssetPair" case "orderType": - fields[i].Types = []string{"Buy", "Sell"} + fields[i].Type = "Buy|Sell" } } case "ExchangeTransaction": for i := range fields { switch fields[i].Name { case "sellOrder", "buyOrder": - fields[i].Types = []string{"Order"} + fields[i].Type = "Order" } } } @@ -210,6 +195,7 @@ func mustLoadObjects() map[ast.LibraryVersion]ObjectsSignatures { ast.LibV4: {map[string]ObjectInfo{}}, ast.LibV5: {map[string]ObjectInfo{}}, ast.LibV6: {map[string]ObjectInfo{}}, + ast.LibV7: {map[string]ObjectInfo{}}, } for _, obj := range s.Objects { sort.SliceStable(obj.Actions, func(i, j int) bool { @@ -224,7 +210,7 @@ func mustLoadObjects() map[ast.LibraryVersion]ObjectsSignatures { for _, f := range ver.Fields { resInfo.Fields = append(resInfo.Fields, ObjectField{ Name: f.Name, - Type: parseObjectFieldsTypes(f.Types), + Type: ParseType(f.Type), }) } if strings.HasSuffix(obj.Name, "Transaction") { diff --git a/pkg/ride/compiler/stdlib/types.go b/pkg/ride/compiler/stdlib/types.go index a1dc6b122..13618d9d5 100644 --- a/pkg/ride/compiler/stdlib/types.go +++ b/pkg/ride/compiler/stdlib/types.go @@ -73,6 +73,14 @@ var ( ) func ParseType(t string) Type { + return parseType(t, true) +} + +func ParseRuntimeType(t string) Type { + return parseType(t, false) +} + +func parseType(t string, dropRuntimeTypes bool) Type { p := Types{Buffer: t} err := p.Init() if err != nil { @@ -83,47 +91,53 @@ func ParseType(t string) Type { panic(err) } node := p.AST() - return handleTypes(node.up, t) + return handleTypes(node.up, t, dropRuntimeTypes) } -func handleTypes(node *node32, t string) Type { +func handleTypes(node *node32, s string, dropRuntimeTypes bool) Type { curNode := node.up - var T Type + var t Type switch curNode.pegRule { case ruleGenericType: - T = handleGeneric(curNode, t) + t = handleGeneric(curNode, s, dropRuntimeTypes) case ruleTupleType: - T = handleTupleType(curNode, t) + t = handleTupleType(curNode, s, dropRuntimeTypes) case ruleType: // check Types - stringType := t[curNode.begin:curNode.end] + stringType := s[curNode.begin:curNode.end] switch stringType { case "Any": - T = AnyType + t = AnyType case "Unknown": - T = ThrowType + t = ThrowType + case "AddressLike": // Replace implementation specific AddressLike with Address, duplications handled later + if dropRuntimeTypes { + t = SimpleType{Type: "Address"} + } else { + t = SimpleType{Type: "AddressLike"} + } default: - T = SimpleType{stringType} + t = SimpleType{stringType} } } curNode = curNode.next if curNode == nil { - return T + return t } resType := UnionType{Types: []Type{}} - resType.Types = append(resType.Types, T) + resType.AppendType(t) if curNode.pegRule == rule_ { curNode = curNode.next } if curNode.pegRule == rule_ { curNode = curNode.next } - resType.Types = append(resType.Types, handleTypes(curNode, t)) + resType.AppendType(handleTypes(curNode, s, dropRuntimeTypes)) return resType } -func handleTupleType(node *node32, t string) Type { +func handleTupleType(node *node32, t string, dropRuntimeTypes bool) Type { curNode := node.up var tupleTypes []Type for { @@ -131,7 +145,7 @@ func handleTupleType(node *node32, t string) Type { curNode = curNode.next } if curNode.pegRule == ruleTypes { - tupleTypes = append(tupleTypes, handleTypes(curNode, t)) + tupleTypes = append(tupleTypes, handleTypes(curNode, t, dropRuntimeTypes)) curNode = curNode.next } if curNode == nil { @@ -141,7 +155,7 @@ func handleTupleType(node *node32, t string) Type { return TupleType{tupleTypes} } -func handleGeneric(node *node32, t string) Type { +func handleGeneric(node *node32, t string, dropRuntimeTypes bool) Type { curNode := node.up name := t[curNode.begin:curNode.end] if name != "List" { @@ -158,7 +172,7 @@ func handleGeneric(node *node32, t string) Type { curNode = curNode.next } - return ListType{Type: handleTypes(curNode, t)} + return ListType{Type: handleTypes(curNode, t, dropRuntimeTypes)} } type throwType struct{} @@ -167,13 +181,13 @@ func (t throwType) String() string { return "Unknown" } -func (t throwType) Equal(rideType Type) bool { - _, ok := rideType.(throwType) +func (t throwType) Equal(other Type) bool { + _, ok := other.(throwType) return ok } -func (t throwType) EqualWithEntry(rideType Type) bool { - return t.Equal(rideType) +func (t throwType) EqualWithEntry(other Type) bool { + return t.Equal(other) } type anyType struct{} @@ -182,8 +196,8 @@ func (t anyType) String() string { return "Any" } -func (t anyType) Equal(rideType Type) bool { - _, ok := rideType.(anyType) +func (t anyType) Equal(other Type) bool { + _, ok := other.(anyType) return ok } @@ -195,13 +209,13 @@ type SimpleType struct { Type string } -func (t SimpleType) EqualWithEntry(rideType Type) bool { - return t.Equal(rideType) +func (t SimpleType) EqualWithEntry(other Type) bool { + return t.Equal(other) } -func (t SimpleType) Equal(rideType Type) bool { - if T, ok := rideType.(SimpleType); ok { - return t.Type == T.Type +func (t SimpleType) Equal(other Type) bool { + if o, ok := other.(SimpleType); ok { + return t.Type == o.Type } return false } @@ -214,11 +228,11 @@ type UnionType struct { Types []Type } -func (t UnionType) Equal(rideType Type) bool { - if T, ok := rideType.(UnionType); ok { - for _, typeName := range T.Types { - for _, checkTypeName := range t.Types { - if !checkTypeName.Equal(typeName) { +func (t UnionType) Equal(other Type) bool { + if o, ok := other.(UnionType); ok { + for _, ot := range o.Types { + for _, tt := range t.Types { + if !tt.Equal(ot) { return false } } @@ -228,15 +242,15 @@ func (t UnionType) Equal(rideType Type) bool { return false } -func (t UnionType) EqualWithEntry(rideType Type) bool { - switch T := rideType.(type) { +func (t UnionType) EqualWithEntry(other Type) bool { + switch o := other.(type) { case anyType: return false case UnionType: - for _, typeName := range T.Types { + for _, ot := range o.Types { eq := false - for _, checkTypeName := range t.Types { - if checkTypeName.EqualWithEntry(typeName) { + for _, tt := range t.Types { + if tt.EqualWithEntry(ot) { eq = true break } @@ -247,8 +261,8 @@ func (t UnionType) EqualWithEntry(rideType Type) bool { } return true default: - for _, typeName := range t.Types { - if typeName.EqualWithEntry(rideType) { + for _, tt := range t.Types { + if tt.EqualWithEntry(other) { return true } } @@ -328,12 +342,12 @@ func (t *UnionType) AppendType(rideType Type) { } func (t UnionType) String() string { - var stringTypes []string - for _, T := range t.Types { - stringTypes = append(stringTypes, T.String()) + var types []string + for _, tt := range t.Types { + types = append(types, tt.String()) } - sort.Strings(stringTypes) - return strings.Join(stringTypes, "|") + sort.Strings(types) + return strings.Join(types, "|") } func (t UnionType) Simplify() Type { @@ -355,32 +369,32 @@ type ListType struct { Type Type } -func (t ListType) Equal(rideType Type) bool { - T, ok := rideType.(ListType) +func (t ListType) Equal(other Type) bool { + o, ok := other.(ListType) if !ok { return false } - if t.Type == nil && T.Type == nil { + if t.Type == nil && o.Type == nil { return true } - if t.Type == nil || T.Type == nil { + if t.Type == nil || o.Type == nil { return false } - return t.Type.Equal(T.Type) + return t.Type.Equal(o.Type) } -func (t ListType) EqualWithEntry(rideType Type) bool { - if T, ok := rideType.(ListType); ok { - if t.Type == nil && T.Type == nil { +func (t ListType) EqualWithEntry(other Type) bool { + if o, ok := other.(ListType); ok { + if t.Type == nil && o.Type == nil { return true } if t.Type == nil { return false } - if T.Type == nil { + if o.Type == nil { return true } - return t.Type.EqualWithEntry(T.Type) + return t.Type.EqualWithEntry(o.Type) } return false } @@ -404,10 +418,10 @@ func (t *ListType) AppendType(rideType Type) { } func (t *ListType) AppendList(rideType Type) { - T := rideType.(ListType) + o := rideType.(ListType) union := UnionType{Types: []Type{}} union.AppendType(t.Type) - union.AppendType(T.Type) + union.AppendType(o.Type) if len(union.Types) == 1 { t.Type = union.Types[0] } else { @@ -419,38 +433,38 @@ type TupleType struct { Types []Type } -func (t TupleType) Equal(rideType Type) bool { - T, ok := rideType.(TupleType) +func (t TupleType) Equal(other Type) bool { + o, ok := other.(TupleType) if !ok { return false } - if len(T.Types) != len(t.Types) { + if len(o.Types) != len(t.Types) { return false } for i := 0; i < len(t.Types); i++ { - if t.Types[i] == nil || T.Types[i] == nil { + if t.Types[i] == nil || o.Types[i] == nil { continue } - if !t.Types[i].Equal(T.Types[i]) { + if !t.Types[i].Equal(o.Types[i]) { return false } } return true } -func (t TupleType) EqualWithEntry(rideType Type) bool { - T, ok := rideType.(TupleType) +func (t TupleType) EqualWithEntry(other Type) bool { + o, ok := other.(TupleType) if !ok { return false } - if len(T.Types) != len(t.Types) { + if len(o.Types) != len(t.Types) { return false } for i := 0; i < len(t.Types); i++ { - if t.Types[i] == nil || T.Types[i] == nil { + if t.Types[i] == nil || o.Types[i] == nil { continue } - if !t.Types[i].EqualWithEntry(T.Types[i]) { + if !t.Types[i].EqualWithEntry(o.Types[i]) { return false } } @@ -475,7 +489,7 @@ func (t TupleType) String() string { } func loadNonConfigTypes(res map[ast.LibraryVersion]map[string]Type) { - for v := ast.LibV1; v <= ast.LibV6; v++ { + for v := ast.LibV1; v <= ast.CurrentMaxLibraryVersion(); v++ { res[v]["Int"] = IntType res[v]["String"] = StringType res[v]["Boolean"] = BooleanType @@ -492,16 +506,16 @@ func loadNonConfigTypes(res map[ast.LibraryVersion]map[string]Type) { res[v]["HalfDown"] = SimpleType{Type: "HalfDown"} res[v]["Up"] = SimpleType{Type: "Up"} } - for v := ast.LibV2; v <= ast.LibV6; v++ { + for v := ast.LibV2; v <= ast.CurrentMaxLibraryVersion(); v++ { res[v]["OrderType"] = SimpleType{Type: "OrderType"} } - for v := ast.LibV3; v <= ast.LibV6; v++ { + for v := ast.LibV3; v <= ast.CurrentMaxLibraryVersion(); v++ { res[v]["DigestAlgorithmType"] = SimpleType{Type: "DigestAlgorithmType"} } - for v := ast.LibV4; v <= ast.LibV6; v++ { + for v := ast.LibV4; v <= ast.CurrentMaxLibraryVersion(); v++ { res[v]["BlockInfo"] = SimpleType{Type: "BlockInfo"} } - for v := ast.LibV5; v <= ast.LibV6; v++ { + for v := ast.LibV5; v <= ast.CurrentMaxLibraryVersion(); v++ { res[v]["BigInt"] = BigIntType } @@ -574,6 +588,7 @@ func loadNonConfigTypes(res map[ast.LibraryVersion]map[string]Type) { SimpleType{"SponsorFeeTransaction"}, SimpleType{"DataTransaction"}, }} + res[ast.LibV7]["Transaction"] = res[ast.LibV6]["Transaction"] } func mustLoadDefaultTypes() map[ast.LibraryVersion]map[string]Type { @@ -596,6 +611,9 @@ func mustLoadDefaultTypes() map[ast.LibraryVersion]map[string]Type { ast.LibV6: { "Transaction": UnionType{Types: []Type{}}, }, + ast.LibV7: { + "Transaction": UnionType{Types: []Type{}}, + }, } f, err := embedFS.ReadFile("ride_objects.json") diff --git a/pkg/ride/compiler/stdlib/vars.json b/pkg/ride/compiler/stdlib/vars.json index cc86cae5f..b0a7e6cc5 100644 --- a/pkg/ride/compiler/stdlib/vars.json +++ b/pkg/ride/compiler/stdlib/vars.json @@ -118,6 +118,7 @@ "UP" ] }, + {}, {} ] } diff --git a/pkg/ride/constants.gen.go b/pkg/ride/constants.gen.go index 7d059a5da..300f7cd61 100644 --- a/pkg/ride/constants.gen.go +++ b/pkg/ride/constants.gen.go @@ -140,6 +140,29 @@ func checkConstantV6(name string) (uint16, bool) { return 0, false } +var ConstantsV7 = []string{"Buy", "CEILING", "DOWN", "FLOOR", "HALFEVEN", "HALFUP", "MD5", "NOALG", "SHA1", "SHA224", "SHA256", "SHA3224", "SHA3256", "SHA3384", "SHA3512", "SHA384", "SHA512", "Sell", "height", "lastBlock", "nil", "this", "tx", "unit"} + +const _constants_V7 = "BuyCEILINGDOWNFLOORHALFEVENHALFUPMD5NOALGSHA1SHA224SHA256SHA3224SHA3256SHA3384SHA3512SHA384SHA512SellheightlastBlocknilthistxunit" + +var _constructors_V7 = [...]rideConstructor{newBuy, newCeiling, newDown, newFloor, newHalfEven, newHalfUp, newMd5, newNoAlg, newSha1, newSha224, newSha256, newSha3224, newSha3256, newSha3384, newSha3512, newSha384, newSha512, newSell, newHeight, newLastBlock, newNil, newThis, newTx, newUnit} +var _c_index_V7 = [...]int{0, 3, 10, 14, 19, 27, 33, 36, 41, 45, 51, 57, 64, 71, 78, 85, 91, 97, 101, 107, 116, 119, 123, 125, 129} + +func constantV7(id int) rideConstructor { + if id < 0 || id > 23 { + return nil + } + return _constructors_V7[id] +} + +func checkConstantV7(name string) (uint16, bool) { + for i := 0; i <= 23; i++ { + if _constants_V7[_c_index_V7[i]:_c_index_V7[i+1]] == name { + return uint16(i), true + } + } + return 0, false +} + func newBuy(environment) rideType { return rideNamedType{name: "Buy"} } diff --git a/pkg/ride/constraints.go b/pkg/ride/constraints.go index ba00eae74..2ea6a54f9 100644 --- a/pkg/ride/constraints.go +++ b/pkg/ride/constraints.go @@ -24,7 +24,7 @@ func MaxChainInvokeComplexityByVersion(version ast.LibraryVersion) (uint32, erro return maxChainInvokeComplexityV3V4, nil case ast.LibV5: return maxChainInvokeComplexityV5, nil - case ast.LibV6: + case ast.LibV6, ast.LibV7: return maxChainInvokeComplexityV6, nil default: return 0, errors.Errorf("unsupported library version %d", version) diff --git a/pkg/ride/constructors.gen.go b/pkg/ride/constructors.gen.go index 88f30bd7a..36a706505 100644 --- a/pkg/ride/constructors.gen.go +++ b/pkg/ride/constructors.gen.go @@ -290,6 +290,71 @@ func blockInfoV4Constructor(_ environment, args_ ...rideType) (rideType, error) return newRideBlockInfoV4(vrf, generationSignature, generatorPublicKey, baseTarget, timestamp, height, generator), nil } +func blockInfoV7Constructor(_ environment, args_ ...rideType) (rideType, error) { + if err := checkArgs(args_, 8); err != nil { + return nil, errors.Wrap(err, "blockInfoV7Constructor") + } + + timestamp, ok := args_[0].(rideInt) + if !ok { + return nil, errors.Errorf("blockInfoV7Constructor: unexpected type '%s' for timestamp", args_[0].instanceOf()) + } + + height, ok := args_[1].(rideInt) + if !ok { + return nil, errors.Errorf("blockInfoV7Constructor: unexpected type '%s' for height", args_[1].instanceOf()) + } + + baseTarget, ok := args_[2].(rideInt) + if !ok { + return nil, errors.Errorf("blockInfoV7Constructor: unexpected type '%s' for baseTarget", args_[2].instanceOf()) + } + + generationSignature, ok := args_[3].(rideByteVector) + if !ok { + return nil, errors.Errorf("blockInfoV7Constructor: unexpected type '%s' for generationSignature", args_[3].instanceOf()) + } + + generator, ok := args_[4].(rideAddress) + if !ok { + return nil, errors.Errorf("blockInfoV7Constructor: unexpected type '%s' for generator", args_[4].instanceOf()) + } + + generatorPublicKey, ok := args_[5].(rideByteVector) + if !ok { + return nil, errors.Errorf("blockInfoV7Constructor: unexpected type '%s' for generatorPublicKey", args_[5].instanceOf()) + } + + var vrf rideType + switch v := args_[6].(type) { + case rideByteVector, rideUnit: + vrf = v + default: + return nil, errors.Errorf("blockInfoV7Constructor: unexpected type '%s' for vrf", args_[6].instanceOf()) + } + + rewards, ok := args_[7].(rideList) + if !ok { + return nil, errors.Errorf("blockInfoV7Constructor: unexpected type '%s' for rewards", args_[7].instanceOf()) + } + // checks for list elements + for _, el := range rewards { + switch te := el.(type) { + case tuple2: + if _, ok := te.el1.(rideAddress); !ok { + return nil, errors.Errorf("blockInfoV7Constructor: unexpected type '%s' of element 1 in rewards list tuple", te.el1.instanceOf()) + } + if _, ok := te.el2.(rideInt); !ok { + return nil, errors.Errorf("blockInfoV7Constructor: unexpected type '%s' of element 2 in rewards list tuple", te.el2.instanceOf()) + } + default: + return nil, errors.Errorf("blockInfoV7Constructor: unexpected type '%s' in rewards list", te.instanceOf()) + } + } + + return newRideBlockInfoV7(vrf, generationSignature, generatorPublicKey, baseTarget, timestamp, height, generator, rewards), nil +} + func booleanEntryConstructor(_ environment, args_ ...rideType) (rideType, error) { if err := checkArgs(args_, 2); err != nil { return nil, errors.Wrap(err, "booleanEntryConstructor") @@ -432,11 +497,11 @@ func invocationV4Constructor(_ environment, args_ ...rideType) (rideType, error) return nil, errors.Errorf("invocationV4Constructor: unexpected type '%s' for payments", args_[0].instanceOf()) } // checks for list elements - for _, elem := range payments { - switch t := elem.(type) { + for _, el := range payments { + switch te := el.(type) { case rideAttachedPayment: default: - return nil, errors.Errorf("invocationV4Constructor: unexpected type '%s' in payments list", t.instanceOf()) + return nil, errors.Errorf("invocationV4Constructor: unexpected type '%s' in payments list", te.instanceOf()) } } @@ -481,11 +546,11 @@ func invocationV5Constructor(_ environment, args_ ...rideType) (rideType, error) return nil, errors.Errorf("invocationV5Constructor: unexpected type '%s' for payments", args_[0].instanceOf()) } // checks for list elements - for _, elem := range payments { - switch t := elem.(type) { + for _, el := range payments { + switch te := el.(type) { case rideAttachedPayment: default: - return nil, errors.Errorf("invocationV5Constructor: unexpected type '%s' in payments list", t.instanceOf()) + return nil, errors.Errorf("invocationV5Constructor: unexpected type '%s' in payments list", te.instanceOf()) } } @@ -696,11 +761,11 @@ func orderConstructor(_ environment, args_ ...rideType) (rideType, error) { return nil, errors.Errorf("orderConstructor: unexpected type '%s' for proofs", args_[13].instanceOf()) } // checks for list elements - for _, elem := range proofs { - switch t := elem.(type) { + for _, el := range proofs { + switch te := el.(type) { case rideByteVector: default: - return nil, errors.Errorf("orderConstructor: unexpected type '%s' in proofs list", t.instanceOf()) + return nil, errors.Errorf("orderConstructor: unexpected type '%s' in proofs list", te.instanceOf()) } } @@ -844,11 +909,11 @@ func transferSetConstructor(_ environment, args_ ...rideType) (rideType, error) return nil, errors.Errorf("transferSetConstructor: unexpected type '%s' for transfers", args_[0].instanceOf()) } // checks for list elements - for _, elem := range transfers { - switch t := elem.(type) { + for _, el := range transfers { + switch te := el.(type) { case rideScriptTransfer: default: - return nil, errors.Errorf("transferSetConstructor: unexpected type '%s' in transfers list", t.instanceOf()) + return nil, errors.Errorf("transferSetConstructor: unexpected type '%s' in transfers list", te.instanceOf()) } } @@ -865,11 +930,11 @@ func writeSetConstructor(_ environment, args_ ...rideType) (rideType, error) { return nil, errors.Errorf("writeSetConstructor: unexpected type '%s' for data", args_[0].instanceOf()) } // checks for list elements - for _, elem := range data { - switch t := elem.(type) { + for _, el := range data { + switch te := el.(type) { case rideDataEntry: default: - return nil, errors.Errorf("writeSetConstructor: unexpected type '%s' in data list", t.instanceOf()) + return nil, errors.Errorf("writeSetConstructor: unexpected type '%s' in data list", te.instanceOf()) } } @@ -931,11 +996,11 @@ func burnTransactionConstructor(_ environment, args_ ...rideType) (rideType, err return nil, errors.Errorf("burnTransactionConstructor: unexpected type '%s' for proofs", args_[9].instanceOf()) } // checks for list elements - for _, elem := range proofs { - switch t := elem.(type) { + for _, el := range proofs { + switch te := el.(type) { case rideByteVector: default: - return nil, errors.Errorf("burnTransactionConstructor: unexpected type '%s' in proofs list", t.instanceOf()) + return nil, errors.Errorf("burnTransactionConstructor: unexpected type '%s' in proofs list", te.instanceOf()) } } @@ -992,11 +1057,11 @@ func createAliasTransactionConstructor(_ environment, args_ ...rideType) (rideTy return nil, errors.Errorf("createAliasTransactionConstructor: unexpected type '%s' for proofs", args_[8].instanceOf()) } // checks for list elements - for _, elem := range proofs { - switch t := elem.(type) { + for _, el := range proofs { + switch te := el.(type) { case rideByteVector: default: - return nil, errors.Errorf("createAliasTransactionConstructor: unexpected type '%s' in proofs list", t.instanceOf()) + return nil, errors.Errorf("createAliasTransactionConstructor: unexpected type '%s' in proofs list", te.instanceOf()) } } @@ -1013,11 +1078,11 @@ func dataTransactionConstructor(_ environment, args_ ...rideType) (rideType, err return nil, errors.Errorf("dataTransactionConstructor: unexpected type '%s' for data", args_[0].instanceOf()) } // checks for list elements - for _, elem := range data { - switch t := elem.(type) { + for _, el := range data { + switch te := el.(type) { case rideBinaryEntry, rideBooleanEntry, rideDeleteEntry, rideIntegerEntry, rideStringEntry: default: - return nil, errors.Errorf("dataTransactionConstructor: unexpected type '%s' in data list", t.instanceOf()) + return nil, errors.Errorf("dataTransactionConstructor: unexpected type '%s' in data list", te.instanceOf()) } } @@ -1061,11 +1126,11 @@ func dataTransactionConstructor(_ environment, args_ ...rideType) (rideType, err return nil, errors.Errorf("dataTransactionConstructor: unexpected type '%s' for proofs", args_[8].instanceOf()) } // checks for list elements - for _, elem := range proofs { - switch t := elem.(type) { + for _, el := range proofs { + switch te := el.(type) { case rideByteVector: default: - return nil, errors.Errorf("dataTransactionConstructor: unexpected type '%s' in proofs list", t.instanceOf()) + return nil, errors.Errorf("dataTransactionConstructor: unexpected type '%s' in proofs list", te.instanceOf()) } } @@ -1147,11 +1212,11 @@ func exchangeTransactionConstructor(_ environment, args_ ...rideType) (rideType, return nil, errors.Errorf("exchangeTransactionConstructor: unexpected type '%s' for proofs", args_[13].instanceOf()) } // checks for list elements - for _, elem := range proofs { - switch t := elem.(type) { + for _, el := range proofs { + switch te := el.(type) { case rideByteVector: default: - return nil, errors.Errorf("exchangeTransactionConstructor: unexpected type '%s' in proofs list", t.instanceOf()) + return nil, errors.Errorf("exchangeTransactionConstructor: unexpected type '%s' in proofs list", te.instanceOf()) } } @@ -1257,11 +1322,11 @@ func invokeExpressionTransactionConstructor(_ environment, args_ ...rideType) (r return nil, errors.Errorf("invokeExpressionTransactionConstructor: unexpected type '%s' for proofs", args_[9].instanceOf()) } // checks for list elements - for _, elem := range proofs { - switch t := elem.(type) { + for _, el := range proofs { + switch te := el.(type) { case rideByteVector: default: - return nil, errors.Errorf("invokeExpressionTransactionConstructor: unexpected type '%s' in proofs list", t.instanceOf()) + return nil, errors.Errorf("invokeExpressionTransactionConstructor: unexpected type '%s' in proofs list", te.instanceOf()) } } @@ -1299,19 +1364,19 @@ func invokeScriptTransactionV3Constructor(_ environment, args_ ...rideType) (rid return nil, errors.Errorf("invokeScriptTransactionV3Constructor: unexpected type '%s' for args", args_[3].instanceOf()) } // checks for list elements - for _, elem := range args { - switch t := elem.(type) { + for _, el := range args { + switch te := el.(type) { case rideList: - for _, elem := range t { - switch t := elem.(type) { + for _, el := range te { + switch te := el.(type) { case rideBoolean, rideByteVector, rideInt, rideString: default: - return nil, errors.Errorf("invokeScriptTransactionV3Constructor: unexpected type '%s' in args list", t.instanceOf()) + return nil, errors.Errorf("invokeScriptTransactionV3Constructor: unexpected type '%s' in args list", te.instanceOf()) } } case rideBoolean, rideByteVector, rideInt, rideString: default: - return nil, errors.Errorf("invokeScriptTransactionV3Constructor: unexpected type '%s' in args list", t.instanceOf()) + return nil, errors.Errorf("invokeScriptTransactionV3Constructor: unexpected type '%s' in args list", te.instanceOf()) } } @@ -1363,11 +1428,11 @@ func invokeScriptTransactionV3Constructor(_ environment, args_ ...rideType) (rid return nil, errors.Errorf("invokeScriptTransactionV3Constructor: unexpected type '%s' for proofs", args_[12].instanceOf()) } // checks for list elements - for _, elem := range proofs { - switch t := elem.(type) { + for _, el := range proofs { + switch te := el.(type) { case rideByteVector: default: - return nil, errors.Errorf("invokeScriptTransactionV3Constructor: unexpected type '%s' in proofs list", t.instanceOf()) + return nil, errors.Errorf("invokeScriptTransactionV3Constructor: unexpected type '%s' in proofs list", te.instanceOf()) } } @@ -1405,19 +1470,19 @@ func invokeScriptTransactionV4Constructor(_ environment, args_ ...rideType) (rid return nil, errors.Errorf("invokeScriptTransactionV4Constructor: unexpected type '%s' for args", args_[3].instanceOf()) } // checks for list elements - for _, elem := range args { - switch t := elem.(type) { + for _, el := range args { + switch te := el.(type) { case rideList: - for _, elem := range t { - switch t := elem.(type) { + for _, el := range te { + switch te := el.(type) { case rideBoolean, rideByteVector, rideInt, rideString: default: - return nil, errors.Errorf("invokeScriptTransactionV4Constructor: unexpected type '%s' in args list", t.instanceOf()) + return nil, errors.Errorf("invokeScriptTransactionV4Constructor: unexpected type '%s' in args list", te.instanceOf()) } } case rideBoolean, rideByteVector, rideInt, rideString: default: - return nil, errors.Errorf("invokeScriptTransactionV4Constructor: unexpected type '%s' in args list", t.instanceOf()) + return nil, errors.Errorf("invokeScriptTransactionV4Constructor: unexpected type '%s' in args list", te.instanceOf()) } } @@ -1461,11 +1526,11 @@ func invokeScriptTransactionV4Constructor(_ environment, args_ ...rideType) (rid return nil, errors.Errorf("invokeScriptTransactionV4Constructor: unexpected type '%s' for payments", args_[11].instanceOf()) } // checks for list elements - for _, elem := range payments { - switch t := elem.(type) { + for _, el := range payments { + switch te := el.(type) { case rideAttachedPayment: default: - return nil, errors.Errorf("invokeScriptTransactionV4Constructor: unexpected type '%s' in payments list", t.instanceOf()) + return nil, errors.Errorf("invokeScriptTransactionV4Constructor: unexpected type '%s' in payments list", te.instanceOf()) } } @@ -1474,11 +1539,11 @@ func invokeScriptTransactionV4Constructor(_ environment, args_ ...rideType) (rid return nil, errors.Errorf("invokeScriptTransactionV4Constructor: unexpected type '%s' for proofs", args_[12].instanceOf()) } // checks for list elements - for _, elem := range proofs { - switch t := elem.(type) { + for _, el := range proofs { + switch te := el.(type) { case rideByteVector: default: - return nil, errors.Errorf("invokeScriptTransactionV4Constructor: unexpected type '%s' in proofs list", t.instanceOf()) + return nil, errors.Errorf("invokeScriptTransactionV4Constructor: unexpected type '%s' in proofs list", te.instanceOf()) } } @@ -1563,11 +1628,11 @@ func issueTransactionConstructor(_ environment, args_ ...rideType) (rideType, er return nil, errors.Errorf("issueTransactionConstructor: unexpected type '%s' for proofs", args_[13].instanceOf()) } // checks for list elements - for _, elem := range proofs { - switch t := elem.(type) { + for _, el := range proofs { + switch te := el.(type) { case rideByteVector: default: - return nil, errors.Errorf("issueTransactionConstructor: unexpected type '%s' in proofs list", t.instanceOf()) + return nil, errors.Errorf("issueTransactionConstructor: unexpected type '%s' in proofs list", te.instanceOf()) } } @@ -1624,11 +1689,11 @@ func leaseCancelTransactionConstructor(_ environment, args_ ...rideType) (rideTy return nil, errors.Errorf("leaseCancelTransactionConstructor: unexpected type '%s' for proofs", args_[8].instanceOf()) } // checks for list elements - for _, elem := range proofs { - switch t := elem.(type) { + for _, el := range proofs { + switch te := el.(type) { case rideByteVector: default: - return nil, errors.Errorf("leaseCancelTransactionConstructor: unexpected type '%s' in proofs list", t.instanceOf()) + return nil, errors.Errorf("leaseCancelTransactionConstructor: unexpected type '%s' in proofs list", te.instanceOf()) } } @@ -1693,11 +1758,11 @@ func leaseTransactionConstructor(_ environment, args_ ...rideType) (rideType, er return nil, errors.Errorf("leaseTransactionConstructor: unexpected type '%s' for proofs", args_[9].instanceOf()) } // checks for list elements - for _, elem := range proofs { - switch t := elem.(type) { + for _, el := range proofs { + switch te := el.(type) { case rideByteVector: default: - return nil, errors.Errorf("leaseTransactionConstructor: unexpected type '%s' in proofs list", t.instanceOf()) + return nil, errors.Errorf("leaseTransactionConstructor: unexpected type '%s' in proofs list", te.instanceOf()) } } @@ -1727,11 +1792,11 @@ func massTransferTransactionConstructor(_ environment, args_ ...rideType) (rideT return nil, errors.Errorf("massTransferTransactionConstructor: unexpected type '%s' for transfers", args_[2].instanceOf()) } // checks for list elements - for _, elem := range transfers { - switch t := elem.(type) { + for _, el := range transfers { + switch te := el.(type) { case rideTransfer: default: - return nil, errors.Errorf("massTransferTransactionConstructor: unexpected type '%s' in transfers list", t.instanceOf()) + return nil, errors.Errorf("massTransferTransactionConstructor: unexpected type '%s' in transfers list", te.instanceOf()) } } @@ -1785,11 +1850,11 @@ func massTransferTransactionConstructor(_ environment, args_ ...rideType) (rideT return nil, errors.Errorf("massTransferTransactionConstructor: unexpected type '%s' for proofs", args_[12].instanceOf()) } // checks for list elements - for _, elem := range proofs { - switch t := elem.(type) { + for _, el := range proofs { + switch te := el.(type) { case rideByteVector: default: - return nil, errors.Errorf("massTransferTransactionConstructor: unexpected type '%s' in proofs list", t.instanceOf()) + return nil, errors.Errorf("massTransferTransactionConstructor: unexpected type '%s' in proofs list", te.instanceOf()) } } @@ -1854,11 +1919,11 @@ func paymentTransactionConstructor(_ environment, args_ ...rideType) (rideType, return nil, errors.Errorf("paymentTransactionConstructor: unexpected type '%s' for proofs", args_[9].instanceOf()) } // checks for list elements - for _, elem := range proofs { - switch t := elem.(type) { + for _, el := range proofs { + switch te := el.(type) { case rideByteVector: default: - return nil, errors.Errorf("paymentTransactionConstructor: unexpected type '%s' in proofs list", t.instanceOf()) + return nil, errors.Errorf("paymentTransactionConstructor: unexpected type '%s' in proofs list", te.instanceOf()) } } @@ -1925,11 +1990,11 @@ func reissueTransactionConstructor(_ environment, args_ ...rideType) (rideType, return nil, errors.Errorf("reissueTransactionConstructor: unexpected type '%s' for proofs", args_[10].instanceOf()) } // checks for list elements - for _, elem := range proofs { - switch t := elem.(type) { + for _, el := range proofs { + switch te := el.(type) { case rideByteVector: default: - return nil, errors.Errorf("reissueTransactionConstructor: unexpected type '%s' in proofs list", t.instanceOf()) + return nil, errors.Errorf("reissueTransactionConstructor: unexpected type '%s' in proofs list", te.instanceOf()) } } @@ -1994,11 +2059,11 @@ func setAssetScriptTransactionConstructor(_ environment, args_ ...rideType) (rid return nil, errors.Errorf("setAssetScriptTransactionConstructor: unexpected type '%s' for proofs", args_[9].instanceOf()) } // checks for list elements - for _, elem := range proofs { - switch t := elem.(type) { + for _, el := range proofs { + switch te := el.(type) { case rideByteVector: default: - return nil, errors.Errorf("setAssetScriptTransactionConstructor: unexpected type '%s' in proofs list", t.instanceOf()) + return nil, errors.Errorf("setAssetScriptTransactionConstructor: unexpected type '%s' in proofs list", te.instanceOf()) } } @@ -2058,11 +2123,11 @@ func setScriptTransactionConstructor(_ environment, args_ ...rideType) (rideType return nil, errors.Errorf("setScriptTransactionConstructor: unexpected type '%s' for proofs", args_[8].instanceOf()) } // checks for list elements - for _, elem := range proofs { - switch t := elem.(type) { + for _, el := range proofs { + switch te := el.(type) { case rideByteVector: default: - return nil, errors.Errorf("setScriptTransactionConstructor: unexpected type '%s' in proofs list", t.instanceOf()) + return nil, errors.Errorf("setScriptTransactionConstructor: unexpected type '%s' in proofs list", te.instanceOf()) } } @@ -2127,11 +2192,11 @@ func sponsorFeeTransactionConstructor(_ environment, args_ ...rideType) (rideTyp return nil, errors.Errorf("sponsorFeeTransactionConstructor: unexpected type '%s' for proofs", args_[9].instanceOf()) } // checks for list elements - for _, elem := range proofs { - switch t := elem.(type) { + for _, el := range proofs { + switch te := el.(type) { case rideByteVector: default: - return nil, errors.Errorf("sponsorFeeTransactionConstructor: unexpected type '%s' in proofs list", t.instanceOf()) + return nil, errors.Errorf("sponsorFeeTransactionConstructor: unexpected type '%s' in proofs list", te.instanceOf()) } } @@ -2226,11 +2291,11 @@ func transferTransactionConstructor(_ environment, args_ ...rideType) (rideType, return nil, errors.Errorf("transferTransactionConstructor: unexpected type '%s' for proofs", args_[12].instanceOf()) } // checks for list elements - for _, elem := range proofs { - switch t := elem.(type) { + for _, el := range proofs { + switch te := el.(type) { case rideByteVector: default: - return nil, errors.Errorf("transferTransactionConstructor: unexpected type '%s' in proofs list", t.instanceOf()) + return nil, errors.Errorf("transferTransactionConstructor: unexpected type '%s' in proofs list", te.instanceOf()) } } @@ -2300,11 +2365,11 @@ func updateAssetInfoTransactionConstructor(_ environment, args_ ...rideType) (ri return nil, errors.Errorf("updateAssetInfoTransactionConstructor: unexpected type '%s' for proofs", args_[10].instanceOf()) } // checks for list elements - for _, elem := range proofs { - switch t := elem.(type) { + for _, el := range proofs { + switch te := el.(type) { case rideByteVector: default: - return nil, errors.Errorf("updateAssetInfoTransactionConstructor: unexpected type '%s' in proofs list", t.instanceOf()) + return nil, errors.Errorf("updateAssetInfoTransactionConstructor: unexpected type '%s' in proofs list", te.instanceOf()) } } diff --git a/pkg/ride/converters.go b/pkg/ride/converters.go index 9442a20a8..3555612d6 100644 --- a/pkg/ride/converters.go +++ b/pkg/ride/converters.go @@ -115,7 +115,7 @@ func blockInfoToObject(info *proto.BlockInfo) rideType { ) } -func blockHeaderToObject(scheme byte, height proto.Height, header *proto.BlockHeader, vrf []byte) (rideType, error) { +func blockHeaderToObjectV1V6(scheme byte, height proto.Height, header *proto.BlockHeader, vrf []byte) (rideType, error) { address, err := proto.NewAddressFromPublicKey(scheme, header.GeneratorPublicKey) if err != nil { return nil, EvaluationFailure.Wrap(err, "blockHeaderToObject") @@ -135,6 +135,32 @@ func blockHeaderToObject(scheme byte, height proto.Height, header *proto.BlockHe ), nil } +func blockHeaderToObjectV7(scheme byte, height proto.Height, header *proto.BlockHeader, vrf []byte, + rewards proto.Rewards) (rideType, error) { + address, err := proto.NewAddressFromPublicKey(scheme, header.GeneratorPublicKey) + if err != nil { + return nil, EvaluationFailure.Wrap(err, "blockHeaderToObject") + } + var vf rideType = rideUnit{} + if len(vrf) > 0 { + vf = rideByteVector(common.Dup(vrf)) + } + sr := rewards.Sorted() + rl := make(rideList, len(sr)) + for i, r := range sr { + rl[i] = tuple2{el1: rideAddress(r.Address()), el2: rideInt(r.Amount())} + } + return newRideBlockInfoV7(vf, + common.Dup(header.GenSignature.Bytes()), + common.Dup(header.GeneratorPublicKey.Bytes()), + rideInt(header.BaseTarget), + rideInt(header.Timestamp), + rideInt(height), + rideAddress(address), + rl, + ), nil +} + func genesisToObject(_ byte, tx *proto.Genesis) (rideGenesisTransaction, error) { return newRideGenesisTransaction( rideAddress(tx.Recipient), diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index 6e165451d..b9b11a653 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -342,6 +342,10 @@ func (ws *WrappedState) BlockVRF(blockHeader *proto.BlockHeader, height proto.He return ws.diff.state.BlockVRF(blockHeader, height) } +func (ws *WrappedState) BlockRewards(blockHeader *proto.BlockHeader, height proto.Height) (proto.Rewards, error) { + return ws.diff.state.BlockRewards(blockHeader, height) +} + func (ws *WrappedState) EstimatorVersion() (int, error) { return ws.diff.state.EstimatorVersion() } diff --git a/pkg/ride/functions.gen.go b/pkg/ride/functions.gen.go index d21461d7e..12fe3d62d 100644 --- a/pkg/ride/functions.gen.go +++ b/pkg/ride/functions.gen.go @@ -311,3 +311,65 @@ func costV6(id int) int { } return _catalogue_V6[id] } + +var _functions_V7 [302]rideFunction +var _functions_map_V7 map[string]rideFunction + +func init() { + _functions_V7 = [302]rideFunction{unaryNot, neq, unaryMinus, eq, instanceOf, sum, transactionHeightByID, assetInfoV4, blockInfoByHeight, transferByID, wavesBalanceV4, assetBalanceV4, hashScriptAtAddress, sub, gt, invoke, reentrantInvoke, ge, mul, intFromArray, booleanFromArray, bytesFromArray, stringFromArray, div, intFromState, booleanFromState, bytesFromState, stringFromState, isDataStorageUntouched, intFromSelfState, booleanFromSelfState, bytesFromSelfState, stringFromSelfState, mod, addressFromRecipient, addressToString, addressFromString, addressFromPublicKeyStrict, fraction, transferFromProtobuf, pow, calculateAssetID, calculateLeaseID, log, simplifiedIssue, fullIssue, simplifiedLease, fullLease, fractionIntRounds, limitedCreateList, appendToList, concatList, indexOfList, lastIndexOfList, listRemoveByIndex, powBigInt, logBigInt, bytesToUTF8String, bytesToInt, bytesToIntWithOffset, indexOfSubstring, indexOfSubstringWithOffset, splitStringV6, parseInt, lastIndexOfSubstring, lastIndexOfSubstringWithOffset, makeStringV6, makeString2C, makeString11C, splitString4C, splitString51C, newTuple2, newTuple3, newTuple4, newTuple5, newTuple6, newTuple7, newTuple8, newTuple9, newTuple10, newTuple11, newTuple12, newTuple13, newTuple14, newTuple15, newTuple16, newTuple17, newTuple18, newTuple19, newTuple20, newTuple21, newTuple22, sizeTuple, throw, sizeBytes, takeBytes, dropBytes, concatBytes, takeRightBytes, dropRightBytes, bls12Groth16Verify_1, bls12Groth16Verify_2, bls12Groth16Verify_3, bls12Groth16Verify_4, bls12Groth16Verify_5, bls12Groth16Verify_6, bls12Groth16Verify_7, bls12Groth16Verify_8, bls12Groth16Verify_9, bls12Groth16Verify_10, bls12Groth16Verify_11, bls12Groth16Verify_12, bls12Groth16Verify_13, bls12Groth16Verify_14, bls12Groth16Verify_15, bn256Groth16Verify_1, bn256Groth16Verify_2, bn256Groth16Verify_3, bn256Groth16Verify_4, bn256Groth16Verify_5, bn256Groth16Verify_6, bn256Groth16Verify_7, bn256Groth16Verify_8, bn256Groth16Verify_9, bn256Groth16Verify_10, bn256Groth16Verify_11, bn256Groth16Verify_12, bn256Groth16Verify_13, bn256Groth16Verify_14, bn256Groth16Verify_15, sigVerify_8, sigVerify_16, sigVerify_32, sigVerify_64, sigVerify_128, rsaVerify_16, rsaVerify_32, rsaVerify_64, rsaVerify_128, keccak256_16, keccak256_32, keccak256_64, keccak256_128, blake2b256_16, blake2b256_32, blake2b256_64, blake2b256_128, sha256_16, sha256_32, sha256_64, sha256_128, getType, concatStrings, takeString, dropString, sizeString, takeRightString, dropRightString, toBigInt, sumBigInt, subtractBigInt, multiplyBigInt, divideBigInt, moduloBigInt, fractionBigInt, fractionBigIntRounds, unaryMinusBigInt, gtBigInt, geBigInt, sizeList, getList, median, max, min, maxListBigInt, minListBigInt, intToBytes, stringToBytes, booleanToBytes, bigIntToBytes, bytesToBigInt, bytesToBigIntLim, bigIntToInt, intToString, booleanToString, bigIntToString, stringToBigInt, stringToBigIntOpt, medianListBigInt, sigVerify, keccak256, blake2b256, sha256, rsaVerify, toBase58, fromBase58, toBase64, fromBase64, toBase16, fromBase16, rebuildMerkleRoot, bls12Groth16Verify, bn256Groth16Verify, ecRecover, intValueFromArray, booleanValueFromArray, bytesValueFromArray, stringValueFromArray, intValueFromState, booleanValueFromState, bytesValueFromState, stringValueFromState, intValueFromSelfState, booleanValueFromSelfState, bytesValueFromSelfState, stringValueFromSelfState, addressValueFromString, addressValueFromString, bytesValueFromArrayByIndex, booleanValueFromArrayByIndex, intValueFromArrayByIndex, stringValueFromArrayByIndex, address, alias, assetV4Constructor, assetPairConstructor, attachedPaymentConstructor, balanceDetailsConstructor, binaryEntryConstructor, blockInfoV7Constructor, booleanEntryConstructor, burnConstructor, burnTransactionConstructor, createBuy, createCeiling, createAliasTransactionConstructor, dataTransactionConstructor, deleteEntryConstructor, createDown, exchangeTransactionConstructor, createFloor, genesisTransactionConstructor, createHalfDown, createHalfEven, createHalfUp, integerEntryConstructor, invocationV5Constructor, invokeExpressionTransactionConstructor, invokeScriptTransactionV4Constructor, issueConstructor, issueTransactionConstructor, leaseConstructor, leaseCancelConstructor, leaseCancelTransactionConstructor, leaseTransactionConstructor, massTransferTransactionConstructor, createMd5, createNoAlg, orderConstructor, paymentTransactionConstructor, reissueConstructor, reissueTransactionConstructor, scriptTransferConstructor, createSell, setAssetScriptTransactionConstructor, setScriptTransactionConstructor, createSha1, createSha224, createSha256, createSha3224, createSha3256, createSha3384, createSha3512, createSha384, createSha512, sponsorFeeConstructor, sponsorFeeTransactionConstructor, stringEntryConstructor, transferConstructor, transferTransactionConstructor, unit, createUp, updateAssetInfoTransactionConstructor, addressFromPublicKey, contains, containsElement, dropRightString, dropRightBytes, bytesFromArrayByIndex, booleanFromArrayByIndex, intFromArrayByIndex, stringFromArrayByIndex, isDefined, parseIntValue, sqrt, sqrtBigInt, takeRightString, takeRightBytes, throw0, value, valueOrElse, valueOrErrorMessage} + _functions_map_V7 = map[string]rideFunction{"!": unaryNot, "!=": neq, "-": unaryMinus, "0": eq, "1": instanceOf, "100": sum, "1001": transactionHeightByID, "1004": assetInfoV4, "1005": blockInfoByHeight, "1006": transferByID, "1007": wavesBalanceV4, "1008": assetBalanceV4, "1009": hashScriptAtAddress, "101": sub, "102": gt, "1020": invoke, "1021": reentrantInvoke, "103": ge, "104": mul, "1040": intFromArray, "1041": booleanFromArray, "1042": bytesFromArray, "1043": stringFromArray, "105": div, "1050": intFromState, "1051": booleanFromState, "1052": bytesFromState, "1053": stringFromState, "1054": isDataStorageUntouched, "1055": intFromSelfState, "1056": booleanFromSelfState, "1057": bytesFromSelfState, "1058": stringFromSelfState, "106": mod, "1060": addressFromRecipient, "1061": addressToString, "1062": addressFromString, "1063": addressFromPublicKeyStrict, "107": fraction, "1070": transferFromProtobuf, "108": pow, "1080": calculateAssetID, "1081": calculateLeaseID, "109": log, "1090": simplifiedIssue, "1091": fullIssue, "1092": simplifiedLease, "1093": fullLease, "110": fractionIntRounds, "1100": limitedCreateList, "1101": appendToList, "1102": concatList, "1103": indexOfList, "1104": lastIndexOfList, "1105": listRemoveByIndex, "118": powBigInt, "119": logBigInt, "1200": bytesToUTF8String, "1201": bytesToInt, "1202": bytesToIntWithOffset, "1203": indexOfSubstring, "1204": indexOfSubstringWithOffset, "1205": splitStringV6, "1206": parseInt, "1207": lastIndexOfSubstring, "1208": lastIndexOfSubstringWithOffset, "1209": makeStringV6, "1210": makeString2C, "1211": makeString11C, "1212": splitString4C, "1213": splitString51C, "1300": newTuple2, "1301": newTuple3, "1302": newTuple4, "1303": newTuple5, "1304": newTuple6, "1305": newTuple7, "1306": newTuple8, "1307": newTuple9, "1308": newTuple10, "1309": newTuple11, "1310": newTuple12, "1311": newTuple13, "1312": newTuple14, "1313": newTuple15, "1314": newTuple16, "1315": newTuple17, "1316": newTuple18, "1317": newTuple19, "1318": newTuple20, "1319": newTuple21, "1320": newTuple22, "1350": sizeTuple, "2": throw, "200": sizeBytes, "201": takeBytes, "202": dropBytes, "203": concatBytes, "204": takeRightBytes, "205": dropRightBytes, "2400": bls12Groth16Verify_1, "2401": bls12Groth16Verify_2, "2402": bls12Groth16Verify_3, "2403": bls12Groth16Verify_4, "2404": bls12Groth16Verify_5, "2405": bls12Groth16Verify_6, "2406": bls12Groth16Verify_7, "2407": bls12Groth16Verify_8, "2408": bls12Groth16Verify_9, "2409": bls12Groth16Verify_10, "2410": bls12Groth16Verify_11, "2411": bls12Groth16Verify_12, "2412": bls12Groth16Verify_13, "2413": bls12Groth16Verify_14, "2414": bls12Groth16Verify_15, "2450": bn256Groth16Verify_1, "2451": bn256Groth16Verify_2, "2452": bn256Groth16Verify_3, "2453": bn256Groth16Verify_4, "2454": bn256Groth16Verify_5, "2455": bn256Groth16Verify_6, "2456": bn256Groth16Verify_7, "2457": bn256Groth16Verify_8, "2458": bn256Groth16Verify_9, "2459": bn256Groth16Verify_10, "2460": bn256Groth16Verify_11, "2461": bn256Groth16Verify_12, "2462": bn256Groth16Verify_13, "2463": bn256Groth16Verify_14, "2464": bn256Groth16Verify_15, "2500": sigVerify_8, "2501": sigVerify_16, "2502": sigVerify_32, "2503": sigVerify_64, "2504": sigVerify_128, "2600": rsaVerify_16, "2601": rsaVerify_32, "2602": rsaVerify_64, "2603": rsaVerify_128, "2700": keccak256_16, "2701": keccak256_32, "2702": keccak256_64, "2703": keccak256_128, "2800": blake2b256_16, "2801": blake2b256_32, "2802": blake2b256_64, "2803": blake2b256_128, "2900": sha256_16, "2901": sha256_32, "2902": sha256_64, "2903": sha256_128, "3": getType, "300": concatStrings, "303": takeString, "304": dropString, "305": sizeString, "306": takeRightString, "307": dropRightString, "310": toBigInt, "311": sumBigInt, "312": subtractBigInt, "313": multiplyBigInt, "314": divideBigInt, "315": moduloBigInt, "316": fractionBigInt, "317": fractionBigIntRounds, "318": unaryMinusBigInt, "319": gtBigInt, "320": geBigInt, "400": sizeList, "401": getList, "405": median, "406": max, "407": min, "408": maxListBigInt, "409": minListBigInt, "410": intToBytes, "411": stringToBytes, "412": booleanToBytes, "413": bigIntToBytes, "414": bytesToBigInt, "415": bytesToBigIntLim, "416": bigIntToInt, "420": intToString, "421": booleanToString, "422": bigIntToString, "423": stringToBigInt, "424": stringToBigIntOpt, "425": medianListBigInt, "500": sigVerify, "501": keccak256, "502": blake2b256, "503": sha256, "504": rsaVerify, "600": toBase58, "601": fromBase58, "602": toBase64, "603": fromBase64, "604": toBase16, "605": fromBase16, "701": rebuildMerkleRoot, "800": bls12Groth16Verify, "801": bn256Groth16Verify, "900": ecRecover, "@extrNative(1040)": intValueFromArray, "@extrNative(1041)": booleanValueFromArray, "@extrNative(1042)": bytesValueFromArray, "@extrNative(1043)": stringValueFromArray, "@extrNative(1050)": intValueFromState, "@extrNative(1051)": booleanValueFromState, "@extrNative(1052)": bytesValueFromState, "@extrNative(1053)": stringValueFromState, "@extrNative(1055)": intValueFromSelfState, "@extrNative(1056)": booleanValueFromSelfState, "@extrNative(1057)": bytesValueFromSelfState, "@extrNative(1058)": stringValueFromSelfState, "@extrNative(1062)": addressValueFromString, "@extrUser(addressFromString)": addressValueFromString, "@extrUser(getBinary)": bytesValueFromArrayByIndex, "@extrUser(getBoolean)": booleanValueFromArrayByIndex, "@extrUser(getInteger)": intValueFromArrayByIndex, "@extrUser(getString)": stringValueFromArrayByIndex, "Address": address, "Alias": alias, "Asset": assetV4Constructor, "AssetPair": assetPairConstructor, "AttachedPayment": attachedPaymentConstructor, "BalanceDetails": balanceDetailsConstructor, "BinaryEntry": binaryEntryConstructor, "BlockInfo": blockInfoV7Constructor, "BooleanEntry": booleanEntryConstructor, "Burn": burnConstructor, "BurnTransaction": burnTransactionConstructor, "Buy": createBuy, "Ceiling": createCeiling, "CreateAliasTransaction": createAliasTransactionConstructor, "DataTransaction": dataTransactionConstructor, "DeleteEntry": deleteEntryConstructor, "Down": createDown, "ExchangeTransaction": exchangeTransactionConstructor, "Floor": createFloor, "GenesisTransaction": genesisTransactionConstructor, "HalfDown": createHalfDown, "HalfEven": createHalfEven, "HalfUp": createHalfUp, "IntegerEntry": integerEntryConstructor, "Invocation": invocationV5Constructor, "InvokeExpressionTransaction": invokeExpressionTransactionConstructor, "InvokeScriptTransaction": invokeScriptTransactionV4Constructor, "Issue": issueConstructor, "IssueTransaction": issueTransactionConstructor, "Lease": leaseConstructor, "LeaseCancel": leaseCancelConstructor, "LeaseCancelTransaction": leaseCancelTransactionConstructor, "LeaseTransaction": leaseTransactionConstructor, "MassTransferTransaction": massTransferTransactionConstructor, "Md5": createMd5, "NoAlg": createNoAlg, "Order": orderConstructor, "PaymentTransaction": paymentTransactionConstructor, "Reissue": reissueConstructor, "ReissueTransaction": reissueTransactionConstructor, "ScriptTransfer": scriptTransferConstructor, "Sell": createSell, "SetAssetScriptTransaction": setAssetScriptTransactionConstructor, "SetScriptTransaction": setScriptTransactionConstructor, "Sha1": createSha1, "Sha224": createSha224, "Sha256": createSha256, "Sha3224": createSha3224, "Sha3256": createSha3256, "Sha3384": createSha3384, "Sha3512": createSha3512, "Sha384": createSha384, "Sha512": createSha512, "SponsorFee": sponsorFeeConstructor, "SponsorFeeTransaction": sponsorFeeTransactionConstructor, "StringEntry": stringEntryConstructor, "Transfer": transferConstructor, "TransferTransaction": transferTransactionConstructor, "Unit": unit, "Up": createUp, "UpdateAssetInfoTransaction": updateAssetInfoTransactionConstructor, "addressFromPublicKey": addressFromPublicKey, "contains": contains, "containsElement": containsElement, "dropRight": dropRightString, "dropRightBytes": dropRightBytes, "getBinary": bytesFromArrayByIndex, "getBoolean": booleanFromArrayByIndex, "getInteger": intFromArrayByIndex, "getString": stringFromArrayByIndex, "isDefined": isDefined, "parseIntValue": parseIntValue, "sqrt": sqrt, "sqrtBigInt": sqrtBigInt, "takeRight": takeRightString, "takeRightBytes": takeRightBytes, "throw": throw0, "value": value, "valueOrElse": valueOrElse, "valueOrErrorMessage": valueOrErrorMessage} +} + +var _catalogue_V7 = [...]int{1, 1, 1, 1, 1, 1, 20, 15, 5, 60, 10, 10, 200, 1, 1, 75, 75, 1, 1, 10, 10, 10, 10, 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 5, 1, 1, 1, 1, 5, 28, 10, 1, 100, 1, 1, 1, 1, 1, 1, 1, 4, 5, 5, 7, 270, 200, 7, 1, 1, 3, 3, 1, 2, 3, 3, 1, 2, 11, 4, 51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 2, 6, 6, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 800, 850, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1550, 1600, 43, 50, 64, 93, 150, 500, 550, 625, 750, 20, 39, 74, 147, 13, 29, 58, 115, 12, 23, 47, 93, 1, 1, 20, 20, 1, 20, 20, 1, 8, 8, 64, 64, 64, 1, 1, 8, 8, 8, 2, 2, 20, 3, 3, 192, 192, 1, 8, 1, 65, 65, 65, 1, 1, 1, 1, 65, 65, 160, 180, 195, 136, 118, 1000, 3, 1, 35, 40, 10, 10, 30, 2700, 1650, 70, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 124, 10, 10, 10, 10, 1, 1, 10, 2, 2, 4, 2, 8, 2, 2, 10, 0, 0, 9, 9, 1, 0, 14, 0, 6, 0, 0, 0, 2, 8, 10, 13, 7, 14, 3, 1, 9, 10, 13, 0, 0, 14, 10, 3, 11, 3, 0, 10, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 10, 2, 2, 13, 0, 0, 11, 63, 3, 5, 20, 6, 30, 30, 30, 30, 1, 2, 2, 5, 20, 6, 1, 2, 2, 2} + +var CatalogueV7 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "1009": 200, "101": 1, "102": 1, "1020": 75, "1021": 75, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "1054": 10, "1055": 10, "1056": 10, "1057": 10, "1058": 10, "106": 1, "1060": 5, "1061": 1, "1062": 1, "1063": 1, "107": 1, "1070": 5, "108": 28, "1080": 10, "1081": 1, "109": 100, "1090": 1, "1091": 1, "1092": 1, "1093": 1, "110": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1105": 7, "118": 270, "119": 200, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 1, "1206": 2, "1207": 3, "1208": 3, "1209": 1, "1210": 2, "1211": 11, "1212": 4, "1213": 51, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "1350": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "204": 6, "205": 6, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 43, "2501": 50, "2502": 64, "2503": 93, "2504": 150, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 20, "2701": 39, "2702": 74, "2703": 147, "2800": 13, "2801": 29, "2802": 58, "2803": 115, "2900": 12, "2901": 23, "2902": 47, "2903": 93, "3": 1, "300": 1, "303": 20, "304": 20, "305": 1, "306": 20, "307": 20, "310": 1, "311": 8, "312": 8, "313": 64, "314": 64, "315": 64, "316": 1, "317": 1, "318": 8, "319": 8, "320": 8, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "408": 192, "409": 192, "410": 1, "411": 8, "412": 1, "413": 65, "414": 65, "415": 65, "416": 1, "420": 1, "421": 1, "422": 1, "423": 65, "424": 65, "425": 160, "500": 180, "501": 195, "502": 136, "503": 118, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1055)": 10, "@extrNative(1056)": 10, "@extrNative(1057)": 10, "@extrNative(1058)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "Asset": 10, "AssetPair": 2, "AttachedPayment": 2, "BalanceDetails": 4, "BinaryEntry": 2, "BlockInfo": 8, "BooleanEntry": 2, "Burn": 2, "BurnTransaction": 10, "Buy": 0, "Ceiling": 0, "CreateAliasTransaction": 9, "DataTransaction": 9, "DeleteEntry": 1, "Down": 0, "ExchangeTransaction": 14, "Floor": 0, "GenesisTransaction": 6, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 2, "Invocation": 8, "InvokeExpressionTransaction": 10, "InvokeScriptTransaction": 13, "Issue": 7, "IssueTransaction": 14, "Lease": 3, "LeaseCancel": 1, "LeaseCancelTransaction": 9, "LeaseTransaction": 10, "MassTransferTransaction": 13, "Md5": 0, "NoAlg": 0, "Order": 14, "PaymentTransaction": 10, "Reissue": 3, "ReissueTransaction": 11, "ScriptTransfer": 3, "Sell": 0, "SetAssetScriptTransaction": 10, "SetScriptTransaction": 9, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 2, "SponsorFeeTransaction": 10, "StringEntry": 2, "Transfer": 2, "TransferTransaction": 13, "Unit": 0, "Up": 0, "UpdateAssetInfoTransaction": 11, "addressFromPublicKey": 63, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "sqrt": 2, "sqrtBigInt": 5, "takeRight": 20, "takeRightBytes": 6, "throw": 1, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} + +var EvaluationCatalogueV7EvaluatorV1 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "1009": 200, "101": 1, "102": 1, "1020": 75, "1021": 75, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "1054": 10, "1055": 10, "1056": 10, "1057": 10, "1058": 10, "106": 1, "1060": 5, "1061": 1, "1062": 1, "1063": 1, "107": 1, "1070": 5, "108": 28, "1080": 10, "1081": 1, "109": 100, "1090": 1, "1091": 1, "1092": 1, "1093": 1, "110": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1105": 7, "118": 270, "119": 200, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 1, "1206": 2, "1207": 3, "1208": 3, "1209": 1, "1210": 2, "1211": 11, "1212": 4, "1213": 51, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "1350": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "204": 6, "205": 6, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 43, "2501": 50, "2502": 64, "2503": 93, "2504": 150, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 20, "2701": 39, "2702": 74, "2703": 147, "2800": 13, "2801": 29, "2802": 58, "2803": 115, "2900": 12, "2901": 23, "2902": 47, "2903": 93, "3": 1, "300": 1, "303": 20, "304": 20, "305": 1, "306": 20, "307": 20, "310": 1, "311": 8, "312": 8, "313": 64, "314": 64, "315": 64, "316": 1, "317": 1, "318": 8, "319": 8, "320": 8, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "408": 192, "409": 192, "410": 1, "411": 8, "412": 1, "413": 65, "414": 65, "415": 65, "416": 1, "420": 1, "421": 1, "422": 1, "423": 65, "424": 65, "425": 160, "500": 180, "501": 195, "502": 136, "503": 118, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1055)": 10, "@extrNative(1056)": 10, "@extrNative(1057)": 10, "@extrNative(1058)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 0, "Alias": 0, "Asset": 0, "AssetPair": 0, "AttachedPayment": 0, "BalanceDetails": 0, "BinaryEntry": 0, "BlockInfo": 0, "BooleanEntry": 0, "Burn": 0, "BurnTransaction": 0, "Buy": 0, "Ceiling": 0, "CreateAliasTransaction": 0, "DataTransaction": 0, "DeleteEntry": 0, "Down": 0, "ExchangeTransaction": 0, "Floor": 0, "GenesisTransaction": 0, "HalfDown": 0, "HalfEven": 0, "HalfUp": 0, "IntegerEntry": 0, "Invocation": 0, "InvokeExpressionTransaction": 0, "InvokeScriptTransaction": 0, "Issue": 0, "IssueTransaction": 0, "Lease": 0, "LeaseCancel": 0, "LeaseCancelTransaction": 0, "LeaseTransaction": 0, "MassTransferTransaction": 0, "Md5": 0, "NoAlg": 0, "Order": 0, "PaymentTransaction": 0, "Reissue": 0, "ReissueTransaction": 0, "ScriptTransfer": 0, "Sell": 0, "SetAssetScriptTransaction": 0, "SetScriptTransaction": 0, "Sha1": 0, "Sha224": 0, "Sha256": 0, "Sha3224": 0, "Sha3256": 0, "Sha3384": 0, "Sha3512": 0, "Sha384": 0, "Sha512": 0, "SponsorFee": 0, "SponsorFeeTransaction": 0, "StringEntry": 0, "Transfer": 0, "TransferTransaction": 0, "Unit": 0, "Up": 0, "UpdateAssetInfoTransaction": 0, "addressFromPublicKey": 63, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "sqrt": 2, "sqrtBigInt": 5, "takeRight": 20, "takeRightBytes": 6, "throw": 2, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} +var EvaluationCatalogueV7EvaluatorV2 = map[string]int{"!": 1, "!=": 1, "-": 1, "0": 1, "1": 1, "100": 1, "1001": 20, "1004": 15, "1005": 5, "1006": 60, "1007": 10, "1008": 10, "1009": 200, "101": 1, "102": 1, "1020": 75, "1021": 75, "103": 1, "104": 1, "1040": 10, "1041": 10, "1042": 10, "1043": 10, "105": 1, "1050": 10, "1051": 10, "1052": 10, "1053": 10, "1054": 10, "1055": 10, "1056": 10, "1057": 10, "1058": 10, "106": 1, "1060": 5, "1061": 1, "1062": 1, "1063": 1, "107": 1, "1070": 5, "108": 28, "1080": 10, "1081": 1, "109": 100, "1090": 1, "1091": 1, "1092": 1, "1093": 1, "110": 1, "1100": 1, "1101": 1, "1102": 4, "1103": 5, "1104": 5, "1105": 7, "118": 270, "119": 200, "1200": 7, "1201": 1, "1202": 1, "1203": 3, "1204": 3, "1205": 1, "1206": 2, "1207": 3, "1208": 3, "1209": 1, "1210": 2, "1211": 11, "1212": 4, "1213": 51, "1300": 1, "1301": 1, "1302": 1, "1303": 1, "1304": 1, "1305": 1, "1306": 1, "1307": 1, "1308": 1, "1309": 1, "1310": 1, "1311": 1, "1312": 1, "1313": 1, "1314": 1, "1315": 1, "1316": 1, "1317": 1, "1318": 1, "1319": 1, "1320": 1, "1350": 1, "2": 1, "200": 1, "201": 6, "202": 6, "203": 2, "204": 6, "205": 6, "2400": 1200, "2401": 1300, "2402": 1400, "2403": 1500, "2404": 1600, "2405": 1700, "2406": 1800, "2407": 1900, "2408": 2000, "2409": 2100, "2410": 2200, "2411": 2300, "2412": 2400, "2413": 2500, "2414": 2600, "2450": 800, "2451": 850, "2452": 950, "2453": 1000, "2454": 1050, "2455": 1100, "2456": 1150, "2457": 1200, "2458": 1250, "2459": 1300, "2460": 1350, "2461": 1400, "2462": 1450, "2463": 1550, "2464": 1600, "2500": 43, "2501": 50, "2502": 64, "2503": 93, "2504": 150, "2600": 500, "2601": 550, "2602": 625, "2603": 750, "2700": 20, "2701": 39, "2702": 74, "2703": 147, "2800": 13, "2801": 29, "2802": 58, "2803": 115, "2900": 12, "2901": 23, "2902": 47, "2903": 93, "3": 1, "300": 1, "303": 20, "304": 20, "305": 1, "306": 20, "307": 20, "310": 1, "311": 8, "312": 8, "313": 64, "314": 64, "315": 64, "316": 1, "317": 1, "318": 8, "319": 8, "320": 8, "400": 2, "401": 2, "405": 20, "406": 3, "407": 3, "408": 192, "409": 192, "410": 1, "411": 8, "412": 1, "413": 65, "414": 65, "415": 65, "416": 1, "420": 1, "421": 1, "422": 1, "423": 65, "424": 65, "425": 160, "500": 180, "501": 195, "502": 136, "503": 118, "504": 1000, "600": 3, "601": 1, "602": 35, "603": 40, "604": 10, "605": 10, "701": 30, "800": 2700, "801": 1650, "900": 70, "@extrNative(1040)": 10, "@extrNative(1041)": 10, "@extrNative(1042)": 10, "@extrNative(1043)": 10, "@extrNative(1050)": 10, "@extrNative(1051)": 10, "@extrNative(1052)": 10, "@extrNative(1053)": 10, "@extrNative(1055)": 10, "@extrNative(1056)": 10, "@extrNative(1057)": 10, "@extrNative(1058)": 10, "@extrNative(1062)": 1, "@extrUser(addressFromString)": 124, "@extrUser(getBinary)": 10, "@extrUser(getBoolean)": 10, "@extrUser(getInteger)": 10, "@extrUser(getString)": 10, "Address": 1, "Alias": 1, "Asset": 1, "AssetPair": 1, "AttachedPayment": 1, "BalanceDetails": 1, "BinaryEntry": 1, "BlockInfo": 1, "BooleanEntry": 1, "Burn": 1, "BurnTransaction": 1, "Buy": 0, "Ceiling": 1, "CreateAliasTransaction": 1, "DataTransaction": 1, "DeleteEntry": 1, "Down": 1, "ExchangeTransaction": 1, "Floor": 1, "GenesisTransaction": 1, "HalfDown": 0, "HalfEven": 1, "HalfUp": 1, "IntegerEntry": 1, "Invocation": 1, "InvokeExpressionTransaction": 1, "InvokeScriptTransaction": 1, "Issue": 1, "IssueTransaction": 1, "Lease": 1, "LeaseCancel": 1, "LeaseCancelTransaction": 1, "LeaseTransaction": 1, "MassTransferTransaction": 1, "Md5": 1, "NoAlg": 1, "Order": 1, "PaymentTransaction": 1, "Reissue": 1, "ReissueTransaction": 1, "ScriptTransfer": 1, "Sell": 0, "SetAssetScriptTransaction": 1, "SetScriptTransaction": 1, "Sha1": 1, "Sha224": 1, "Sha256": 1, "Sha3224": 1, "Sha3256": 1, "Sha3384": 1, "Sha3512": 1, "Sha384": 1, "Sha512": 1, "SponsorFee": 1, "SponsorFeeTransaction": 1, "StringEntry": 1, "Transfer": 1, "TransferTransaction": 1, "Unit": 1, "Up": 0, "UpdateAssetInfoTransaction": 1, "addressFromPublicKey": 63, "contains": 3, "containsElement": 5, "dropRight": 20, "dropRightBytes": 6, "getBinary": 30, "getBoolean": 30, "getInteger": 30, "getString": 30, "isDefined": 1, "parseIntValue": 2, "sqrt": 2, "sqrtBigInt": 5, "takeRight": 20, "takeRightBytes": 6, "throw": 2, "value": 2, "valueOrElse": 2, "valueOrErrorMessage": 2} + +const _names_V7 = "!!=-0110010011004100510061007100810091011021020102110310410401041104210431051050105110521053105410551056105710581061060106110621063107107010810801081109109010911092109311011001101110211031104110511811912001201120212031204120512061207120812091210121112121213130013011302130313041305130613071308130913101311131213131314131513161317131813191320135022002012022032042052400240124022403240424052406240724082409241024112412241324142450245124522453245424552456245724582459246024612462246324642500250125022503250426002601260226032700270127022703280028012802280329002901290229033300303304305306307310311312313314315316317318319320400401405406407408409410411412413414415416420421422423424425500501502503504600601602603604605701800801900@extrNative(1040)@extrNative(1041)@extrNative(1042)@extrNative(1043)@extrNative(1050)@extrNative(1051)@extrNative(1052)@extrNative(1053)@extrNative(1055)@extrNative(1056)@extrNative(1057)@extrNative(1058)@extrNative(1062)@extrUser(addressFromString)@extrUser(getBinary)@extrUser(getBoolean)@extrUser(getInteger)@extrUser(getString)AddressAliasAssetAssetPairAttachedPaymentBalanceDetailsBinaryEntryBlockInfoBooleanEntryBurnBurnTransactionBuyCeilingCreateAliasTransactionDataTransactionDeleteEntryDownExchangeTransactionFloorGenesisTransactionHalfDownHalfEvenHalfUpIntegerEntryInvocationInvokeExpressionTransactionInvokeScriptTransactionIssueIssueTransactionLeaseLeaseCancelLeaseCancelTransactionLeaseTransactionMassTransferTransactionMd5NoAlgOrderPaymentTransactionReissueReissueTransactionScriptTransferSellSetAssetScriptTransactionSetScriptTransactionSha1Sha224Sha256Sha3224Sha3256Sha3384Sha3512Sha384Sha512SponsorFeeSponsorFeeTransactionStringEntryTransferTransferTransactionUnitUpUpdateAssetInfoTransactionaddressFromPublicKeycontainscontainsElementdropRightdropRightBytesgetBinarygetBooleangetIntegergetStringisDefinedparseIntValuesqrtsqrtBigInttakeRighttakeRightBytesthrowvaluevalueOrElsevalueOrErrorMessage" + +var _index_V7 = [...]int{0, 1, 3, 4, 5, 6, 9, 13, 17, 21, 25, 29, 33, 37, 40, 43, 47, 51, 54, 57, 61, 65, 69, 73, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 115, 119, 123, 127, 131, 134, 138, 141, 145, 149, 152, 156, 160, 164, 168, 171, 175, 179, 183, 187, 191, 195, 198, 201, 205, 209, 213, 217, 221, 225, 229, 233, 237, 241, 245, 249, 253, 257, 261, 265, 269, 273, 277, 281, 285, 289, 293, 297, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 346, 349, 352, 355, 358, 361, 364, 368, 372, 376, 380, 384, 388, 392, 396, 400, 404, 408, 412, 416, 420, 424, 428, 432, 436, 440, 444, 448, 452, 456, 460, 464, 468, 472, 476, 480, 484, 488, 492, 496, 500, 504, 508, 512, 516, 520, 524, 528, 532, 536, 540, 544, 548, 552, 556, 560, 564, 568, 569, 572, 575, 578, 581, 584, 587, 590, 593, 596, 599, 602, 605, 608, 611, 614, 617, 620, 623, 626, 629, 632, 635, 638, 641, 644, 647, 650, 653, 656, 659, 662, 665, 668, 671, 674, 677, 680, 683, 686, 689, 692, 695, 698, 701, 704, 707, 710, 713, 716, 719, 722, 725, 742, 759, 776, 793, 810, 827, 844, 861, 878, 895, 912, 929, 946, 974, 994, 1015, 1036, 1056, 1063, 1068, 1073, 1082, 1097, 1111, 1122, 1131, 1143, 1147, 1162, 1165, 1172, 1194, 1209, 1220, 1224, 1243, 1248, 1266, 1274, 1282, 1288, 1300, 1310, 1337, 1360, 1365, 1381, 1386, 1397, 1419, 1435, 1458, 1461, 1466, 1471, 1489, 1496, 1514, 1528, 1532, 1557, 1577, 1581, 1587, 1593, 1600, 1607, 1614, 1621, 1627, 1633, 1643, 1664, 1675, 1683, 1702, 1706, 1708, 1734, 1754, 1762, 1777, 1786, 1800, 1809, 1819, 1829, 1838, 1847, 1860, 1864, 1874, 1883, 1897, 1902, 1907, 1918, 1937} + +func functionNameV7(i int) string { + if i < 0 || i > 301 { + return "" + } + return _names_V7[_index_V7[i]:_index_V7[i+1]] +} + +func functionV7(id int) rideFunction { + if id < 0 || id > 301 { + return nil + } + return _functions_V7[id] +} + +func functionsV7(name string) (rideFunction, bool) { + f, ok := _functions_map_V7[name] + return f, ok +} + +func expressionFunctionsV7(name string) (rideFunction, bool) { + if name == "1020" || name == "1021" { + return nil, false + } + f, ok := _functions_map_V7[name] + return f, ok +} + +func checkFunctionV7(name string) (uint16, bool) { + for i := 0; i <= 301; i++ { + if _names_V7[_index_V7[i]:_index_V7[i+1]] == name { + return uint16(i), true + } + } + return 0, false +} + +func costV7(id int) int { + if id < 0 || id > 301 { + return -1 + } + return _catalogue_V7[id] +} diff --git a/pkg/ride/functions_proto.go b/pkg/ride/functions_proto.go index 90baf52b6..3ba4759bc 100644 --- a/pkg/ride/functions_proto.go +++ b/pkg/ride/functions_proto.go @@ -844,7 +844,22 @@ func blockInfoByHeight(env environment, args ...rideType) (rideType, error) { if err != nil { return nil, errors.Wrap(err, "blockInfoByHeight") } - obj, err := blockHeaderToObject(env.scheme(), height, header, vrf) + v, err := env.libVersion() + if err != nil { + return nil, errors.Wrap(err, "blockInfoByHeight") + } + if v >= ast.LibV7 { + rewards, err := env.state().BlockRewards(header, height) + if err != nil { + return nil, errors.Wrap(err, "blockInfoByHeight") + } + obj, err := blockHeaderToObjectV7(env.scheme(), height, header, vrf, rewards) + if err != nil { + return nil, errors.Wrap(err, "blockInfoByHeight") + } + return obj, nil + } + obj, err := blockHeaderToObjectV1V6(env.scheme(), height, header, vrf) if err != nil { return nil, errors.Wrap(err, "blockInfoByHeight") } diff --git a/pkg/ride/generate/internal/constants_generation.go b/pkg/ride/generate/internal/constants_generation.go index b7df0727f..a5ef3f82b 100644 --- a/pkg/ride/generate/internal/constants_generation.go +++ b/pkg/ride/generate/internal/constants_generation.go @@ -71,6 +71,10 @@ func constantsV6() map[string]constantDescription { return constantsV5() } +func constantsV7() map[string]constantDescription { + return constantsV6() +} + func createConstants(cd *Coder, ver string, c map[string]constantDescription) { keys := make([]string, 0, len(c)) for k := range c { @@ -154,6 +158,7 @@ func GenerateConstants(fn string) { createConstants(cd, "V4", constantsV4()) createConstants(cd, "V5", constantsV5()) createConstants(cd, "V6", constantsV6()) + createConstants(cd, "V7", constantsV7()) createConstructors(cd, constantsV4()) if err := cd.Save(fn); err != nil { diff --git a/pkg/ride/generate/internal/constructors_generation.go b/pkg/ride/generate/internal/constructors_generation.go index 848e17a86..a4455996f 100644 --- a/pkg/ride/generate/internal/constructors_generation.go +++ b/pkg/ride/generate/internal/constructors_generation.go @@ -7,6 +7,7 @@ import ( "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/ride/ast" + "github.com/wavesplatform/gowaves/pkg/ride/compiler/stdlib" "github.com/wavesplatform/gowaves/pkg/ride/generate/internal/vinfo" ) @@ -43,31 +44,40 @@ func extractConstructorArguments(args []actionField) ([]actionField, error) { return arguments, nil } -func checkListElementsTypes(cd *Coder, constructorName string, topListVarName string, info *listTypeInfo) { - var helper func(listVarName string, info *listTypeInfo) - - helper = func(listVarName string, info *listTypeInfo) { - cd.Line("for _, elem := range %s {", listVarName) - cd.Line("switch t := elem.(type) {") - - onelineTypes := make([]string, 0, len(info.ElementTypes())) - for _, tInfo := range info.ElementTypes() { - switch t := tInfo.(type) { - case *listTypeInfo: - cd.Line("case %s: ", t.String()) - helper("t", t) - default: - onelineTypes = append(onelineTypes, t.String()) +func checkListElementsTypes(cd *Coder, constructorName string, topListVarName string, list stdlib.ListType) { + var helper func(listVarName string, ti stdlib.Type) + + helper = func(listVarName string, t stdlib.Type) { + cd.Line("for _, el := range %s {", listVarName) + cd.Line("switch te := el.(type) {") + + switch tt := t.(type) { + case stdlib.SimpleType: + cd.Line("case %s:", getType(tt)) + case stdlib.UnionType: + ts, l, lt := getUnionType(tt) + if l { + cd.Line("case %s:", getType(lt)) + helper("te", lt.Type) } + cd.Line("case %s:", ts) + case stdlib.TupleType: + cd.Line("case tuple%d:", len(tt.Types)) + for i, elt := range tt.Types { + cd.Line("if _, ok := te.el%d.(%s); !ok {", i+1, getType(elt)) + cd.Line("return nil, errors.Errorf(\"%s: unexpected type '%%s' of element %d in %s list tuple\", te.el%d.instanceOf())", constructorName, i+1, topListVarName, i+1) + cd.Line("}") + } + case stdlib.ListType: + cd.Line("case %s: ", getType(tt)) + helper(listVarName, tt.Type) } - - cd.Line("case %s:", strings.Join(onelineTypes, ",")) cd.Line("default:") - cd.Line("return nil, errors.Errorf(\"%s: unexpected type '%%s' in %s list\", t.instanceOf())", constructorName, topListVarName) + cd.Line("return nil, errors.Errorf(\"%s: unexpected type '%%s' in %s list\", te.instanceOf())", constructorName, topListVarName) cd.Line("}") cd.Line("}") } - helper(topListVarName, info) + helper(topListVarName, list.Type) } func constructorsFunctions(ver ast.LibraryVersion, m map[string]string) { @@ -157,26 +167,38 @@ func constructorsHandleRideObject(cd *Coder, obj rideObject) error { for i, arg := range arguments { varName := argVarName(arg) + t := stdlib.ParseRuntimeType(arg.Type) + switch att := t.(type) { + case stdlib.SimpleType: + cd.Line("%s, ok := args_[%d].(%s)", varName, i, getType(att)) + cd.Line("if !ok {") + cd.Line("return nil, errors.Errorf(\"%s: unexpected type '%%s' for %s\", args_[%d].instanceOf())", constructorName, varName, i) + cd.Line("}") + case stdlib.TupleType: + l := len(att.Types) + cd.Line("%s, ok := args_[%d].(tuple%d)", varName, i, l) + cd.Line("if !ok {") + cd.Line("return nil, errors.Errorf(\"%s: unexpected type '%%s' for %s\", args_[%d].instanceOf())", constructorName, varName, i) + cd.Line("}") + for i, elt := range att.Types { + cd.Line("if _, ok := t.el%d.(%s); !ok {", i+1, getType(elt)) + cd.Line("return nil, errors.Errorf(\"%s: unexpected type '%%s' of element %d in %s tuple\", t.instanceOf())", constructorName, i+1, varName) + cd.Line("}") + } - if len(arg.Types) == 1 { - info := arg.Types[0] - cd.Line("%s, ok := args_[%d].(%s)", varName, i, info) + case stdlib.ListType: + cd.Line("%s, ok := args_[%d].(%s)", varName, i, getType(att)) cd.Line("if !ok {") cd.Line("return nil, errors.Errorf(\"%s: unexpected type '%%s' for %s\", args_[%d].instanceOf())", constructorName, varName, i) cd.Line("}") + cd.Line("// checks for list elements") + checkListElementsTypes(cd, constructorName, varName, att) - if listInfo, ok := info.(*listTypeInfo); ok { - cd.Line("// checks for list elements") - checkListElementsTypes(cd, constructorName, varName, listInfo) - } - } else { + case stdlib.UnionType: + ts, _, _ := getUnionType(att) cd.Line("var %s rideType", varName) cd.Line("switch v := args_[%d].(type) {", i) - onelineTypes := make([]string, 0, len(arg.Types)) - for _, t := range arg.Types { - onelineTypes = append(onelineTypes, t.String()) - } - cd.Line("case %s:", strings.Join(onelineTypes, ", ")) + cd.Line("case %s:", ts) cd.Line("%s = v", varName) cd.Line("default:") cd.Line("return nil, errors.Errorf(\"%s: unexpected type '%%s' for %s\", args_[%d].instanceOf())", constructorName, varName, i) diff --git a/pkg/ride/generate/internal/functions_generation.go b/pkg/ride/generate/internal/functions_generation.go index d05bfc028..00e672122 100644 --- a/pkg/ride/generate/internal/functions_generation.go +++ b/pkg/ride/generate/internal/functions_generation.go @@ -801,6 +801,12 @@ func functionsV6() map[string]string { return m } +func functionsV7() map[string]string { + m := functionsV6() + constructorsFunctions(ast.LibV7, m) + return m +} + func catalogueV6() map[string]int { m := catalogueV5() m["3"] = 1 @@ -849,6 +855,12 @@ func catalogueV6() map[string]int { return m } +func catalogueV7() map[string]int { + m := catalogueV6() + constructorsCatalogue(ast.LibV7, m) + return m +} + func evaluationCatalogueV6EvaluatorV1() map[string]int { m := catalogueV6() m["throw"] = 2 @@ -901,6 +913,18 @@ func evaluationCatalogueV6EvaluatorV2() map[string]int { return m } +func evaluationCatalogueV7EvaluatorV1() map[string]int { + m := evaluationCatalogueV6EvaluatorV1() + constructorsEvaluationCatalogueEvaluatorV1(ast.LibV7, m) + return m +} + +func evaluationCatalogueV7EvaluatorV2() map[string]int { + m := evaluationCatalogueV6EvaluatorV2() + constructorsEvaluationCatalogueEvaluatorV2(ast.LibV7, m) + return m +} + func constructorsFromConstants(m map[string]string, c map[string]constantDescription) { for _, v := range c { if v.constructor == "" { @@ -1023,6 +1047,7 @@ func GenerateFunctions(fn string) { createFunctionsList(cd, "V4", functionsV4(), catalogueV4(), evaluationCatalogueV4EvaluatorV1(), evaluationCatalogueV4EvaluatorV2()) createFunctionsList(cd, "V5", functionsV5(), catalogueV5(), evaluationCatalogueV5EvaluatorV1(), evaluationCatalogueV5EvaluatorV2()) createFunctionsList(cd, "V6", functionsV6(), catalogueV6(), evaluationCatalogueV6EvaluatorV1(), evaluationCatalogueV6EvaluatorV2()) + createFunctionsList(cd, "V7", functionsV7(), catalogueV7(), evaluationCatalogueV7EvaluatorV1(), evaluationCatalogueV7EvaluatorV2()) if err := cd.Save(fn); err != nil { panic(err) } diff --git a/pkg/ride/generate/internal/generator_config.go b/pkg/ride/generate/internal/generator_config.go index af673b631..5268bdd55 100644 --- a/pkg/ride/generate/internal/generator_config.go +++ b/pkg/ride/generate/internal/generator_config.go @@ -5,131 +5,16 @@ import ( "fmt" "os" "sort" - "strconv" - "strings" "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/ride/ast" ) type actionField struct { - Name string `json:"name"` - Types typeInfos `json:"types"` - Order int `json:"order"` // order for string representation - ConstructorOrder int `json:"constructorOrder"` // order for constructor -} - -type typeInfo interface { - fmt.Stringer - json.Unmarshaler -} - -type typeInfos []typeInfo - -func (infos *typeInfos) UnmarshalJSON(data []byte) error { - var rawTypes []string - if err := json.Unmarshal(data, &rawTypes); err != nil { - return errors.Wrap(err, "typeInfos raw types unmarshal") - } - - typeInfoList := make([]typeInfo, len(rawTypes)) - for i, name := range rawTypes { - typeInfoList[i] = guessInfoType(name) - } - - if err := json.Unmarshal(data, &typeInfoList); err != nil { - return errors.Wrapf(err, "typeInfoList unmarshal(%s)", strings.Join(rawTypes, ",")) - } - *infos = typeInfoList - - return nil -} - -func guessInfoType(typeName string) typeInfo { - if strings.HasPrefix(typeName, "List") { - return &listTypeInfo{} - } - return &simpleTypeInfo{} -} - -type simpleTypeInfo struct { - name string -} - -func (info *simpleTypeInfo) String() string { - return "ride" + info.name -} - -func (info *simpleTypeInfo) UnmarshalJSON(data []byte) error { - if err := json.Unmarshal(data, &info.name); err != nil { - return errors.Wrap(err, "unmarshal type name") - } - return nil -} - -type listTypeInfo struct { - elementsTypes typeInfos -} - -func (info *listTypeInfo) String() string { - return "rideList" -} - -func (info *listTypeInfo) UnmarshalJSON(data []byte) error { - var source string - if err := json.Unmarshal(data, &source); err != nil { - return errors.Wrap(err, "listTypeInfo unmarshal raw string") - } - - if !strings.HasPrefix(source, "List") { - return errors.Errorf("'%s' is missing: %s", info.String(), source) - } - source = strings.ReplaceAll(string(data), " ", "") - - begin, end := strings.Index(source, "["), strings.LastIndex(source, "]") - if begin == -1 || end == -1 || begin == end { - return errors.Errorf("bad brace sequence in elements types: %s", source) - } - begin++ - - var typeNames []string - opened := 0 - for cur := begin; cur < end; cur++ { - switch source[cur] { - case '[': - opened++ - case ']': - if opened == 0 { - return errors.Errorf("bad bracket sequence: %s", source) - } - opened-- - case '|': - if opened == 0 { - typeNames = append(typeNames, source[begin:cur]) - begin = cur + 1 - } - } - } - typeNames = append(typeNames, source[begin:end]) - if opened != 0 { - return errors.Errorf("bad bracket sequence:%s", source) - } - - var jsonStr strings.Builder - jsonStr.WriteByte('[') - for i, name := range typeNames { - jsonStr.WriteString(strconv.Quote(name)) - if i != len(typeNames)-1 { - jsonStr.WriteByte(',') - } - } - jsonStr.WriteByte(']') - - return json.Unmarshal([]byte(jsonStr.String()), &info.elementsTypes) -} - -func (info *listTypeInfo) ElementTypes() typeInfos { - return info.elementsTypes + Name string `json:"name"` + Type string `json:"type"` + Order int `json:"order"` // order for string representation + ConstructorOrder int `json:"constructorOrder"` // order for constructor } type actionsObject struct { diff --git a/pkg/ride/generate/internal/objects_generation.go b/pkg/ride/generate/internal/objects_generation.go index 66339209f..cc682d853 100644 --- a/pkg/ride/generate/internal/objects_generation.go +++ b/pkg/ride/generate/internal/objects_generation.go @@ -4,24 +4,44 @@ import ( "fmt" "sort" "strings" -) -var ( - versionString = []string{"V1", "V2", "V3", "V4", "V5", "V6"} + "github.com/wavesplatform/gowaves/pkg/ride/ast" + "github.com/wavesplatform/gowaves/pkg/ride/compiler/stdlib" ) func removeVersionFromString(name string) string { - for _, v := range versionString { - name = strings.ReplaceAll(name, v, "") + for v := ast.LibV1; v <= ast.CurrentMaxLibraryVersion(); v++ { + vs := fmt.Sprintf("V%d", v) + name = strings.ReplaceAll(name, vs, "") } return name } -func getType(types typeInfos) string { - if len(types) == 1 { - return types[0].String() +func getType(t stdlib.Type) string { + switch t.(type) { + case stdlib.SimpleType: + return "ride" + t.String() + case stdlib.ListType: + return "rideList" + default: + return "rideType" + } +} + +func getUnionType(union stdlib.UnionType) (string, bool, stdlib.ListType) { + ns := make([]string, 0, len(union.Types)) + hasList := false + listType := stdlib.ListType{} + for _, t := range union.Types { + switch tt := t.(type) { + case stdlib.ListType: + hasList = true + listType = tt + case stdlib.SimpleType: + ns = append(ns, getType(t)) + } } - return "rideType" + return strings.Join(ns, ", "), hasList, listType } func rideActionConstructorName(act actionsObject) string { @@ -83,7 +103,8 @@ func GenerateObjects(configPath, fn string) { // Struct Implementation cd.Line("type ride%s struct {", act.StructName) for _, field := range act.Fields { - cd.Line("%s %s", field.Name, getType(field.Types)) + ft := stdlib.ParseRuntimeType(field.Type) + cd.Line("%s %s", field.Name, getType(ft)) } cd.Line("}") cd.Line("") @@ -92,7 +113,8 @@ func GenerateObjects(configPath, fn string) { constructorName := rideActionConstructorName(act) arguments := make([]string, len(act.Fields)) for i, field := range act.Fields { - arguments[i] = fmt.Sprintf("%s %s", field.Name, getType(field.Types)) + ft := stdlib.ParseRuntimeType(field.Type) + arguments[i] = fmt.Sprintf("%s %s", field.Name, getType(ft)) } cd.Line("func %s(%s) ride%s {", constructorName, strings.Join(arguments, ", "), act.StructName) cd.Line("return ride%s{", act.StructName) diff --git a/pkg/ride/objects.gen.go b/pkg/ride/objects.gen.go index b4b20e4ff..61cbbcdb9 100644 --- a/pkg/ride/objects.gen.go +++ b/pkg/ride/objects.gen.go @@ -109,6 +109,7 @@ const ( recipientField = "recipient" regularField = "regular" reissuableField = "reissuable" + rewardsField = "rewards" scriptField = "script" scriptedField = "scripted" sellMatcherFeeField = "sellMatcherFee" @@ -800,6 +801,113 @@ func (o rideBlockInfoV4) String() string { return strings.Join(o.lines(), "\n") } +type rideBlockInfoV7 struct { + vrf rideType + generationSignature rideByteVector + generatorPublicKey rideByteVector + baseTarget rideInt + timestamp rideInt + height rideInt + generator rideAddress + rewards rideList +} + +func newRideBlockInfoV7(vrf rideType, generationSignature rideByteVector, generatorPublicKey rideByteVector, baseTarget rideInt, timestamp rideInt, height rideInt, generator rideAddress, rewards rideList) rideBlockInfoV7 { + return rideBlockInfoV7{ + vrf: vrf, + generationSignature: generationSignature, + generatorPublicKey: generatorPublicKey, + baseTarget: baseTarget, + timestamp: timestamp, + height: height, + generator: generator, + rewards: rewards, + } +} + +func (o rideBlockInfoV7) instanceOf() string { + return "BlockInfo" +} + +func (o rideBlockInfoV7) eq(other rideType) bool { + if oo, ok := other.(rideBlockInfoV7); ok { + if !o.vrf.eq(oo.vrf) { + return false + } + if !o.generationSignature.eq(oo.generationSignature) { + return false + } + if !o.generatorPublicKey.eq(oo.generatorPublicKey) { + return false + } + if !o.baseTarget.eq(oo.baseTarget) { + return false + } + if !o.timestamp.eq(oo.timestamp) { + return false + } + if !o.height.eq(oo.height) { + return false + } + if !o.generator.eq(oo.generator) { + return false + } + if !o.rewards.eq(oo.rewards) { + return false + } + return true + } + return false +} + +func (o rideBlockInfoV7) get(prop string) (rideType, error) { + switch prop { + case "$instance": + return rideString("BlockInfo"), nil + case "vrf": + return o.vrf, nil + case "generationSignature": + return o.generationSignature, nil + case "generatorPublicKey": + return o.generatorPublicKey, nil + case "baseTarget": + return o.baseTarget, nil + case "timestamp": + return o.timestamp, nil + case "height": + return o.height, nil + case "generator": + return o.generator, nil + case "rewards": + return o.rewards, nil + default: + return nil, errors.Errorf("type '%s' has no property '%s'", o.instanceOf(), prop) + } +} + +func (o rideBlockInfoV7) copy() rideType { + return newRideBlockInfoV7(o.vrf, o.generationSignature, o.generatorPublicKey, o.baseTarget, o.timestamp, o.height, o.generator, o.rewards) +} + +func (o rideBlockInfoV7) lines() []string { + r := make([]string, 0, 10) + r = append(r, "BlockInfo(") + r = append(r, fieldLines("baseTarget", o.baseTarget.lines())...) + r = append(r, fieldLines("generator", o.generator.lines())...) + r = append(r, fieldLines("timestamp", o.timestamp.lines())...) + r = append(r, fieldLines("vrf", o.vrf.lines())...) + r = append(r, fieldLines("height", o.height.lines())...) + r = append(r, fieldLines("generationSignature", o.generationSignature.lines())...) + r = append(r, fieldLines("generatorPublicKey", o.generatorPublicKey.lines())...) + r = append(r, fieldLines("rewards", o.rewards.lines())...) + r = append(r, ")") + return r +} + +func (o rideBlockInfoV7) String() string { + return strings.Join(o.lines(), "\n") +} + type rideBooleanEntry struct { key rideString value rideBoolean diff --git a/pkg/ride/selectors.go b/pkg/ride/selectors.go index 740f6c530..08fd85585 100644 --- a/pkg/ride/selectors.go +++ b/pkg/ride/selectors.go @@ -20,6 +20,11 @@ func selectFunctionsByName(v ast.LibraryVersion, enableInvocation bool) (func(st return functionsV6, nil } return expressionFunctionsV6, nil + case ast.LibV7: + if enableInvocation { + return functionsV7, nil + } + return expressionFunctionsV7, nil default: return nil, EvaluationFailure.Errorf("unsupported library version '%d'", v) } @@ -37,6 +42,8 @@ func selectFunctions(v ast.LibraryVersion) (func(id int) rideFunction, error) { return functionV5, nil case ast.LibV6: return functionV6, nil + case ast.LibV7: + return functionV7, nil default: return nil, EvaluationFailure.Errorf("unsupported library version '%d'", v) } @@ -54,6 +61,8 @@ func selectFunctionChecker(v ast.LibraryVersion) (func(name string) (uint16, boo return checkFunctionV5, nil case ast.LibV6: return checkFunctionV6, nil + case ast.LibV7: + return checkFunctionV7, nil default: return nil, EvaluationFailure.Errorf("unsupported library version '%d'", v) } @@ -91,6 +100,8 @@ func selectEvaluationCostsProvider(v ast.LibraryVersion, ev int) (map[string]int } case ast.LibV6: // Only new version of evaluator works after activation of RideV6 return EvaluationCatalogueV6EvaluatorV2, nil + case ast.LibV7: + return EvaluationCatalogueV7EvaluatorV2, nil default: return nil, EvaluationFailure.Errorf("unsupported library version '%d'", v) } @@ -108,6 +119,8 @@ func selectFunctionNameProvider(v ast.LibraryVersion) (func(int) string, error) return functionNameV5, nil case ast.LibV6: return functionNameV6, nil + case ast.LibV7: + return functionNameV7, nil default: return nil, EvaluationFailure.Errorf("unsupported library version '%d'", v) } @@ -127,6 +140,8 @@ func selectConstants(v ast.LibraryVersion) (func(int) rideConstructor, error) { return constantV5, nil case ast.LibV6: return constantV6, nil + case ast.LibV7: + return constantV7, nil default: return nil, EvaluationFailure.Errorf("unsupported library version '%d'", v) } @@ -146,6 +161,8 @@ func selectConstantsChecker(v ast.LibraryVersion) (func(name string) (uint16, bo return checkConstantV5, nil case ast.LibV6: return checkConstantV6, nil + case ast.LibV7: + return checkConstantV7, nil default: return nil, EvaluationFailure.Errorf("unsupported library version '%d'", v) } diff --git a/pkg/ride/smart_state_moq_test.go b/pkg/ride/smart_state_moq_test.go index fb4700702..4e709077c 100644 --- a/pkg/ride/smart_state_moq_test.go +++ b/pkg/ride/smart_state_moq_test.go @@ -24,6 +24,9 @@ var _ types.SmartState = &MockSmartState{} // AddingBlockHeightFunc: func() (uint64, error) { // panic("mock out the AddingBlockHeight method") // }, +// BlockRewardsFunc: func(blockHeader *proto.BlockHeader, height uint64) (proto.Rewards, error) { +// panic("mock out the BlockRewards method") +// }, // BlockVRFFunc: func(blockHeader *proto.BlockHeader, height uint64) ([]byte, error) { // panic("mock out the BlockVRF method") // }, @@ -115,6 +118,9 @@ type MockSmartState struct { // AddingBlockHeightFunc mocks the AddingBlockHeight method. AddingBlockHeightFunc func() (uint64, error) + // BlockRewardsFunc mocks the BlockRewards method. + BlockRewardsFunc func(blockHeader *proto.BlockHeader, height uint64) (proto.Rewards, error) + // BlockVRFFunc mocks the BlockVRF method. BlockVRFFunc func(blockHeader *proto.BlockHeader, height uint64) ([]byte, error) @@ -201,6 +207,13 @@ type MockSmartState struct { // AddingBlockHeight holds details about calls to the AddingBlockHeight method. AddingBlockHeight []struct { } + // BlockRewards holds details about calls to the BlockRewards method. + BlockRewards []struct { + // BlockHeader is the blockHeader argument value. + BlockHeader *proto.BlockHeader + // Height is the height argument value. + Height uint64 + } // BlockVRF holds details about calls to the BlockVRF method. BlockVRF []struct { // BlockHeader is the blockHeader argument value. @@ -350,6 +363,7 @@ type MockSmartState struct { } } lockAddingBlockHeight sync.RWMutex + lockBlockRewards sync.RWMutex lockBlockVRF sync.RWMutex lockEstimatorVersion sync.RWMutex lockIsNotFound sync.RWMutex @@ -406,6 +420,42 @@ func (mock *MockSmartState) AddingBlockHeightCalls() []struct { return calls } +// BlockRewards calls BlockRewardsFunc. +func (mock *MockSmartState) BlockRewards(blockHeader *proto.BlockHeader, height uint64) (proto.Rewards, error) { + if mock.BlockRewardsFunc == nil { + panic("MockSmartState.BlockRewardsFunc: method is nil but SmartState.BlockRewards was just called") + } + callInfo := struct { + BlockHeader *proto.BlockHeader + Height uint64 + }{ + BlockHeader: blockHeader, + Height: height, + } + mock.lockBlockRewards.Lock() + mock.calls.BlockRewards = append(mock.calls.BlockRewards, callInfo) + mock.lockBlockRewards.Unlock() + return mock.BlockRewardsFunc(blockHeader, height) +} + +// BlockRewardsCalls gets all the calls that were made to BlockRewards. +// Check the length with: +// +// len(mockedSmartState.BlockRewardsCalls()) +func (mock *MockSmartState) BlockRewardsCalls() []struct { + BlockHeader *proto.BlockHeader + Height uint64 +} { + var calls []struct { + BlockHeader *proto.BlockHeader + Height uint64 + } + mock.lockBlockRewards.RLock() + calls = mock.calls.BlockRewards + mock.lockBlockRewards.RUnlock() + return calls +} + // BlockVRF calls BlockVRFFunc. func (mock *MockSmartState) BlockVRF(blockHeader *proto.BlockHeader, height uint64) ([]byte, error) { if mock.BlockVRFFunc == nil { diff --git a/pkg/ride/test_helpers_test.go b/pkg/ride/test_helpers_test.go index ecccd32db..0ec5e0937 100644 --- a/pkg/ride/test_helpers_test.go +++ b/pkg/ride/test_helpers_test.go @@ -388,6 +388,27 @@ func (e *testEnv) withBlock(blockInfo *proto.BlockInfo) *testEnv { return e } +func (e *testEnv) withBlockHeader(blockHeader *proto.BlockHeader) *testEnv { + e.ms.NewestHeaderByHeightFunc = func(height uint64) (*proto.BlockHeader, error) { + return blockHeader, nil + } + return e +} + +func (e *testEnv) withBlockVRF(vrf []byte) *testEnv { + e.ms.BlockVRFFunc = func(blockHeader *proto.BlockHeader, height uint64) ([]byte, error) { + return vrf, nil + } + return e +} + +func (e *testEnv) withBlockRewards(rewards proto.Rewards) *testEnv { + e.ms.BlockRewardsFunc = func(blockHeader *proto.BlockHeader, height uint64) (proto.Rewards, error) { + return rewards, nil + } + return e +} + func (e *testEnv) withProtobufTx() *testEnv { e.me.isProtobufTxFunc = func() bool { return true diff --git a/pkg/ride/tree_estimatorV1.go b/pkg/ride/tree_estimatorV1.go index 654cebe67..26efc0d7d 100644 --- a/pkg/ride/tree_estimatorV1.go +++ b/pkg/ride/tree_estimatorV1.go @@ -101,6 +101,8 @@ func newTreeEstimatorV1(tree *ast.Tree) (*treeEstimatorV1, error) { r.scope = newEstimationScopeV1(ConstantsV5, CatalogueV5) case ast.LibV6: r.scope = newEstimationScopeV1(ConstantsV6, CatalogueV6) + case ast.LibV7: + r.scope = newEstimationScopeV1(ConstantsV7, CatalogueV7) default: return nil, errors.Errorf("unsupported library version %d", tree.LibVersion) } diff --git a/pkg/ride/tree_estimatorV2.go b/pkg/ride/tree_estimatorV2.go index 7e60194a5..4e897ebd5 100644 --- a/pkg/ride/tree_estimatorV2.go +++ b/pkg/ride/tree_estimatorV2.go @@ -105,6 +105,8 @@ func newTreeEstimatorV2(tree *ast.Tree) (*treeEstimatorV2, error) { r.scope = newEstimationScopeV2(ConstantsV5, CatalogueV5) case ast.LibV6: r.scope = newEstimationScopeV2(ConstantsV6, CatalogueV6) + case ast.LibV7: + r.scope = newEstimationScopeV2(ConstantsV7, CatalogueV7) default: return nil, errors.Errorf("unsupported library version %d", tree.LibVersion) } diff --git a/pkg/ride/tree_estimatorV3.go b/pkg/ride/tree_estimatorV3.go index baa19cc02..226ce78b6 100644 --- a/pkg/ride/tree_estimatorV3.go +++ b/pkg/ride/tree_estimatorV3.go @@ -157,6 +157,8 @@ func newTreeEstimatorV3(tree *ast.Tree) (*treeEstimatorV3, error) { r.scope = newEstimationScopeV3(CatalogueV5) case ast.LibV6: r.scope = newEstimationScopeV3(CatalogueV6) + case ast.LibV7: + r.scope = newEstimationScopeV3(CatalogueV7) default: return nil, errors.Errorf("unsupported library version %d", tree.LibVersion) } diff --git a/pkg/ride/tree_estimatorV4.go b/pkg/ride/tree_estimatorV4.go index 8fce0f838..a1b325472 100644 --- a/pkg/ride/tree_estimatorV4.go +++ b/pkg/ride/tree_estimatorV4.go @@ -24,6 +24,8 @@ func newTreeEstimatorV4(tree *ast.Tree) (*treeEstimatorV4, error) { r.scope = newEstimationScopeV3(CatalogueV5) case ast.LibV6: r.scope = newEstimationScopeV3(CatalogueV6) + case ast.LibV7: + r.scope = newEstimationScopeV3(CatalogueV7) default: return nil, errors.Errorf("unsupported library version %d", tree.LibVersion) } diff --git a/pkg/ride/tree_evaluation_test.go b/pkg/ride/tree_evaluation_test.go index a54e781a0..4eff42914 100644 --- a/pkg/ride/tree_evaluation_test.go +++ b/pkg/ride/tree_evaluation_test.go @@ -12,6 +12,7 @@ import ( "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/ride/ast" + ridec "github.com/wavesplatform/gowaves/pkg/ride/compiler" "github.com/wavesplatform/gowaves/pkg/util/byte_helpers" ) @@ -5038,7 +5039,7 @@ func TestInvokeActionsCountRestrictionsV6ToV5WithBlockRewardDistribution(t *test strict a3 = invoke(dApp2, "call", [], []) # 30 actions strict b3 = invoke(dApp3, "call", [], []) # check V5 - OK strict a4 = invoke(dApp2, "call", [], []) # 40 actions - strict b4 = invoke(dApp3, "call", [], []) # check V5 - OK + strict b4 = invoke(dApp3, "call", [], []) # check V5 - FAIL [] } */ @@ -5597,3 +5598,75 @@ func TestDefaultFunction(t *testing.T) { _, err = CallFunction(env.withComplexityLimit(ast.LibV5, 2000).toEnv(), tree1, proto.NewFunctionCall("default", args)) assert.NoError(t, err) } + +func TestRideBlockInfoV7(t *testing.T) { + dApp1 := newTestAccount(t, "DAPP1") // 3MzDtgL5yw73C2xVLnLJCrT5gCL4357a4sz + sender := newTestAccount(t, "SENDER") // 3N8CkZAyS4XcDoJTJoKNuNk2xmNKmQj7myW + + src1 := ` + {-# STDLIB_VERSION 7 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + let sender = addressFromStringValue("3N8CkZAyS4XcDoJTJoKNuNk2xmNKmQj7myW") + let dapp1 = addressFromStringValue("3MzDtgL5yw73C2xVLnLJCrT5gCL4357a4sz") + + func rewardFor(rwds: List[(Address, Int)], target: Address) = { + let s = rwds.size() + let (a0, r0) = rwds[0] + let (a1, r1) = rwds[1] + let (a2, r2) = rwds[2] + if (s > 0 && a0 == target) then r0 + else if (s > 1 && a1 == target) then r1 + else if (s > 2 && a2 == target) then r2 + else unit + } + + @Callable(i) + func foo() = { + match blockInfoByHeight(height) { + case block: BlockInfo => + let r1 = rewardFor(block.rewards, sender).value() + let r2 = rewardFor(block.rewards, dapp1).value() + [IntegerEntry("sender", r1), IntegerEntry("dapp1", r2)] + case _ => throw("Can't find block") + } + } + ` + tree1, errs := ridec.CompileToTree(src1) + require.Empty(t, errs) + + blockHeader := &proto.BlockHeader{ + Version: proto.ProtobufBlockVersion, + GeneratorPublicKey: sender.publicKey(), + } + rewards := proto.Rewards{proto.NewReward(dApp1.address(), 67890), proto.NewReward(sender.address(), 12345)} + + env := newTestEnv(t).withLibVersion(ast.LibV7).withComplexityLimit(ast.LibV7, 2000). + withBlockV5Activated().withProtobufTx().withRideV6Activated().withBlockRewardDistribution(). + withDataEntriesSizeV2().withMessageLengthV3().withValidateInternalPayments(). + withThis(dApp1).withDApp(dApp1).withSender(sender).withHeight(12345). + withBlockHeader(blockHeader).withBlockVRF(nil).withBlockRewards(rewards). + withInvocation("foo", withTransactionID(crypto.Digest{})).withTree(dApp1, tree1). + withWrappedState() + res, err := CallFunction(env.toEnv(), tree1, proto.NewFunctionCall("foo", proto.Arguments{})) + require.NoError(t, err) + assert.Equal(t, 2, len(res.ScriptActions())) + r, ok := res.(DAppResult) + require.True(t, ok) + + sr, _, err := proto.NewScriptResult(r.actions, proto.ScriptErrorMessage{}) + require.NoError(t, err) + expectedResult := &proto.ScriptResult{ + DataEntries: []*proto.DataEntryScriptAction{{Entry: &proto.IntegerDataEntry{Key: "sender", Value: 12345}}, {Entry: &proto.IntegerDataEntry{Key: "dapp1", Value: 67890}}}, + Transfers: make([]*proto.TransferScriptAction, 0), + Issues: make([]*proto.IssueScriptAction, 0), + Reissues: make([]*proto.ReissueScriptAction, 0), + Burns: make([]*proto.BurnScriptAction, 0), + Sponsorships: make([]*proto.SponsorshipScriptAction, 0), + Leases: make([]*proto.LeaseScriptAction, 0), + LeaseCancels: make([]*proto.LeaseCancelScriptAction, 0), + ErrorMsg: proto.ScriptErrorMessage{}, + } + assert.Equal(t, expectedResult, sr) +} diff --git a/pkg/ride/tree_evaluator.go b/pkg/ride/tree_evaluator.go index c1ebdafc7..5b3af4277 100644 --- a/pkg/ride/tree_evaluator.go +++ b/pkg/ride/tree_evaluator.go @@ -178,6 +178,8 @@ func selectConstantNames(v ast.LibraryVersion) ([]string, error) { return ConstantsV5, nil case ast.LibV6: return ConstantsV6, nil + case ast.LibV7: + return ConstantsV7, nil default: return nil, EvaluationFailure.Errorf("unsupported library version %d", v) } diff --git a/pkg/state/smart_state_moq_test.go b/pkg/state/smart_state_moq_test.go index 93216fd99..5f55681e2 100644 --- a/pkg/state/smart_state_moq_test.go +++ b/pkg/state/smart_state_moq_test.go @@ -24,6 +24,9 @@ var _ types.SmartState = &AnotherMockSmartState{} // AddingBlockHeightFunc: func() (uint64, error) { // panic("mock out the AddingBlockHeight method") // }, +// BlockRewardsFunc: func(blockHeader *proto.BlockHeader, height uint64) (proto.Rewards, error) { +// panic("mock out the BlockRewards method") +// }, // BlockVRFFunc: func(blockHeader *proto.BlockHeader, height uint64) ([]byte, error) { // panic("mock out the BlockVRF method") // }, @@ -115,6 +118,9 @@ type AnotherMockSmartState struct { // AddingBlockHeightFunc mocks the AddingBlockHeight method. AddingBlockHeightFunc func() (uint64, error) + // BlockRewardsFunc mocks the BlockRewards method. + BlockRewardsFunc func(blockHeader *proto.BlockHeader, height uint64) (proto.Rewards, error) + // BlockVRFFunc mocks the BlockVRF method. BlockVRFFunc func(blockHeader *proto.BlockHeader, height uint64) ([]byte, error) @@ -201,6 +207,13 @@ type AnotherMockSmartState struct { // AddingBlockHeight holds details about calls to the AddingBlockHeight method. AddingBlockHeight []struct { } + // BlockRewards holds details about calls to the BlockRewards method. + BlockRewards []struct { + // BlockHeader is the blockHeader argument value. + BlockHeader *proto.BlockHeader + // Height is the height argument value. + Height uint64 + } // BlockVRF holds details about calls to the BlockVRF method. BlockVRF []struct { // BlockHeader is the blockHeader argument value. @@ -350,6 +363,7 @@ type AnotherMockSmartState struct { } } lockAddingBlockHeight sync.RWMutex + lockBlockRewards sync.RWMutex lockBlockVRF sync.RWMutex lockEstimatorVersion sync.RWMutex lockIsNotFound sync.RWMutex @@ -406,6 +420,42 @@ func (mock *AnotherMockSmartState) AddingBlockHeightCalls() []struct { return calls } +// BlockRewards calls BlockRewardsFunc. +func (mock *AnotherMockSmartState) BlockRewards(blockHeader *proto.BlockHeader, height uint64) (proto.Rewards, error) { + if mock.BlockRewardsFunc == nil { + panic("AnotherMockSmartState.BlockRewardsFunc: method is nil but SmartState.BlockRewards was just called") + } + callInfo := struct { + BlockHeader *proto.BlockHeader + Height uint64 + }{ + BlockHeader: blockHeader, + Height: height, + } + mock.lockBlockRewards.Lock() + mock.calls.BlockRewards = append(mock.calls.BlockRewards, callInfo) + mock.lockBlockRewards.Unlock() + return mock.BlockRewardsFunc(blockHeader, height) +} + +// BlockRewardsCalls gets all the calls that were made to BlockRewards. +// Check the length with: +// +// len(mockedSmartState.BlockRewardsCalls()) +func (mock *AnotherMockSmartState) BlockRewardsCalls() []struct { + BlockHeader *proto.BlockHeader + Height uint64 +} { + var calls []struct { + BlockHeader *proto.BlockHeader + Height uint64 + } + mock.lockBlockRewards.RLock() + calls = mock.calls.BlockRewards + mock.lockBlockRewards.RUnlock() + return calls +} + // BlockVRF calls BlockVRFFunc. func (mock *AnotherMockSmartState) BlockVRF(blockHeader *proto.BlockHeader, height uint64) ([]byte, error) { if mock.BlockVRFFunc == nil { diff --git a/pkg/state/state.go b/pkg/state/state.go index bb5192e58..891c13951 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -651,6 +651,31 @@ func (s *stateManager) BlockVRF(blockHeader *proto.BlockHeader, height proto.Hei return vrf, nil } +func (s *stateManager) BlockRewards(blockHeader *proto.BlockHeader, height proto.Height) (proto.Rewards, error) { + reward, err := s.stor.monetaryPolicy.reward() + if err != nil { + return nil, err + } + minerReward := reward + minerAddress, err := proto.NewAddressFromPublicKey(s.settings.AddressSchemeCharacter, blockHeader.GeneratorPublicKey) + if err != nil { + return nil, err + } + active := s.stor.features.newestIsActivatedAtHeight(int16(settings.BlockReward), height) + if !active { + return proto.Rewards{proto.NewReward(minerAddress, minerReward)}, nil + } + numberOfAddresses := uint64(len(s.settings.RewardAddresses) + 1) + r := make(proto.Rewards, 0, numberOfAddresses) + for _, a := range s.settings.RewardAddresses { + addressReward := reward / numberOfAddresses + r = append(r, proto.NewReward(a, addressReward)) + minerReward -= addressReward + } + r = append(r, proto.NewReward(minerAddress, minerReward)) + return r, nil +} + func (s *stateManager) Header(blockID proto.BlockID) (*proto.BlockHeader, error) { header, err := s.rw.readBlockHeader(blockID) if err != nil { diff --git a/pkg/state/transaction_checker.go b/pkg/state/transaction_checker.go index a6d008980..75231c46e 100644 --- a/pkg/state/transaction_checker.go +++ b/pkg/state/transaction_checker.go @@ -83,6 +83,10 @@ func (tc *transactionChecker) scriptActivation(libVersion ast.LibraryVersion, ha if err != nil { return scriptFeaturesActivations{}, err } + blockRewardDistributionActivated, err := tc.stor.features.newestIsActivated(int16(settings.BlockRewardDistribution)) + if err != nil { + return scriptFeaturesActivations{}, err + } if libVersion == ast.LibV3 && !rideForDAppsActivated { return scriptFeaturesActivations{}, errors.New("Ride4DApps feature must be activated for scripts version 3") } @@ -98,6 +102,9 @@ func (tc *transactionChecker) scriptActivation(libVersion ast.LibraryVersion, ha if libVersion == ast.LibV6 && !rideV6Activated { return scriptFeaturesActivations{}, errors.New("RideV6 feature must be activated for scripts version 6") } + if libVersion == ast.LibV7 && !blockRewardDistributionActivated { + return scriptFeaturesActivations{}, errors.New("BlockRewardDistribution feature must be activated for scripts version 7") + } return scriptFeaturesActivations{ rideForDAppsActivated: rideForDAppsActivated, blockV5Activated: blockV5Activated, @@ -117,7 +124,7 @@ func (tc *transactionChecker) checkScriptComplexity(libVersion ast.LibraryVersio | DApp Callable V1, V2 | 2000 | 2000 | | DApp Callable V3, V4 | 4000 | 4000 | | DApp Callable V5 | 10000 | 10000 | - | DApp Callable V6 | 52000 | 52000 | + | DApp Callable V6, V7 | 52000 | 52000 | */ var maxCallableComplexity, maxVerifierComplexity int switch version := libVersion; version { @@ -130,7 +137,7 @@ func (tc *transactionChecker) checkScriptComplexity(libVersion ast.LibraryVersio case ast.LibV5: maxCallableComplexity = MaxCallableScriptComplexityV5 maxVerifierComplexity = MaxVerifierScriptComplexity - case ast.LibV6: + case ast.LibV6, ast.LibV7: maxCallableComplexity = MaxCallableScriptComplexityV6 maxVerifierComplexity = MaxVerifierScriptComplexity default: diff --git a/pkg/types/types.go b/pkg/types/types.go index 9c4adcb76..4ea916a25 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -71,6 +71,7 @@ type SmartState interface { NewestScriptByAsset(assetID crypto.Digest) (*ast.Tree, error) NewestHeaderByHeight(height proto.Height) (*proto.BlockHeader, error) BlockVRF(blockHeader *proto.BlockHeader, height proto.Height) ([]byte, error) + BlockRewards(blockHeader *proto.BlockHeader, height proto.Height) (proto.Rewards, error) EstimatorVersion() (int, error) IsNotFound(err error) bool From 03730686ced647c4703d9afcb19adcf3c7465b61 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Thu, 15 Jun 2023 09:08:57 +0300 Subject: [PATCH 029/139] Fix clear-text logging of sensitive information. (#1128) --- cmd/node/node.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/node/node.go b/cmd/node/node.go index be179500f..aac72570a 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -112,7 +112,7 @@ func debugCommandLineParameters() { zap.S().Debugf("peers: %s", *peerAddresses) zap.S().Debugf("declared-address: %s", *declAddr) zap.S().Debugf("api-address: %s", *apiAddr) - zap.S().Debugf("api-key: %s", *apiKey) + zap.S().Debugf("api-key: %s", crypto.MustKeccak256([]byte(*apiKey)).Hex()) zap.S().Debugf("grpc-address: %s", *grpcAddr) zap.S().Debugf("enable-grpc-api: %t", *enableGrpcApi) zap.S().Debugf("black-list-residence-time: %s", *blackListResidenceTime) @@ -125,7 +125,7 @@ func debugCommandLineParameters() { zap.S().Debugf("obsolescence: %s", *obsolescencePeriod) zap.S().Debugf("disable-miner %t", *disableMiner) zap.S().Debugf("wallet-path: %s", *walletPath) - zap.S().Debugf("hashed wallet-password: %s", crypto.MustFastHash([]byte(*walletPassword))) + zap.S().Debugf("hashed wallet-password: %s", crypto.MustKeccak256([]byte(*walletPassword)).Hex()) zap.S().Debugf("limit-connections: %d", *limitAllConnections) zap.S().Debugf("profiler: %t", *profiler) zap.S().Debugf("disable-bloom: %t", *disableBloomFilter) From d7b2cac585a9210f8c028dbef4a2e8dca47090be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Jun 2023 10:28:56 +0400 Subject: [PATCH 030/139] Bump golang.org/x/sync from 0.2.0 to 0.3.0 (#1129) Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.2.0 to 0.3.0. - [Commits](https://github.com/golang/sync/compare/v0.2.0...v0.3.0) --- updated-dependencies: - dependency-name: golang.org/x/sync dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alexey Kiselev --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c5545ff8f..e0d225f03 100644 --- a/go.mod +++ b/go.mod @@ -46,7 +46,7 @@ require ( go.uber.org/zap v1.24.0 golang.org/x/crypto v0.10.0 golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb - golang.org/x/sync v0.2.0 + golang.org/x/sync v0.3.0 golang.org/x/sys v0.9.0 google.golang.org/grpc v1.55.0 google.golang.org/protobuf v1.30.0 diff --git a/go.sum b/go.sum index 08b02d895..4b9436333 100644 --- a/go.sum +++ b/go.sum @@ -556,8 +556,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= -golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= From 5e7b472c125b00cd0b88cb3bbdcfba388e914e29 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Fri, 23 Jun 2023 19:50:56 +0300 Subject: [PATCH 031/139] Added 'LeaseStateStatus'. Changed types in 'LeaseStateSnapshot'. --- pkg/state/snapshot_types.go | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 67df41639..a6e4b4a89 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -9,10 +9,7 @@ import ( type TransactionSnapshot []AtomicSnapshot -type AtomicSnapshot interface { - atomicSnapshotMarker() - // TODO: add all necessary methods here -} +type AtomicSnapshot interface{ atomicSnapshotMarker() } type WavesBalanceSnapshot struct { Address proto.WavesAddress @@ -21,7 +18,6 @@ type WavesBalanceSnapshot struct { func (*WavesBalanceSnapshot) atomicSnapshotMarker() {} -// What is address || asset_id? type AssetBalanceSnapshot struct { Address proto.WavesAddress AssetID crypto.Digest @@ -61,13 +57,19 @@ type LeaseBalanceSnapshot struct { func (*LeaseBalanceSnapshot) atomicSnapshotMarker() {} +type LeaseStateStatus struct { + Status LeaseStatus // can be only LeaseActive or LeaseCanceled + CancelHeight proto.Height + CancelTransactionID *crypto.Digest +} + type LeaseStateSnapshot struct { LeaseID crypto.Digest - Status LeaseStatus // TODO(nickeskov): add cancelHeight and cancelTxID info for canceled leases + Status LeaseStateStatus Amount uint64 Sender proto.WavesAddress Recipient proto.WavesAddress - OriginTransactionID crypto.Digest + OriginTransactionID *crypto.Digest Height proto.Height } From cc2d19d1e0523b8ab04d8285131fc286b9b20e66 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Fri, 23 Jun 2023 19:55:41 +0300 Subject: [PATCH 032/139] Rename 'LeaseStateStatus.Status' to 'LeaseStateStatus.Value'. --- pkg/state/snapshot_types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index a6e4b4a89..379ce1e14 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -58,7 +58,7 @@ type LeaseBalanceSnapshot struct { func (*LeaseBalanceSnapshot) atomicSnapshotMarker() {} type LeaseStateStatus struct { - Status LeaseStatus // can be only LeaseActive or LeaseCanceled + Value LeaseStatus // can be only LeaseActive or LeaseCanceled CancelHeight proto.Height CancelTransactionID *crypto.Digest } From 59e5b3cb649e0a83a71ab932721485d19819fba8 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Mon, 26 Jun 2023 23:03:52 +0300 Subject: [PATCH 033/139] Add methods to 'SnapshotManager' interface. Changed 'AtomicSnapshot' interface. --- pkg/state/snapshot_types.go | 42 ++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 379ce1e14..7b2e5e8fe 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -9,14 +9,14 @@ import ( type TransactionSnapshot []AtomicSnapshot -type AtomicSnapshot interface{ atomicSnapshotMarker() } +type AtomicSnapshot interface{ Apply(SnapshotManager) error } type WavesBalanceSnapshot struct { Address proto.WavesAddress Balance uint64 } -func (*WavesBalanceSnapshot) atomicSnapshotMarker() {} +func (s WavesBalanceSnapshot) Apply(m SnapshotManager) error { return m.ApplyWavesBalance(s) } type AssetBalanceSnapshot struct { Address proto.WavesAddress @@ -24,14 +24,14 @@ type AssetBalanceSnapshot struct { Balance uint64 } -func (*AssetBalanceSnapshot) atomicSnapshotMarker() {} +func (s AssetBalanceSnapshot) Apply(m SnapshotManager) error { return m.ApplyAssetBalance(s) } type DataEntriesSnapshot struct { // AccountData in pb Address proto.WavesAddress DataEntries []proto.DataEntry } -func (*DataEntriesSnapshot) atomicSnapshotMarker() {} +func (s DataEntriesSnapshot) Apply(m SnapshotManager) error { return m.ApplyDataEntries(s) } type AccountScriptSnapshot struct { SenderPublicKey crypto.PublicKey @@ -39,7 +39,7 @@ type AccountScriptSnapshot struct { VerifierComplexity uint64 } -func (*AccountScriptSnapshot) atomicSnapshotMarker() {} +func (s AccountScriptSnapshot) Apply(m SnapshotManager) error { return m.ApplyAccountScript(s) } type AssetScriptSnapshot struct { AssetID crypto.Digest @@ -47,7 +47,7 @@ type AssetScriptSnapshot struct { Complexity uint64 } -func (*AssetScriptSnapshot) atomicSnapshotMarker() {} +func (s AssetScriptSnapshot) Apply(m SnapshotManager) error { return m.ApplyAssetScript(s) } type LeaseBalanceSnapshot struct { Address proto.WavesAddress @@ -55,7 +55,7 @@ type LeaseBalanceSnapshot struct { LeaseOut uint64 } -func (*LeaseBalanceSnapshot) atomicSnapshotMarker() {} +func (s LeaseBalanceSnapshot) Apply(m SnapshotManager) error { return m.ApplyLeaseBalance(s) } type LeaseStateStatus struct { Value LeaseStatus // can be only LeaseActive or LeaseCanceled @@ -73,21 +73,21 @@ type LeaseStateSnapshot struct { Height proto.Height } -func (*LeaseStateSnapshot) atomicSnapshotMarker() {} +func (s LeaseStateSnapshot) Apply(m SnapshotManager) error { return m.ApplyLeaseState(s) } type SponsorshipSnapshot struct { AssetID crypto.Digest MinSponsoredFee uint64 } -func (*SponsorshipSnapshot) atomicSnapshotMarker() {} +func (s SponsorshipSnapshot) Apply(m SnapshotManager) error { return m.ApplySponsorship(s) } type AliasSnapshot struct { Address proto.WavesAddress Alias proto.Alias } -func (*AliasSnapshot) atomicSnapshotMarker() {} +func (s AliasSnapshot) Apply(m SnapshotManager) error { return m.ApplyAlias(s) } // FilledVolumeFeeSnapshot Filled Volume and Fee type FilledVolumeFeeSnapshot struct { // OrderFill @@ -96,7 +96,7 @@ type FilledVolumeFeeSnapshot struct { // OrderFill FilledFee uint64 } -func (*FilledVolumeFeeSnapshot) atomicSnapshotMarker() {} +func (s FilledVolumeFeeSnapshot) Apply(m SnapshotManager) error { return m.ApplyFilledVolumeAndFee(s) } type StaticAssetInfoSnapshot struct { AssetID crypto.Digest @@ -106,7 +106,7 @@ type StaticAssetInfoSnapshot struct { IsNFT bool } -func (*StaticAssetInfoSnapshot) atomicSnapshotMarker() {} +func (s StaticAssetInfoSnapshot) Apply(m SnapshotManager) error { return m.ApplyStaticAssetInfo(s) } type AssetVolumeSnapshot struct { // AssetVolume in pb AssetID crypto.Digest @@ -114,7 +114,7 @@ type AssetVolumeSnapshot struct { // AssetVolume in pb IsReissuable bool } -func (*AssetVolumeSnapshot) atomicSnapshotMarker() {} +func (s AssetVolumeSnapshot) Apply(m SnapshotManager) error { return m.ApplyAssetVolume(s) } type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb AssetID crypto.Digest @@ -123,8 +123,20 @@ type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb ChangeHeight proto.Height // last_updated in pb } -func (*AssetDescriptionSnapshot) atomicSnapshotMarker() {} +func (s AssetDescriptionSnapshot) Apply(m SnapshotManager) error { return m.ApplyAssetDescription(s) } type SnapshotManager interface { - // TODO: add all necessary methods here + ApplyWavesBalance(snapshot WavesBalanceSnapshot) error + ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) error + ApplyAssetBalance(snapshot AssetBalanceSnapshot) error + ApplyAlias(snapshot AliasSnapshot) error + ApplyStaticAssetInfo(snapshot StaticAssetInfoSnapshot) error + ApplyAssetDescription(snapshot AssetDescriptionSnapshot) error + ApplyAssetVolume(snapshot AssetVolumeSnapshot) error + ApplyAssetScript(snapshot AssetScriptSnapshot) error + ApplySponsorship(snapshot SponsorshipSnapshot) error + ApplyAccountScript(snapshot AccountScriptSnapshot) error + ApplyFilledVolumeAndFee(snapshot FilledVolumeFeeSnapshot) error + ApplyDataEntries(snapshot DataEntriesSnapshot) error + ApplyLeaseState(snapshot LeaseStateSnapshot) error } From 48ea9a6df48d945e418585012a81ea458b049944 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Thu, 29 Jun 2023 04:44:52 +0300 Subject: [PATCH 034/139] Snapshot applier (#1145) * Create marshal/unmarshal methods for 'leasing' structure in 'pkg/state'. * WIP: rollbackable map. * Return 'balanceProfile' and 'wavesBalanceRecord' by value. * Started 'snapshotApplier.' * Add apply methods for assets snapshot applying. * Add 'snapshotApplier.applySponsorship' method. * Add 'snapshotApplier.applyAccountScript' method. * Refactor 'ordersVolumes'. * Add 'snapshotApplier.applyFilledVolumeAndFee' method. * Add 'snapshotApplier.applyDataEntry' method. * Add 'snapshotApplier.applyLeaseState' method. * Revert "WIP: rollbackable map." This reverts commit cb3496915e101cd683f8174c5e801cbe924d6bca. * Created and used 'SnapshotApplierInfo' interface in 'state' package. * Create 'SnapshotApplier' interface in 'state' package. * Refactor 'SnapshotApplier' interface. * Remove 'SnapshotApplierInfo' interface. * Extracted 'snapshotApplierStorages'. * Rename 'ApplyDataEntry' to 'ApplyDataEntries'. --- pkg/state/balances.go | 48 ++--- pkg/state/balances_test.go | 13 +- pkg/state/diff_applier.go | 21 +- pkg/state/keys.go | 6 +- pkg/state/leases.go | 20 +- pkg/state/orders_volume.go | 53 ++--- pkg/state/orders_volume_test.go | 48 ++--- pkg/state/scripts_complexity.go | 2 +- pkg/state/snapshot_applier.go | 248 ++++++++++++++++++++++++ pkg/state/state.go | 8 +- pkg/state/transaction_checker.go | 34 ++-- pkg/state/transaction_differ.go | 26 +-- pkg/state/transaction_performer.go | 10 +- pkg/state/transaction_performer_test.go | 24 +-- 14 files changed, 388 insertions(+), 173 deletions(-) create mode 100644 pkg/state/snapshot_applier.go diff --git a/pkg/state/balances.go b/pkg/state/balances.go index 65bbded3a..9053f7c51 100644 --- a/pkg/state/balances.go +++ b/pkg/state/balances.go @@ -267,7 +267,7 @@ func (s *balances) cancelAllLeases(blockID proto.BlockID) error { zap.S().Infof("Resetting lease balance for %s", addr.String()) r.leaseOut = 0 r.leaseIn = 0 - val := &wavesValue{leaseChange: true, profile: r.balanceProfile} + val := wavesValue{leaseChange: true, profile: r.balanceProfile} if err := s.setWavesBalance(k.address, val, blockID); err != nil { return err } @@ -309,7 +309,7 @@ func (s *balances) cancelLeaseOverflows(blockID proto.BlockID) (map[proto.WavesA ) overflowedAddresses[wavesAddr] = empty r.leaseOut = 0 - val := &wavesValue{leaseChange: true, profile: r.balanceProfile} + val := wavesValue{leaseChange: true, profile: r.balanceProfile} if err := s.setWavesBalance(k.address, val, blockID); err != nil { return nil, err } @@ -355,7 +355,7 @@ func (s *balances) cancelInvalidLeaseIns(correctLeaseIns map[proto.WavesAddress] wavesAddress.String(), r.leaseIn, correctLeaseIn, ) r.leaseIn = correctLeaseIn - val := &wavesValue{leaseChange: true, profile: r.balanceProfile} + val := wavesValue{leaseChange: true, profile: r.balanceProfile} if err := s.setWavesBalance(k.address, val, blockID); err != nil { return err } @@ -374,11 +374,11 @@ func (s *balances) cancelLeases(changes map[proto.WavesAddress]balanceDiff, bloc return err } profile := r.balanceProfile - newProfile, err := bd.applyTo(&profile) + newProfile, err := bd.applyTo(profile) if err != nil { return err } - val := &wavesValue{leaseChange: true, profile: *newProfile} + val := wavesValue{leaseChange: true, profile: newProfile} if err := s.setWavesBalance(a.ID(), val, blockID); err != nil { return err } @@ -544,59 +544,59 @@ func (s *balances) newestAssetBalance(addr proto.AddressID, asset proto.AssetID) return s.assetBalanceFromRecordBytes(recordBytes) } -func (s *balances) newestWavesRecord(key []byte) (*wavesBalanceRecord, error) { +func (s *balances) newestWavesRecord(key []byte) (wavesBalanceRecord, error) { recordBytes, err := s.hs.newestTopEntryData(key) if err == keyvalue.ErrNotFound || err == errEmptyHist { // Unknown address, expected behavior is to return empty profile and no errors in this case. - return &wavesBalanceRecord{}, nil + return wavesBalanceRecord{}, nil } else if err != nil { - return nil, err + return wavesBalanceRecord{}, err } var record wavesBalanceRecord if err := record.unmarshalBinary(recordBytes); err != nil { - return nil, err + return wavesBalanceRecord{}, err } - return &record, nil + return record, nil } -func (s *balances) newestWavesBalance(addr proto.AddressID) (*balanceProfile, error) { +func (s *balances) newestWavesBalance(addr proto.AddressID) (balanceProfile, error) { key := wavesBalanceKey{address: addr} r, err := s.newestWavesRecord(key.bytes()) if err != nil { - return nil, err + return balanceProfile{}, err } - return &r.balanceProfile, nil + return r.balanceProfile, nil } -func (s *balances) wavesRecord(key []byte) (*wavesBalanceRecord, error) { +func (s *balances) wavesRecord(key []byte) (wavesBalanceRecord, error) { recordBytes, err := s.hs.topEntryData(key) if err == keyvalue.ErrNotFound || err == errEmptyHist { // Unknown address, expected behavior is to return empty profile and no errors in this case. - return &wavesBalanceRecord{}, nil + return wavesBalanceRecord{}, nil } else if err != nil { - return nil, err + return wavesBalanceRecord{}, err } var record wavesBalanceRecord if err := record.unmarshalBinary(recordBytes); err != nil { - return nil, err + return wavesBalanceRecord{}, errors.Wrap(err, "failed to unmarshal data to %T") } - return &record, nil + return record, nil } -func (s *balances) wavesBalance(addr proto.AddressID) (*balanceProfile, error) { +func (s *balances) wavesBalance(addr proto.AddressID) (balanceProfile, error) { key := wavesBalanceKey{address: addr} r, err := s.wavesRecord(key.bytes()) if err != nil { - return nil, err + return balanceProfile{}, err } - return &r.balanceProfile, nil + return r.balanceProfile, nil } func (s *balances) setAssetBalance(addr proto.AddressID, assetID proto.AssetID, balance uint64, blockID proto.BlockID) error { key := assetBalanceKey{address: addr, asset: assetID} keyBytes := key.bytes() keyStr := string(keyBytes) - record := &assetBalanceRecord{balance} + record := assetBalanceRecord{balance} recordBytes, err := record.marshalBinary() if err != nil { return err @@ -624,11 +624,11 @@ func (s *balances) setAssetBalance(addr proto.AddressID, assetID proto.AssetID, return s.hs.addNewEntry(assetBalance, keyBytes, recordBytes, blockID) } -func (s *balances) setWavesBalance(addr proto.AddressID, balance *wavesValue, blockID proto.BlockID) error { +func (s *balances) setWavesBalance(addr proto.AddressID, balance wavesValue, blockID proto.BlockID) error { key := wavesBalanceKey{address: addr} keyBytes := key.bytes() keyStr := string(keyBytes) - record := &wavesBalanceRecord{balance.profile} + record := wavesBalanceRecord{balance.profile} recordBytes, err := record.marshalBinary() if err != nil { return err diff --git a/pkg/state/balances_test.go b/pkg/state/balances_test.go index 444abd9fd..182d94636 100644 --- a/pkg/state/balances_test.go +++ b/pkg/state/balances_test.go @@ -38,6 +38,17 @@ func genAsset(fillWith byte) crypto.Digest { return asset } +func newWavesValueFromProfile(p balanceProfile) wavesValue { + val := wavesValue{profile: p} + if p.leaseIn != 0 || p.leaseOut != 0 { + val.leaseChange = true + } + if p.balance != 0 { + val.balanceChange = true + } + return val +} + func TestCancelAllLeases(t *testing.T) { to := createBalances(t) @@ -219,7 +230,7 @@ func TestBalances(t *testing.T) { if err != nil { t.Fatalf("Failed to retrieve waves balance: %v\n", err) } - if *profile != tc.profile { + if profile != tc.profile { t.Errorf("Waves balance profiles are not equal: %v and %v\n", profile, tc.profile) } } diff --git a/pkg/state/diff_applier.go b/pkg/state/diff_applier.go index 1c03501cf..eb9c14e72 100644 --- a/pkg/state/diff_applier.go +++ b/pkg/state/diff_applier.go @@ -20,19 +20,8 @@ func newDiffApplier(balances *balances, scheme proto.Scheme) (*diffApplier, erro return &diffApplier{balances, scheme}, nil } -func newWavesValueFromProfile(p balanceProfile) *wavesValue { - val := &wavesValue{profile: p} - if p.leaseIn != 0 || p.leaseOut != 0 { - val.leaseChange = true - } - if p.balance != 0 { - val.balanceChange = true - } - return val -} - -func newWavesValue(prevProf, newProf balanceProfile) *wavesValue { - val := &wavesValue{profile: newProf} +func newWavesValue(prevProf, newProf balanceProfile) wavesValue { + val := wavesValue{profile: newProf} if prevProf.balance != newProf.balance { val.balanceChange = true } @@ -51,7 +40,7 @@ func (a *diffApplier) applyWavesBalanceChanges(change *balanceChanges, validateO if err != nil { return errors.Errorf("failed to retrieve waves balance: %v\n", err) } - prevProfile := *profile + prevProfile := profile for _, diff := range change.balanceDiffs { // Check for negative balance. newProfile, err := diff.applyTo(profile) @@ -69,11 +58,11 @@ func (a *diffApplier) applyWavesBalanceChanges(change *balanceChanges, validateO if validateOnly { continue } - val := newWavesValue(prevProfile, *newProfile) + val := newWavesValue(prevProfile, newProfile) if err := a.balances.setWavesBalance(k.address, val, diff.blockID); err != nil { return errors.Errorf("failed to set account balance: %v\n", err) } - prevProfile = *newProfile + prevProfile = newProfile } return nil } diff --git a/pkg/state/keys.go b/pkg/state/keys.go index cc2ead4b1..cd26482be 100644 --- a/pkg/state/keys.go +++ b/pkg/state/keys.go @@ -473,13 +473,13 @@ func (k *votesFeaturesKey) unmarshal(data []byte) error { } type ordersVolumeKey struct { - orderId []byte + orderID []byte } func (k *ordersVolumeKey) bytes() []byte { - buf := make([]byte, 1+len(k.orderId)) + buf := make([]byte, 1+len(k.orderID)) buf[0] = ordersVolumeKeyPrefix - copy(buf[1:], k.orderId) + copy(buf[1:], k.orderID) return buf } diff --git a/pkg/state/leases.go b/pkg/state/leases.go index 652fb7771..e4a4636f0 100644 --- a/pkg/state/leases.go +++ b/pkg/state/leases.go @@ -51,10 +51,18 @@ type leasing struct { CancelTransactionID *crypto.Digest `cbor:"8,keyasint,omitempty"` } -func (l leasing) isActive() bool { +func (l *leasing) isActive() bool { return l.Status == LeaseActive } +func (l *leasing) marshalBinary() ([]byte, error) { + return cbor.Marshal(l) +} + +func (l *leasing) unmarshalBinary(data []byte) error { + return cbor.Unmarshal(data, l) +} + type leases struct { hs *historyStorage @@ -91,7 +99,7 @@ func (l *leases) cancelLeases(bySenders map[proto.WavesAddress]struct{}, blockID key := keyvalue.SafeKey(leaseIter) leaseBytes := keyvalue.SafeValue(leaseIter) record := new(leasing) - if err := cbor.Unmarshal(leaseBytes, record); err != nil { + if err := record.unmarshalBinary(leaseBytes); err != nil { return errors.Wrap(err, "failed to unmarshal lease") } toCancel := true @@ -168,7 +176,7 @@ func (l *leases) validLeaseIns() (map[proto.WavesAddress]int64, error) { for leaseIter.Next() { leaseBytes := keyvalue.SafeValue(leaseIter) record := new(leasing) - if err := cbor.Unmarshal(leaseBytes, record); err != nil { + if err := record.unmarshalBinary(leaseBytes); err != nil { return nil, errors.Wrap(err, "failed to unmarshal lease") } if record.isActive() { @@ -191,7 +199,7 @@ func (l *leases) newestLeasingInfo(id crypto.Digest) (*leasing, error) { return nil, err } record := new(leasing) - if err := cbor.Unmarshal(recordBytes, record); err != nil { + if err := record.unmarshalBinary(recordBytes); err != nil { return nil, errors.Wrap(err, "failed to unmarshal record") } if record.OriginTransactionID == nil { @@ -208,7 +216,7 @@ func (l *leases) leasingInfo(id crypto.Digest) (*leasing, error) { return nil, err } record := new(leasing) - if err := cbor.Unmarshal(recordBytes, record); err != nil { + if err := record.unmarshalBinary(recordBytes); err != nil { return nil, errors.Wrap(err, "failed to unmarshal record") } if record.OriginTransactionID == nil { @@ -229,7 +237,7 @@ func (l *leases) addLeasing(id crypto.Digest, leasing *leasing, blockID proto.Bl key := leaseKey{leaseID: id} keyBytes := key.bytes() keyStr := string(keyBytes) - recordBytes, err := cbor.Marshal(leasing) + recordBytes, err := leasing.marshalBinary() if err != nil { return errors.Wrap(err, "failed to marshal record") } diff --git a/pkg/state/orders_volume.go b/pkg/state/orders_volume.go index 37d25f351..64cc9a421 100644 --- a/pkg/state/orders_volume.go +++ b/pkg/state/orders_volume.go @@ -3,6 +3,7 @@ package state import ( "encoding/binary" + "github.com/mr-tron/base58" "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/proto" ) @@ -40,8 +41,8 @@ func newOrdersVolumes(hs *historyStorage) *ordersVolumes { return &ordersVolumes{hs: hs} } -func (ov *ordersVolumes) newestVolumeById(orderId []byte) (*orderVolumeRecord, error) { - key := ordersVolumeKey{orderId} +func (ov *ordersVolumes) newestVolumeById(orderID []byte) (*orderVolumeRecord, error) { + key := ordersVolumeKey{orderID} recordBytes, err := ov.hs.newestTopEntryData(key.bytes()) if err != nil { return nil, err @@ -53,49 +54,35 @@ func (ov *ordersVolumes) newestVolumeById(orderId []byte) (*orderVolumeRecord, e return &record, nil } -func (ov *ordersVolumes) addNewRecord(orderId []byte, record *orderVolumeRecord, blockID proto.BlockID) error { +func (ov *ordersVolumes) addNewRecord(orderID []byte, record *orderVolumeRecord, blockID proto.BlockID) error { recordBytes, err := record.marshalBinary() if err != nil { return err } - key := ordersVolumeKey{orderId} + key := ordersVolumeKey{orderID} return ov.hs.addNewEntry(ordersVolume, key.bytes(), recordBytes, blockID) } -func (ov *ordersVolumes) increaseFilledFee(orderId []byte, feeChange uint64, blockID proto.BlockID) error { - prevVolume, err := ov.newestVolumeById(orderId) +func (ov *ordersVolumes) increaseFilled(orderID []byte, amountChange, feeChange uint64, blockID proto.BlockID) error { + prevVolume, err := ov.newestVolumeById(orderID) if err != nil { - // New record. - return ov.addNewRecord(orderId, &orderVolumeRecord{feeFilled: feeChange}, blockID) - } - prevVolume.feeFilled += feeChange - return ov.addNewRecord(orderId, prevVolume, blockID) -} - -func (ov *ordersVolumes) increaseFilledAmount(orderId []byte, amountChange uint64, blockID proto.BlockID) error { - prevVolume, err := ov.newestVolumeById(orderId) - if err != nil { - // New record. - return ov.addNewRecord(orderId, &orderVolumeRecord{amountFilled: amountChange}, blockID) + if isNotFoundInHistoryOrDBErr(err) { // New record. + return ov.addNewRecord(orderID, &orderVolumeRecord{amountFilled: amountChange, feeFilled: feeChange}, blockID) + } + return errors.Wrapf(err, "failed to increase filled for order %q", base58.Encode(orderID)) } prevVolume.amountFilled += amountChange - return ov.addNewRecord(orderId, prevVolume, blockID) -} - -func (ov *ordersVolumes) newestFilledFee(orderId []byte) (uint64, error) { - volume, err := ov.newestVolumeById(orderId) - if err != nil { - // No fee volume filled yet. - return 0, nil - } - return volume.feeFilled, nil + prevVolume.feeFilled += feeChange + return ov.addNewRecord(orderID, prevVolume, blockID) } -func (ov *ordersVolumes) newestFilledAmount(orderId []byte) (uint64, error) { - volume, err := ov.newestVolumeById(orderId) +func (ov *ordersVolumes) newestFilled(orderID []byte) (amount, fee uint64, err error) { + volume, err := ov.newestVolumeById(orderID) if err != nil { - // No amount volume filled yet. - return 0, nil + if isNotFoundInHistoryOrDBErr(err) { // No fee volume filled yet. + return 0, 0, nil + } + return 0, 0, errors.Wrapf(err, "failed to get filled for order %q", base58.Encode(orderID)) } - return volume.amountFilled, nil + return volume.amountFilled, volume.feeFilled, nil } diff --git a/pkg/state/orders_volume_test.go b/pkg/state/orders_volume_test.go index 70e4617b4..db5d46cb3 100644 --- a/pkg/state/orders_volume_test.go +++ b/pkg/state/orders_volume_test.go @@ -19,52 +19,36 @@ func createOrdersVolumeStorageObjects(t *testing.T) *ordersVolumesStorageObjects return &ordersVolumesStorageObjects{stor, ordersVolumes} } -func TestIncreaseFilledFee(t *testing.T) { +func TestIncreaseFilled(t *testing.T) { to := createOrdersVolumeStorageObjects(t) to.stor.addBlock(t, blockID0) - orderId := bytes.Repeat([]byte{0xff}, crypto.DigestSize) - firstFee := uint64(1) - secondFee := uint64(100500) - err := to.ordersVolumes.increaseFilledFee(orderId, firstFee, blockID0) - assert.NoError(t, err) - filledFee, err := to.ordersVolumes.newestFilledFee(orderId) - assert.NoError(t, err) - assert.Equal(t, firstFee, filledFee) + orderID := bytes.Repeat([]byte{0xff}, crypto.DigestSize) - err = to.ordersVolumes.increaseFilledFee(orderId, secondFee, blockID0) - assert.NoError(t, err) - filledFee, err = to.ordersVolumes.newestFilledFee(orderId) - assert.NoError(t, err) - assert.Equal(t, firstFee+secondFee, filledFee) + const ( + firstFee = uint64(1) + secondFee = uint64(100500) + firstAmount = uint64(111) + secondAmount = uint64(500100) + ) - to.stor.flush(t) - filledFee, err = to.ordersVolumes.newestFilledFee(orderId) + err := to.ordersVolumes.increaseFilled(orderID, firstAmount, firstFee, blockID0) assert.NoError(t, err) - assert.Equal(t, firstFee+secondFee, filledFee) -} - -func TestIncreaseFilledAmount(t *testing.T) { - to := createOrdersVolumeStorageObjects(t) - - to.stor.addBlock(t, blockID0) - orderId := bytes.Repeat([]byte{0xff}, crypto.DigestSize) - firstAmount := uint64(1) - secondAmount := uint64(100500) - err := to.ordersVolumes.increaseFilledAmount(orderId, firstAmount, blockID0) - assert.NoError(t, err) - filledAmount, err := to.ordersVolumes.newestFilledAmount(orderId) + filledAmount, filledFee, err := to.ordersVolumes.newestFilled(orderID) assert.NoError(t, err) + assert.Equal(t, firstFee, filledFee) assert.Equal(t, firstAmount, filledAmount) - err = to.ordersVolumes.increaseFilledAmount(orderId, secondAmount, blockID0) + err = to.ordersVolumes.increaseFilled(orderID, secondAmount, secondFee, blockID0) assert.NoError(t, err) - filledAmount, err = to.ordersVolumes.newestFilledAmount(orderId) + filledAmount, filledFee, err = to.ordersVolumes.newestFilled(orderID) assert.NoError(t, err) + assert.Equal(t, firstFee+secondFee, filledFee) assert.Equal(t, firstAmount+secondAmount, filledAmount) to.stor.flush(t) - filledAmount, err = to.ordersVolumes.newestFilledAmount(orderId) + filledAmount, filledFee, err = to.ordersVolumes.newestFilled(orderID) assert.NoError(t, err) + assert.Equal(t, firstFee+secondFee, filledFee) assert.Equal(t, firstAmount+secondAmount, filledAmount) } diff --git a/pkg/state/scripts_complexity.go b/pkg/state/scripts_complexity.go index f3d356fe8..6ddad61bb 100644 --- a/pkg/state/scripts_complexity.go +++ b/pkg/state/scripts_complexity.go @@ -95,7 +95,7 @@ func (sc *scriptsComplexity) scriptComplexityByAddress(addr proto.Address, ev in return record, nil } -func (sc *scriptsComplexity) saveComplexitiesForAddr(addr proto.Address, estimations map[int]ride.TreeEstimation, blockID proto.BlockID) error { +func (sc *scriptsComplexity) saveComplexitiesForAddr(addr proto.Address, estimations treeEstimations, blockID proto.BlockID) error { min := math.MaxUint8 addrID := addr.ID() for v, e := range estimations { diff --git a/pkg/state/snapshot_applier.go b/pkg/state/snapshot_applier.go new file mode 100644 index 000000000..6ad95544c --- /dev/null +++ b/pkg/state/snapshot_applier.go @@ -0,0 +1,248 @@ +package state + +import ( + "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/proto" + "github.com/wavesplatform/gowaves/pkg/ride" + "github.com/wavesplatform/gowaves/pkg/ride/serialization" +) + +type SnapshotApplier interface { + ApplyWavesBalance(snapshot WavesBalanceSnapshot) error + ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) error + ApplyAssetBalance(snapshot AssetBalanceSnapshot) error + ApplyAlias(snapshot AliasSnapshot) error + ApplyStaticAssetInfo(snapshot StaticAssetInfoSnapshot) error + ApplyAssetDescription(snapshot AssetDescriptionSnapshot) error + ApplyAssetVolume(snapshot AssetVolumeSnapshot) error + ApplyAssetScript(snapshot AssetScriptSnapshot) error + ApplySponsorship(snapshot SponsorshipSnapshot) error + ApplyAccountScript(snapshot AccountScriptSnapshot) error + ApplyFilledVolumeAndFee(snapshot FilledVolumeFeeSnapshot) error + ApplyDataEntries(snapshot DataEntriesSnapshot) error + ApplyLeaseState(snapshot LeaseStateSnapshot) error +} + +type blockSnapshotsApplier struct { + info blockSnapshotsApplierInfo + stor snapshotApplierStorages +} + +var _ = newBlockSnapshotsApplier // TODO: only for linter, will be removed later + +func newBlockSnapshotsApplier(info blockSnapshotsApplierInfo, stor snapshotApplierStorages) blockSnapshotsApplier { + return blockSnapshotsApplier{info: info, stor: stor} +} + +type snapshotApplierStorages struct { + balances *balances + aliases *aliases + assets *assets + scriptsStorage scriptStorageState + scriptsComplexity *scriptsComplexity + sponsoredAssets *sponsoredAssets + ordersVolumes *ordersVolumes + accountsDataStor *accountsDataStorage + leases *leases +} + +var _ = newSnapshotApplierStorages // TODO: only for linter, will be removed later + +func newSnapshotApplierStorages(stor *blockchainEntitiesStorage) snapshotApplierStorages { + return snapshotApplierStorages{ + balances: stor.balances, + aliases: stor.aliases, + assets: stor.assets, + scriptsStorage: stor.scriptsStorage, + scriptsComplexity: stor.scriptsComplexity, + sponsoredAssets: stor.sponsoredAssets, + ordersVolumes: stor.ordersVolumes, + accountsDataStor: stor.accountsDataStor, + leases: stor.leases, + } +} + +var _ = SnapshotApplier((*blockSnapshotsApplier)(nil)) + +type blockSnapshotsApplierInfo struct { + ci *checkerInfo + scheme proto.Scheme + stateActionsCounter *proto.StateActionsCounter +} + +var _ = newBlockSnapshotsApplierInfo + +func newBlockSnapshotsApplierInfo(ci *checkerInfo, scheme proto.Scheme, cnt *proto.StateActionsCounter) blockSnapshotsApplierInfo { + return blockSnapshotsApplierInfo{ + ci: ci, + scheme: scheme, + stateActionsCounter: cnt, + } +} + +func (s blockSnapshotsApplierInfo) BlockID() proto.BlockID { + return s.ci.blockID +} + +func (s blockSnapshotsApplierInfo) Height() proto.Height { + return s.ci.height +} + +func (s blockSnapshotsApplierInfo) EstimatorVersion() int { + return s.ci.estimatorVersion() +} + +func (s blockSnapshotsApplierInfo) Scheme() proto.Scheme { + return s.scheme +} + +func (s blockSnapshotsApplierInfo) StateActionsCounter() *proto.StateActionsCounter { + return s.stateActionsCounter +} + +func (a *blockSnapshotsApplier) ApplyWavesBalance(snapshot WavesBalanceSnapshot) error { + addrID := snapshot.Address.ID() + profile, err := a.stor.balances.wavesBalance(addrID) + if err != nil { + return errors.Wrapf(err, "failed to get waves balance profile for address %q", snapshot.Address.String()) + } + newProfile := profile + newProfile.balance = snapshot.Balance + value := newWavesValue(profile, newProfile) + if err := a.stor.balances.setWavesBalance(addrID, value, a.info.BlockID()); err != nil { + return errors.Wrapf(err, "failed to get set balance profile for address %q", snapshot.Address.String()) + } + return nil +} + +func (a *blockSnapshotsApplier) ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) error { + addrID := snapshot.Address.ID() + profile, err := a.stor.balances.wavesBalance(addrID) + if err != nil { + return errors.Wrapf(err, "failed to get waves balance profile for address %q", snapshot.Address.String()) + } + newProfile := profile + newProfile.leaseIn = int64(snapshot.LeaseIn) + newProfile.leaseOut = int64(snapshot.LeaseOut) + value := newWavesValue(profile, newProfile) + if err := a.stor.balances.setWavesBalance(addrID, value, a.info.BlockID()); err != nil { + return errors.Wrapf(err, "failed to get set balance profile for address %q", snapshot.Address.String()) + } + return nil +} + +func (a *blockSnapshotsApplier) ApplyAssetBalance(snapshot AssetBalanceSnapshot) error { + addrID := snapshot.Address.ID() + assetID := proto.AssetIDFromDigest(snapshot.AssetID) + return a.stor.balances.setAssetBalance(addrID, assetID, snapshot.Balance, a.info.BlockID()) +} + +func (a *blockSnapshotsApplier) ApplyAlias(snapshot AliasSnapshot) error { + return a.stor.aliases.createAlias(snapshot.Alias.Alias, snapshot.Address, a.info.BlockID()) +} + +func (a *blockSnapshotsApplier) ApplyStaticAssetInfo(snapshot StaticAssetInfoSnapshot) error { + assetID := proto.AssetIDFromDigest(snapshot.AssetID) + assetFullInfo := &assetInfo{ + assetConstInfo: assetConstInfo{ + tail: proto.DigestTail(snapshot.AssetID), + issuer: snapshot.IssuerPublicKey, + decimals: snapshot.Decimals, + issueHeight: a.info.Height(), + issueSequenceInBlock: a.info.StateActionsCounter().NextIssueActionNumber(), + }, + assetChangeableInfo: assetChangeableInfo{}, + } + return a.stor.assets.issueAsset(assetID, assetFullInfo, a.info.BlockID()) +} + +func (a *blockSnapshotsApplier) ApplyAssetDescription(snapshot AssetDescriptionSnapshot) error { + change := &assetInfoChange{ + newName: snapshot.AssetName, + newDescription: snapshot.AssetDescription, + newHeight: snapshot.ChangeHeight, + } + return a.stor.assets.updateAssetInfo(snapshot.AssetID, change, a.info.BlockID()) +} + +func (a *blockSnapshotsApplier) ApplyAssetVolume(snapshot AssetVolumeSnapshot) error { + assetID := proto.AssetIDFromDigest(snapshot.AssetID) + assetFullInfo, err := a.stor.assets.newestAssetInfo(assetID) + if err != nil { + return errors.Wrapf(err, "failed to get newest asset info for asset %q", snapshot.AssetID.String()) + } + assetFullInfo.assetChangeableInfo.reissuable = snapshot.IsReissuable + assetFullInfo.assetChangeableInfo.quantity = snapshot.TotalQuantity + return a.stor.assets.storeAssetInfo(assetID, assetFullInfo, a.info.BlockID()) +} + +func (a *blockSnapshotsApplier) ApplyAssetScript(snapshot AssetScriptSnapshot) error { + estimation := ride.TreeEstimation{ // TODO: use uint in TreeEstimation + Estimation: int(snapshot.Complexity), + Verifier: int(snapshot.Complexity), + Functions: nil, + } + if err := a.stor.scriptsComplexity.saveComplexitiesForAsset(snapshot.AssetID, estimation, a.info.BlockID()); err != nil { + return errors.Wrapf(err, "failed to store asset script estimation for asset %q", snapshot.AssetID.String()) + } + constInfo, err := a.stor.assets.newestConstInfo(proto.AssetIDFromDigest(snapshot.AssetID)) // only issuer can set new asset script + if err != nil { + return errors.Wrapf(err, "failed to get const asset info for asset %q", snapshot.AssetID.String()) + } + return a.stor.scriptsStorage.setAssetScript(snapshot.AssetID, snapshot.Script, constInfo.issuer, a.info.BlockID()) +} + +func (a *blockSnapshotsApplier) ApplySponsorship(snapshot SponsorshipSnapshot) error { + return a.stor.sponsoredAssets.sponsorAsset(snapshot.AssetID, snapshot.MinSponsoredFee, a.info.BlockID()) +} + +func (a *blockSnapshotsApplier) ApplyAccountScript(snapshot AccountScriptSnapshot) error { + addr, err := proto.NewAddressFromPublicKey(a.info.Scheme(), snapshot.SenderPublicKey) + if err != nil { + return errors.Wrapf(err, "failed to create address from scheme %d and PK %q", + a.info.Scheme(), snapshot.SenderPublicKey.String()) + } + var estimations treeEstimations + if !snapshot.Script.IsEmpty() { + tree, err := serialization.Parse(snapshot.Script) + if err != nil { + return errors.Wrapf(err, "failed to parse script from account script snapshot for addr %q", addr.String()) + } + estimations, err = makeRideEstimations(tree, a.info.EstimatorVersion(), true) + if err != nil { + return errors.Wrapf(err, "failed to make account script estimations for addr %q", addr.String()) + } + } + if err := a.stor.scriptsComplexity.saveComplexitiesForAddr(addr, estimations, a.info.BlockID()); err != nil { + return errors.Wrapf(err, "failed to store account script estimation for addr %q", addr.String()) + } + return a.stor.scriptsStorage.setAccountScript(addr, snapshot.Script, snapshot.SenderPublicKey, a.info.BlockID()) +} + +func (a *blockSnapshotsApplier) ApplyFilledVolumeAndFee(snapshot FilledVolumeFeeSnapshot) error { + return a.stor.ordersVolumes.increaseFilled(snapshot.OrderID.Bytes(), snapshot.FilledVolume, snapshot.FilledFee, a.info.BlockID()) +} + +func (a *blockSnapshotsApplier) ApplyDataEntries(snapshot DataEntriesSnapshot) error { + blockID := a.info.BlockID() + for _, entry := range snapshot.DataEntries { + if err := a.stor.accountsDataStor.appendEntry(snapshot.Address, entry, blockID); err != nil { + return errors.Wrapf(err, "failed to add entry (%T) for address %q", entry, snapshot.Address) + } + } + return nil +} + +func (a *blockSnapshotsApplier) ApplyLeaseState(snapshot LeaseStateSnapshot) error { + l := &leasing{ + Sender: snapshot.Sender, + Recipient: snapshot.Recipient, + Amount: snapshot.Amount, + Height: snapshot.Height, + Status: snapshot.Status.Value, + OriginTransactionID: snapshot.OriginTransactionID, + CancelHeight: snapshot.Status.CancelHeight, + CancelTransactionID: snapshot.Status.CancelTransactionID, + } + return a.stor.leases.addLeasing(snapshot.LeaseID, l, a.info.BlockID()) +} diff --git a/pkg/state/state.go b/pkg/state/state.go index 3b8e20cff..a3099d558 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -811,11 +811,11 @@ func (s *stateManager) newestAssetBalance(addr proto.AddressID, asset proto.Asse return balance, nil } -func (s *stateManager) newestWavesBalanceProfile(addr proto.AddressID) (*balanceProfile, error) { +func (s *stateManager) newestWavesBalanceProfile(addr proto.AddressID) (balanceProfile, error) { // Retrieve the latest balance from historyStorage. profile, err := s.stor.balances.newestWavesBalance(addr) if err != nil { - return nil, err + return balanceProfile{}, err } // Retrieve the latest balance diff as for the moment of this function call. key := wavesBalanceKey{address: addr} @@ -825,11 +825,11 @@ func (s *stateManager) newestWavesBalanceProfile(addr proto.AddressID) (*balance return profile, nil } else if err != nil { // Something weird happened. - return nil, err + return balanceProfile{}, err } newProfile, err := diff.applyTo(profile) if err != nil { - return nil, errors.Errorf("given account has negative balance at this point: %v", err) + return balanceProfile{}, errors.Errorf("given account has negative balance at this point: %v", err) } return newProfile, nil } diff --git a/pkg/state/transaction_checker.go b/pkg/state/transaction_checker.go index 72288377f..309254dc2 100644 --- a/pkg/state/transaction_checker.go +++ b/pkg/state/transaction_checker.go @@ -182,7 +182,9 @@ func (tc *transactionChecker) checkDAppCallables(tree *ast.Tree, rideV6Activated return nil } -func (tc *transactionChecker) checkScript(script proto.Script, estimatorVersion int, reducedVerifierComplexity, expandEstimations bool) (map[int]ride.TreeEstimation, error) { +type treeEstimations map[int]ride.TreeEstimation + +func (tc *transactionChecker) checkScript(script proto.Script, estimatorVersion int, reducedVerifierComplexity, expandEstimations bool) (treeEstimations, error) { tree, err := serialization.Parse(script) if err != nil { return nil, errs.Extend(err, "failed to build AST") @@ -207,11 +209,22 @@ func (tc *transactionChecker) checkScript(script proto.Script, estimatorVersion } } - estimations := make(map[int]ride.TreeEstimation) + estimations, err := makeRideEstimations(tree, estimatorVersion, expandEstimations) + if err != nil { + return nil, errs.Extend(err, "failed to make ride estimations") + } + if err := tc.checkScriptComplexity(tree.LibVersion, estimations[estimatorVersion], tree.IsDApp(), reducedVerifierComplexity); err != nil { + return nil, errors.Wrap(err, "failed to check script complexity") + } + return estimations, nil +} + +func makeRideEstimations(tree *ast.Tree, estimatorVersion int, expandEstimations bool) (treeEstimations, error) { maxVersion := maxEstimatorVersion if !expandEstimations { maxVersion = estimatorVersion } + estimations := make(map[int]ride.TreeEstimation, maxVersion-estimatorVersion+1) for ev := estimatorVersion; ev <= maxVersion; ev++ { est, err := ride.EstimateTree(tree, ev) if err != nil { @@ -219,9 +232,6 @@ func (tc *transactionChecker) checkScript(script proto.Script, estimatorVersion } estimations[ev] = est } - if err := tc.checkScriptComplexity(tree.LibVersion, estimations[estimatorVersion], tree.IsDApp(), reducedVerifierComplexity); err != nil { - return nil, errors.Wrap(err, "failed to check script complexity") - } return estimations, nil } @@ -752,8 +762,8 @@ func (tc *transactionChecker) orderScriptedAccount(order proto.Order) (bool, err return tc.stor.scriptsStorage.newestAccountHasVerifier(senderWavesAddr) } -func (tc *transactionChecker) checkEnoughVolume(order proto.Order, newFee, newAmount uint64, info *checkerInfo) error { - orderId, err := order.GetID() +func (tc *transactionChecker) checkEnoughVolume(order proto.Order, newFee, newAmount uint64) error { + orderID, err := order.GetID() if err != nil { return err } @@ -765,17 +775,13 @@ func (tc *transactionChecker) checkEnoughVolume(order proto.Order, newFee, newAm if newFee > fullFee { return errors.New("current fee exceeds total order fee") } - filledAmount, err := tc.stor.ordersVolumes.newestFilledAmount(orderId) + filledAmount, filledFee, err := tc.stor.ordersVolumes.newestFilled(orderID) if err != nil { return err } if fullAmount-newAmount < filledAmount { return errors.New("order amount volume is overflowed") } - filledFee, err := tc.stor.ordersVolumes.newestFilledFee(orderId) - if err != nil { - return err - } if fullFee-newFee < filledFee { return errors.New("order fee volume is overflowed") } @@ -817,14 +823,14 @@ func (tc *transactionChecker) checkExchange(transaction proto.Transaction, info if err != nil { return nil, errs.Extend(err, "sell order") } - if err := tc.checkEnoughVolume(so, tx.GetSellMatcherFee(), tx.GetAmount(), info); err != nil { + if err := tc.checkEnoughVolume(so, tx.GetSellMatcherFee(), tx.GetAmount()); err != nil { return nil, errs.Extend(err, "exchange transaction; sell order") } bo, err := tx.GetBuyOrder() if err != nil { return nil, errs.Extend(err, "buy order") } - if err := tc.checkEnoughVolume(bo, tx.GetBuyMatcherFee(), tx.GetAmount(), info); err != nil { + if err := tc.checkEnoughVolume(bo, tx.GetBuyMatcherFee(), tx.GetAmount()); err != nil { return nil, errs.Extend(err, "exchange transaction; buy order") } o1 := tx.GetOrder1() diff --git a/pkg/state/transaction_differ.go b/pkg/state/transaction_differ.go index 9fad5bd10..56981cbe2 100644 --- a/pkg/state/transaction_differ.go +++ b/pkg/state/transaction_differ.go @@ -79,14 +79,14 @@ func newBalanceDiff(balance, leaseIn, leaseOut int64, updateMinIntermediateBalan // applyTo() applies diff to the profile given. // It does not change input profile, and returns the updated version. // It also checks that it is legitimate to apply this diff to the profile (negative balances / overflows). -func (diff *balanceDiff) applyTo(profile *balanceProfile) (*balanceProfile, error) { +func (diff *balanceDiff) applyTo(profile balanceProfile) (balanceProfile, error) { // Check min intermediate change. minBalance, err := common.AddInt64(diff.minBalance, int64(profile.balance)) if err != nil { - return nil, errors.Errorf("failed to add balance and min balance diff: %v\n", err) + return balanceProfile{}, errors.Errorf("failed to add balance and min balance diff: %v\n", err) } if minBalance < 0 { - return nil, errors.Errorf( + return balanceProfile{}, errors.Errorf( "negative intermediate balance (Attempt to transfer unavailable funds): balance is %d; diff is: %d\n", profile.balance, diff.minBalance, @@ -95,29 +95,29 @@ func (diff *balanceDiff) applyTo(profile *balanceProfile) (*balanceProfile, erro // Check main balance diff. newBalance, err := common.AddInt64(diff.balance, int64(profile.balance)) if err != nil { - return nil, errors.Errorf("failed to add balance and balance diff: %v\n", err) + return balanceProfile{}, errors.Errorf("failed to add balance and balance diff: %v\n", err) } if newBalance < 0 { - return nil, errors.New("negative result balance (Attempt to transfer unavailable funds)") + return balanceProfile{}, errors.New("negative result balance (Attempt to transfer unavailable funds)") } newLeaseIn, err := common.AddInt64(diff.leaseIn, profile.leaseIn) if err != nil { - return nil, errors.Errorf("failed to add leaseIn and leaseIn diff: %v\n", err) + return balanceProfile{}, errors.Errorf("failed to add leaseIn and leaseIn diff: %v\n", err) } // Check leasing change. newLeaseOut, err := common.AddInt64(diff.leaseOut, profile.leaseOut) if err != nil { - return nil, errors.Errorf("failed to add leaseOut and leaseOut diff: %v\n", err) + return balanceProfile{}, errors.Errorf("failed to add leaseOut and leaseOut diff: %v\n", err) } if (newBalance < newLeaseOut) && !diff.allowLeasedTransfer { - return nil, errs.NewTxValidationError("Reason: Cannot lease more than own") + return balanceProfile{}, errs.NewTxValidationError("Reason: Cannot lease more than own") } // Create new profile. - newProfile := &balanceProfile{} - newProfile.balance = uint64(newBalance) - newProfile.leaseIn = newLeaseIn - newProfile.leaseOut = newLeaseOut - return newProfile, nil + return balanceProfile{ + balance: uint64(newBalance), + leaseIn: newLeaseIn, + leaseOut: newLeaseOut, + }, nil } // applyToAssetBalance() is similar to applyTo() but does not deal with leasing. diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 979f56cfb..152d92a51 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -143,7 +143,7 @@ func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transact } func (tp *transactionPerformer) increaseOrderVolume(order proto.Order, tx proto.Exchange, info *performerInfo) error { - orderId, err := order.GetID() + orderID, err := order.GetID() if err != nil { return err } @@ -151,13 +151,7 @@ func (tp *transactionPerformer) increaseOrderVolume(order proto.Order, tx proto. if order.GetOrderType() == proto.Sell { fee = tx.GetSellMatcherFee() } - if err := tp.stor.ordersVolumes.increaseFilledFee(orderId, fee, info.blockID); err != nil { - return err - } - if err := tp.stor.ordersVolumes.increaseFilledAmount(orderId, tx.GetAmount(), info.blockID); err != nil { - return err - } - return nil + return tp.stor.ordersVolumes.increaseFilled(orderID, tx.GetAmount(), fee, info.blockID) } func (tp *transactionPerformer) performExchange(transaction proto.Transaction, info *performerInfo) error { diff --git a/pkg/state/transaction_performer_test.go b/pkg/state/transaction_performer_test.go index ffb6ac4bb..bcb9dd445 100644 --- a/pkg/state/transaction_performer_test.go +++ b/pkg/state/transaction_performer_test.go @@ -165,44 +165,32 @@ func TestPerformExchange(t *testing.T) { err := to.tp.performExchange(tx, defaultPerformerInfo()) assert.NoError(t, err, "performExchange() failed") - sellOrderId, err := tx.GetOrder2().GetID() + sellOrderID, err := tx.GetOrder2().GetID() assert.NoError(t, err) - filledFee, err := to.stor.entities.ordersVolumes.newestFilledFee(sellOrderId) + filledAmount, filledFee, err := to.stor.entities.ordersVolumes.newestFilled(sellOrderID) assert.NoError(t, err) assert.Equal(t, tx.GetSellMatcherFee(), filledFee) - - filledAmount, err := to.stor.entities.ordersVolumes.newestFilledAmount(sellOrderId) - assert.NoError(t, err) assert.Equal(t, tx.GetAmount(), filledAmount) - buyOrderId, err := tx.GetOrder1().GetID() + buyOrderID, err := tx.GetOrder1().GetID() assert.NoError(t, err) - filledFee, err = to.stor.entities.ordersVolumes.newestFilledFee(buyOrderId) + filledAmount, filledFee, err = to.stor.entities.ordersVolumes.newestFilled(buyOrderID) assert.NoError(t, err) assert.Equal(t, tx.GetBuyMatcherFee(), filledFee) - - filledAmount, err = to.stor.entities.ordersVolumes.newestFilledAmount(buyOrderId) - assert.NoError(t, err) assert.Equal(t, tx.GetAmount(), filledAmount) to.stor.flush(t) - filledFee, err = to.stor.entities.ordersVolumes.newestFilledFee(sellOrderId) + filledAmount, filledFee, err = to.stor.entities.ordersVolumes.newestFilled(sellOrderID) assert.NoError(t, err) assert.Equal(t, tx.GetSellMatcherFee(), filledFee) - - filledAmount, err = to.stor.entities.ordersVolumes.newestFilledAmount(sellOrderId) - assert.NoError(t, err) assert.Equal(t, tx.GetAmount(), filledAmount) - filledFee, err = to.stor.entities.ordersVolumes.newestFilledFee(buyOrderId) + filledAmount, filledFee, err = to.stor.entities.ordersVolumes.newestFilled(buyOrderID) assert.NoError(t, err) assert.Equal(t, tx.GetBuyMatcherFee(), filledFee) - - filledAmount, err = to.stor.entities.ordersVolumes.newestFilledAmount(buyOrderId) - assert.NoError(t, err) assert.Equal(t, tx.GetAmount(), filledAmount) } From 54b556ee621f8a0a84f0d4ce9ad6bb59d58668da Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Fri, 30 Jun 2023 01:56:01 +0300 Subject: [PATCH 035/139] Replace 'SnapshotManager' to 'SnapshotApplier'. --- pkg/state/snapshot_applier.go | 16 ---------------- pkg/state/snapshot_types.go | 34 +++++++++++++++++++--------------- 2 files changed, 19 insertions(+), 31 deletions(-) diff --git a/pkg/state/snapshot_applier.go b/pkg/state/snapshot_applier.go index 6ad95544c..1fb25cc0a 100644 --- a/pkg/state/snapshot_applier.go +++ b/pkg/state/snapshot_applier.go @@ -7,22 +7,6 @@ import ( "github.com/wavesplatform/gowaves/pkg/ride/serialization" ) -type SnapshotApplier interface { - ApplyWavesBalance(snapshot WavesBalanceSnapshot) error - ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) error - ApplyAssetBalance(snapshot AssetBalanceSnapshot) error - ApplyAlias(snapshot AliasSnapshot) error - ApplyStaticAssetInfo(snapshot StaticAssetInfoSnapshot) error - ApplyAssetDescription(snapshot AssetDescriptionSnapshot) error - ApplyAssetVolume(snapshot AssetVolumeSnapshot) error - ApplyAssetScript(snapshot AssetScriptSnapshot) error - ApplySponsorship(snapshot SponsorshipSnapshot) error - ApplyAccountScript(snapshot AccountScriptSnapshot) error - ApplyFilledVolumeAndFee(snapshot FilledVolumeFeeSnapshot) error - ApplyDataEntries(snapshot DataEntriesSnapshot) error - ApplyLeaseState(snapshot LeaseStateSnapshot) error -} - type blockSnapshotsApplier struct { info blockSnapshotsApplierInfo stor snapshotApplierStorages diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 7b2e5e8fe..9bf71d075 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -9,14 +9,14 @@ import ( type TransactionSnapshot []AtomicSnapshot -type AtomicSnapshot interface{ Apply(SnapshotManager) error } +type AtomicSnapshot interface{ Apply(SnapshotApplier) error } type WavesBalanceSnapshot struct { Address proto.WavesAddress Balance uint64 } -func (s WavesBalanceSnapshot) Apply(m SnapshotManager) error { return m.ApplyWavesBalance(s) } +func (s WavesBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyWavesBalance(s) } type AssetBalanceSnapshot struct { Address proto.WavesAddress @@ -24,14 +24,14 @@ type AssetBalanceSnapshot struct { Balance uint64 } -func (s AssetBalanceSnapshot) Apply(m SnapshotManager) error { return m.ApplyAssetBalance(s) } +func (s AssetBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetBalance(s) } type DataEntriesSnapshot struct { // AccountData in pb Address proto.WavesAddress DataEntries []proto.DataEntry } -func (s DataEntriesSnapshot) Apply(m SnapshotManager) error { return m.ApplyDataEntries(s) } +func (s DataEntriesSnapshot) Apply(a SnapshotApplier) error { return a.ApplyDataEntries(s) } type AccountScriptSnapshot struct { SenderPublicKey crypto.PublicKey @@ -39,7 +39,7 @@ type AccountScriptSnapshot struct { VerifierComplexity uint64 } -func (s AccountScriptSnapshot) Apply(m SnapshotManager) error { return m.ApplyAccountScript(s) } +func (s AccountScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAccountScript(s) } type AssetScriptSnapshot struct { AssetID crypto.Digest @@ -47,7 +47,7 @@ type AssetScriptSnapshot struct { Complexity uint64 } -func (s AssetScriptSnapshot) Apply(m SnapshotManager) error { return m.ApplyAssetScript(s) } +func (s AssetScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetScript(s) } type LeaseBalanceSnapshot struct { Address proto.WavesAddress @@ -55,7 +55,7 @@ type LeaseBalanceSnapshot struct { LeaseOut uint64 } -func (s LeaseBalanceSnapshot) Apply(m SnapshotManager) error { return m.ApplyLeaseBalance(s) } +func (s LeaseBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseBalance(s) } type LeaseStateStatus struct { Value LeaseStatus // can be only LeaseActive or LeaseCanceled @@ -73,21 +73,21 @@ type LeaseStateSnapshot struct { Height proto.Height } -func (s LeaseStateSnapshot) Apply(m SnapshotManager) error { return m.ApplyLeaseState(s) } +func (s LeaseStateSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseState(s) } type SponsorshipSnapshot struct { AssetID crypto.Digest MinSponsoredFee uint64 } -func (s SponsorshipSnapshot) Apply(m SnapshotManager) error { return m.ApplySponsorship(s) } +func (s SponsorshipSnapshot) Apply(a SnapshotApplier) error { return a.ApplySponsorship(s) } type AliasSnapshot struct { Address proto.WavesAddress Alias proto.Alias } -func (s AliasSnapshot) Apply(m SnapshotManager) error { return m.ApplyAlias(s) } +func (s AliasSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAlias(s) } // FilledVolumeFeeSnapshot Filled Volume and Fee type FilledVolumeFeeSnapshot struct { // OrderFill @@ -96,7 +96,7 @@ type FilledVolumeFeeSnapshot struct { // OrderFill FilledFee uint64 } -func (s FilledVolumeFeeSnapshot) Apply(m SnapshotManager) error { return m.ApplyFilledVolumeAndFee(s) } +func (s FilledVolumeFeeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyFilledVolumeAndFee(s) } type StaticAssetInfoSnapshot struct { AssetID crypto.Digest @@ -106,7 +106,7 @@ type StaticAssetInfoSnapshot struct { IsNFT bool } -func (s StaticAssetInfoSnapshot) Apply(m SnapshotManager) error { return m.ApplyStaticAssetInfo(s) } +func (s StaticAssetInfoSnapshot) Apply(a SnapshotApplier) error { return a.ApplyStaticAssetInfo(s) } type AssetVolumeSnapshot struct { // AssetVolume in pb AssetID crypto.Digest @@ -114,7 +114,7 @@ type AssetVolumeSnapshot struct { // AssetVolume in pb IsReissuable bool } -func (s AssetVolumeSnapshot) Apply(m SnapshotManager) error { return m.ApplyAssetVolume(s) } +func (s AssetVolumeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetVolume(s) } type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb AssetID crypto.Digest @@ -123,9 +123,13 @@ type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb ChangeHeight proto.Height // last_updated in pb } -func (s AssetDescriptionSnapshot) Apply(m SnapshotManager) error { return m.ApplyAssetDescription(s) } +func (s AssetDescriptionSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetDescription(s) } -type SnapshotManager interface { +// SnapshotManager is an alias for SnapshotApplier. +// Deprecated: Exists only for compatibility. Will be removed later. +type SnapshotManager = SnapshotApplier + +type SnapshotApplier interface { ApplyWavesBalance(snapshot WavesBalanceSnapshot) error ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) error ApplyAssetBalance(snapshot AssetBalanceSnapshot) error From 3eb1b86f14e05269f71ddafc9bec0a7d28b7ef45 Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Thu, 29 Jun 2023 23:15:59 -0500 Subject: [PATCH 036/139] Node transaction snapshots (#1078) * Added a conversion function * Added payment transaction conversion * Added transfer tx conversion * Transfer tx conversion changed * Added issue and reissue tx conversions * Issue * Issue, reissue, burn, exchange * Hanled lease transactions * Finished performers * Added snapshots for all types of transactions * Fixed types after merging * Fixed issue snapshot mistake * Added rewards snapshot in append block * Changed functions to newest * Added snapshots from actions * Removed todos * Deleted useless code * Fixed a mistake with leasing cancel * Added tests for issue and reissue transactions * Fixed tests * fixed implicit memory aliasing * Added tests for burn, lease, lease cancel, exchange and create alias transactions * Added tests for data, sponsorship, set account and asset script transactions * Added a test for the invoke transaction snapshots * Fixed after merge * Fixed a function * Moved snapshot generation --- pkg/state/appender.go | 122 ++- pkg/state/block_differ.go | 2 +- pkg/state/block_differ_test.go | 22 +- pkg/state/fee_validation_test.go | 4 +- pkg/state/invoke_applier.go | 78 +- pkg/state/invoke_applier_test.go | 10 +- pkg/state/transaction_checker_test.go | 14 +- pkg/state/transaction_differ_test.go | 4 +- pkg/state/transaction_handler.go | 22 +- pkg/state/transaction_performer.go | 455 ++++++--- pkg/state/transaction_performer_snapshots.go | 745 ++++++++++++++ pkg/state/transaction_performer_test.go | 46 +- pkg/state/transaction_snapshot_test.go | 981 +++++++++++++++++++ 13 files changed, 2255 insertions(+), 250 deletions(-) create mode 100644 pkg/state/transaction_performer_snapshots.go create mode 100644 pkg/state/transaction_snapshot_test.go diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 65386d42f..da87caf22 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -319,49 +319,56 @@ 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, invocationRes *invocationResult, applicationRes *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. - 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 { - return wrapErr(TxCommitmentError, errors.Errorf("failed to save balance diff: %v", err)) + // 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. - if res.status { + currentMinerAddress := proto.MustAddressFromPublicKey(a.settings.AddressSchemeCharacter, params.currentMinerPK) + + var snapshot TransactionSnapshot + if applicationRes.status { // We only perform tx in case it has not failed. performerInfo := &performerInfo{ height: params.checkerInfo.height, - stateActionsCounter: params.stateActionsCounterInBlock, 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 } - if err := a.txHandler.performTx(tx, performerInfo); err != nil { - return wrapErr(TxCommitmentError, errors.Errorf("failed to perform: %v", err)) + // 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 { - return wrapErr(TxCommitmentError, errors.Errorf("failed to write transaction to in mem stor: %v", err)) + 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 { // 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)) + if err := a.rw.writeTransaction(tx, !applicationRes.status); err != nil { + 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 { @@ -405,18 +412,19 @@ type appendTxParams struct { invokeExpressionActivated bool // TODO: check feature naming validatingUtx bool // if validatingUtx == false then chans MUST be initialized with non nil value stateActionsCounterInBlock *proto.StateActionsCounter + currentMinerPK 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) { @@ -470,13 +478,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.Wrap(err, "failed to handle invoke or exchange transaction") } @@ -507,7 +516,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.Wrapf(err, "failed to handle ethereum invoke script transaction (type %s) with id %s, on height %d", ethTx.TxKind.String(), ethTx.ID.String(), params.checkerInfo.height+1) @@ -540,10 +549,17 @@ 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 { + + // 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 } + // a temporary dummy for linters + if len(snapshot) > 1000 { + zap.S().Debug(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 { @@ -553,6 +569,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() { @@ -588,12 +627,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() @@ -633,13 +681,14 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { invokeExpressionActivated: invokeExpressionActivated, validatingUtx: false, stateActionsCounterInBlock: stateActionsCounterInBlock, + currentMinerPK: params.block.GeneratorPublicKey, } if err := a.appendTx(tx, appendTxArgs); err != nil { return err } } // 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 } @@ -669,7 +718,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: @@ -681,17 +730,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) { @@ -798,19 +847,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/block_differ.go b/pkg/state/block_differ.go index a1159900d..6b57c2bf1 100644 --- a/pkg/state/block_differ.go +++ b/pkg/state/block_differ.go @@ -170,7 +170,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 ab580e91d..29b62adb9 100644 --- a/pkg/state/block_differ_test.go +++ b/pkg/state/block_differ_test.go @@ -56,8 +56,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) } @@ -84,8 +84,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() @@ -122,15 +122,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() @@ -185,7 +185,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 @@ -224,7 +224,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) @@ -272,7 +272,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/fee_validation_test.go b/pkg/state/fee_validation_test.go index 9c1f40fef..aeca6a518 100644 --- a/pkg/state/fee_validation_test.go +++ b/pkg/state/fee_validation_test.go @@ -67,7 +67,7 @@ func TestAccountHasVerifierAfterRollbackFilterFalse(t *testing.T) { assert.NoError(t, err, "failed to receive an address from public key") txPerformerInfo := &performerInfo{blockID: blockID2} - err = to.tp.performSetScriptWithProofs(tx, txPerformerInfo) + _, err = to.tp.performSetScriptWithProofs(tx, txPerformerInfo, nil, nil) assert.NoError(t, err, "performSetScriptWithProofs failed with valid SetScriptWithProofs tx") hasVerifier, err := to.tp.stor.scriptsStorage.newestAccountHasVerifier(address) @@ -99,7 +99,7 @@ func TestAccountDoesNotHaveScriptAfterRollbackFilterTrue(t *testing.T) { assert.NoError(t, err, "failed to receive an address from public key") txPerformerInfo := &performerInfo{blockID: blockID2} - err = to.tp.performSetScriptWithProofs(tx, txPerformerInfo) + _, err = to.tp.performSetScriptWithProofs(tx, txPerformerInfo, nil, nil) assert.NoError(t, err, "performSetScriptWithProofs failed with valid SetScriptWithProofs tx") hasVerifier, err := to.tp.stor.scriptsStorage.newestAccountHasVerifier(address) diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index 4ed473d67..8c92f45ea 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -729,7 +729,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() @@ -748,34 +748,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 @@ -784,27 +784,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. @@ -813,32 +813,33 @@ 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. @@ -849,14 +850,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 @@ -867,31 +869,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 @@ -899,7 +905,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 } @@ -908,7 +914,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++ @@ -917,7 +923,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, @@ -935,9 +941,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(), @@ -946,14 +952,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 114890419..d9d044267 100644 --- a/pkg/state/invoke_applier_test.go +++ b/pkg/state/invoke_applier_test.go @@ -129,15 +129,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) { @@ -195,7 +195,7 @@ func (id *invokeApplierTestData) applyTestWithCleanup(t *testing.T, to *invokeAp func (id *invokeApplierTestData) applyTest(t *testing.T, to *invokeApplierTestObjects) { 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/transaction_checker_test.go b/pkg/state/transaction_checker_test.go index dfafe5333..aab51f692 100644 --- a/pkg/state/transaction_checker_test.go +++ b/pkg/state/transaction_checker_test.go @@ -242,7 +242,7 @@ func TestCheckReissueWithSig(t *testing.T) { tx.SenderPK = assetInfo.issuer tx.Reissuable = false - err = to.tp.performReissueWithSig(tx, defaultPerformerInfo()) + _, err = to.tp.performReissueWithSig(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performReissueWithSig failed") to.stor.addBlock(t, blockID0) to.stor.flush(t) @@ -289,7 +289,7 @@ func TestCheckReissueWithProofs(t *testing.T) { tx.SenderPK = assetInfo.issuer tx.Reissuable = false - err = to.tp.performReissueWithProofs(tx, defaultPerformerInfo()) + _, err = to.tp.performReissueWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performReissueWithProofs failed") to.stor.addBlock(t, blockID0) to.stor.flush(t) @@ -611,7 +611,7 @@ func TestCheckLeaseCancelWithSig(t *testing.T) { assert.Error(t, err, "checkLeaseCancelWithSig did not fail when cancelling nonexistent lease") to.stor.addBlock(t, blockID0) - err = to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo()) + _, err = to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performLeaseWithSig failed") to.stor.flush(t) @@ -639,7 +639,7 @@ func TestCheckLeaseCancelWithProofs(t *testing.T) { assert.Error(t, err, "checkLeaseCancelWithProofs did not fail when cancelling nonexistent lease") to.stor.addBlock(t, blockID0) - err = to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo()) + _, err = to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performLeaseWithProofs failed") to.stor.flush(t) @@ -655,7 +655,7 @@ func TestCheckLeaseCancelWithProofs(t *testing.T) { _, err = to.tc.checkLeaseCancelWithProofs(tx, info) assert.NoError(t, err, "checkLeaseCancelWithProofs failed with valid leaseCancel tx") - err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo()) + _, err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performLeaseCancelWithProofs() failed") _, err = to.tc.checkLeaseCancelWithProofs(tx, info) @@ -672,7 +672,7 @@ func TestCheckCreateAliasWithSig(t *testing.T) { assert.NoError(t, err, "checkCreateAliasWithSig failed with valid createAlias tx") to.stor.addBlock(t, blockID0) - err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo()) + _, err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performCreateAliasWithSig failed") to.stor.flush(t) @@ -700,7 +700,7 @@ func TestCheckCreateAliasWithProofs(t *testing.T) { assert.NoError(t, err, "checkCreateAliasWithProofs failed with valid createAlias tx") to.stor.addBlock(t, blockID0) - err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo()) + _, err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performCreateAliasWithProofs failed") to.stor.flush(t) diff --git a/pkg/state/transaction_differ_test.go b/pkg/state/transaction_differ_test.go index 317b6afdf..c1c4c51c5 100644 --- a/pkg/state/transaction_differ_test.go +++ b/pkg/state/transaction_differ_test.go @@ -865,7 +865,7 @@ func TestCreateDiffLeaseCancelWithSig(t *testing.T) { leaseTx := createLeaseWithSig(t) info := defaultPerformerInfo() to.stor.addBlock(t, blockID0) - err := to.tp.performLeaseWithSig(leaseTx, info) + _, err := to.tp.performLeaseWithSig(leaseTx, info, nil, nil) assert.NoError(t, err, "performLeaseWithSig failed") tx := createLeaseCancelWithSig(t, *leaseTx.ID) @@ -898,7 +898,7 @@ func TestCreateDiffLeaseCancelWithProofs(t *testing.T) { leaseTx := createLeaseWithProofs(t) info := defaultPerformerInfo() to.stor.addBlock(t, blockID0) - err := to.tp.performLeaseWithProofs(leaseTx, info) + _, err := to.tp.performLeaseWithProofs(leaseTx, info, nil, nil) assert.NoError(t, err, "performLeaseWithProofs failed") tx := createLeaseCancelWithProofs(t, *leaseTx.ID) diff --git a/pkg/state/transaction_handler.go b/pkg/state/transaction_handler.go index 33a3c686e..16ce0b524 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, *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, @@ -88,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, @@ -154,17 +155,18 @@ 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, invocationRes *invocationResult, applicationRes *applicationResult) (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) + + 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 152d92a51..c5e7992a0 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -11,8 +11,10 @@ import ( type performerInfo struct { height uint64 - stateActionsCounter *proto.StateActionsCounter blockID proto.BlockID + currentMinerAddress proto.WavesAddress + stateActionsCounter *proto.StateActionsCounter + checkerInfo *checkerInfo } type transactionPerformer struct { @@ -24,7 +26,43 @@ 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) 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 genesis transaction") + } + return tp.generateSnapshotForGenesisTx(applicationRes) +} + +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 payment transaction") + } + return tp.generateSnapshotForPaymentTx(applicationRes) +} + +func (tp *transactionPerformer) performTransfer(applicationRes *applicationResult) (TransactionSnapshot, error) { + return tp.generateSnapshotForTransferTx(applicationRes) +} + +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 transfer with sig 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 transfer with proofs transaction") + } + return tp.performTransfer(applicationRes) +} + +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{ @@ -43,149 +81,177 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, assetID crypto.Dig reissuable: tx.Reissuable, }, } + + snapshot, err := tp.generateSnapshotForIssueTx(assetID, txID, tx.SenderPK, *assetInfo, applicationRes) + if err != nil { + return nil, err + } + 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") } - return nil + + return snapshot, nil } -func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (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) + return tp.performIssue(&tx.Issue, assetID, assetID, info, applicationRes) } -func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (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) + return tp.performIssue(&tx.Issue, assetID, assetID, info, applicationRes) } -func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performerInfo) error { +func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { // Modify asset. change := &assetReissueChange{ reissuable: tx.Reissuable, diff: int64(tx.Quantity), } + + snapshot, err := tp.generateSnapshotForReissueTx(tx.AssetID, *change, applicationRes) + if err != nil { + return nil, err + } + 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 + return snapshot, nil } -func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (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) + return tp.performReissue(&tx.Reissue, info, applicationRes) } -func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (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) + return tp.performReissue(&tx.Reissue, info, applicationRes) } -func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo) error { +func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { // Modify asset. change := &assetBurnChange{ diff: int64(tx.Amount), } + + snapshot, err := tp.generateSnapshotForBurnTx(tx.AssetID, *change, applicationRes) + if err != nil { + return nil, err + } + 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 + + return snapshot, nil } -func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (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) + return tp.performBurn(&tx.Burn, info, applicationRes) } -func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (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) + return tp.performBurn(&tx.Burn, info, applicationRes) } -func (tp *transactionPerformer) increaseOrderVolume(order proto.Order, tx proto.Exchange, info *performerInfo) error { +func (tp *transactionPerformer) increaseOrderVolume(order proto.Order, fee uint64, volume uint64, info *performerInfo) error { orderID, err := order.GetID() if err != nil { return err } - fee := tx.GetBuyMatcherFee() - if order.GetOrderType() == proto.Sell { - fee = tx.GetSellMatcherFee() - } - return tp.stor.ordersVolumes.increaseFilled(orderID, tx.GetAmount(), fee, info.blockID) + return tp.stor.ordersVolumes.increaseFilled(orderID, volume, fee, info.blockID) } -func (tp *transactionPerformer) performExchange(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performExchange(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (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() + sellOrder, 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 + buyOrder, err := tx.GetBuyOrder() + if err != nil { + return nil, errors.Wrap(err, "no buy order") } - bo, err := tx.GetBuyOrder() + volume := tx.GetAmount() + sellFee := tx.GetSellMatcherFee() + buyFee := tx.GetBuyMatcherFee() + + // snapshot must be generated before the state with orders is changed + snapshot, err := tp.generateSnapshotForExchangeTx(sellOrder, sellFee, buyOrder, buyFee, volume, applicationRes) if err != nil { - return errors.Wrap(err, "no buy order") + return nil, err } - if err := tp.increaseOrderVolume(bo, tx, info); err != nil { - return err + + err = tp.increaseOrderVolume(sellOrder, sellFee, volume, info) + if err != nil { + return nil, err + } + err = tp.increaseOrderVolume(buyOrder, buyFee, volume, info) + if err != nil { + return nil, err } - return nil + return snapshot, nil } -func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, info *performerInfo) error { +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 { - 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 @@ -198,171 +264,319 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, id *crypto.Digest, Height: info.height, Status: LeaseActive, } - if err := tp.stor.leases.addLeasing(*id, l, info.blockID); err != nil { - return errors.Wrap(err, "failed to add leasing") + snapshot, err := tp.generateSnapshotForLeaseTx(*l, txID, txID, applicationRes) + if err != nil { + return nil, nil + } + + if err := tp.stor.leases.addLeasing(txID, l, info.blockID); err != nil { + return nil, errors.Wrap(err, "failed to add leasing") } - return nil + return snapshot, nil } -func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (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) + return tp.performLease(&tx.Lease, *tx.ID, info, applicationRes) } -func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (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) + return tp.performLease(&tx.Lease, *tx.ID, info, applicationRes) } -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, applicationRes *applicationResult) (TransactionSnapshot, error) { + oldLease, err := tp.stor.leases.newestLeasingInfo(tx.LeaseID) + if err != nil { + return nil, errors.Wrap(err, "failed to receiver leasing info") + } + + snapshot, err := tp.generateSnapshotForLeaseCancelTx(txID, *oldLease, tx.LeaseID, *oldLease.OriginTransactionID, info.height, applicationRes) + if err != nil { + return nil, err + } 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 + return snapshot, nil } -func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (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) + return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info, applicationRes) } -func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (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) + return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info, applicationRes) } -func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info *performerInfo) 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 err + return nil, err + } + + snapshot, err := tp.generateSnapshotForCreateAliasTx(senderAddr, tx.Alias, applicationRes) + if err != nil { + return nil, err } - // Save alias to aliases storage. if err := tp.stor.aliases.createAlias(tx.Alias.Alias, senderAddr, 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, _ *invocationResult, applicationRes *applicationResult) (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) + return tp.performCreateAlias(&tx.CreateAlias, info, applicationRes) } -func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (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, 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") } - return tp.performCreateAlias(&tx.CreateAlias, info) + return tp.generateSnapshotForMassTransferTx(applicationRes) } -func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (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 + } + + snapshot, err := tp.generateSnapshotForDataTx(senderAddr, tx.Entries, applicationRes) + if err != nil { + return nil, err } 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, _ *invocationResult, applicationRes *applicationResult) (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") + } + + snapshot, err := tp.generateSnapshotForSponsorshipTx(tx.AssetID, tx.MinAssetFee, applicationRes) + if err != nil { + return nil, err } 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, _ *invocationResult, applicationRes *applicationResult) (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 + } + + snapshot, err := tp.generateSnapshotForSetScriptTx(senderAddr, tx.SenderPK, tx.Script, info, applicationRes) + if err != nil { + return nil, err } 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, _ *invocationResult, applicationRes *applicationResult) (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") } + + snapshot, err := tp.generateSnapshotForSetAssetScriptTx(tx.AssetID, tx.Script, applicationRes) + if err != nil { + return nil, err + } + 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 snapshot, nil +} + +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 _, ok := addrWavesBalanceDiff[recipientAddress]; ok { + prevRecipientBalance := addrWavesBalanceDiff[recipientAddress] + prevRecipientBalance.balance += amount + addrWavesBalanceDiff[recipientAddress] = prevRecipientBalance + } else { + addrWavesBalanceDiff[recipientAddress] = balanceDiff{balance: amount} + } +} + +// 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 } - return nil + } -func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (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") + } + 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.generateSnapshotForInvokeScriptTx(txID, info, invocationRes, applicationRes) + if err != nil { + return nil, errors.Wrap(err, "failed to generate a snapshot for an invoke transaction") } - return nil + + return snapshot, nil } -func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (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 + 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 + } + + return tp.generateSnapshotForInvokeExpressionTx(txID, info, invocationRes, applicationRes) } -func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (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 + 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.generateSnapshotForEthereumInvokeScriptTx(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) performUpdateAssetInfoWithProofs(transaction proto.Transaction, info *performerInfo) error { +func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (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{ @@ -370,8 +584,13 @@ func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction pro newDescription: tx.Description, newHeight: blockHeight, } + + snapshot, err := tp.generateSnapshotForUpdateAssetInfoTx(tx.AssetID, tx.Name, tx.Description, blockHeight, applicationRes) + if err != nil { + return nil, err + } 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 } 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 +} diff --git a/pkg/state/transaction_performer_test.go b/pkg/state/transaction_performer_test.go index bcb9dd445..97ba679d4 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, new(proto.StateActionsCounter), blockID0} + return &performerInfo{0, blockID0, proto.WavesAddress{}, new(proto.StateActionsCounter), nil} } func TestPerformIssueWithSig(t *testing.T) { @@ -33,7 +33,7 @@ func TestPerformIssueWithSig(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createIssueWithSig(t, 1000) - err := to.tp.performIssueWithSig(tx, defaultPerformerInfo()) + _, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performIssueWithSig() failed") to.stor.flush(t) expectedAssetInfo := assetInfo{ @@ -65,7 +65,7 @@ func TestPerformIssueWithProofs(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createIssueWithProofs(t, 1000) - err := to.tp.performIssueWithProofs(tx, defaultPerformerInfo()) + _, err := to.tp.performIssueWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performIssueWithProofs() failed") to.stor.flush(t) expectedAssetInfo := assetInfo{ @@ -96,7 +96,7 @@ func TestPerformReissueWithSig(t *testing.T) { assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithSig(t, 1000) - err := to.tp.performReissueWithSig(tx, defaultPerformerInfo()) + _, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performReissueWithSig() failed") to.stor.flush(t) assetInfo.reissuable = tx.Reissuable @@ -113,7 +113,7 @@ func TestPerformReissueWithProofs(t *testing.T) { assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithProofs(t, 1000) - err := to.tp.performReissueWithProofs(tx, defaultPerformerInfo()) + _, err := to.tp.performReissueWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performReissueWithProofs() failed") to.stor.flush(t) assetInfo.reissuable = tx.Reissuable @@ -130,7 +130,7 @@ func TestPerformBurnWithSig(t *testing.T) { assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithSig(t) - err := to.tp.performBurnWithSig(tx, defaultPerformerInfo()) + _, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performBurnWithSig() failed") to.stor.flush(t) assetInfo.quantity.Sub(&assetInfo.quantity, big.NewInt(int64(tx.Amount))) @@ -146,7 +146,7 @@ func TestPerformBurnWithProofs(t *testing.T) { assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithProofs(t) - err := to.tp.performBurnWithProofs(tx, defaultPerformerInfo()) + _, err := to.tp.performBurnWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performBurnWithProofs() failed") to.stor.flush(t) assetInfo.quantity.Sub(&assetInfo.quantity, big.NewInt(int64(tx.Amount))) @@ -162,7 +162,7 @@ func TestPerformExchange(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createExchangeWithSig(t) - err := to.tp.performExchange(tx, defaultPerformerInfo()) + _, err := to.tp.performExchange(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performExchange() failed") sellOrderID, err := tx.GetOrder2().GetID() @@ -199,7 +199,7 @@ func TestPerformLeaseWithSig(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createLeaseWithSig(t) - err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo()) + _, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performLeaseWithSig() failed") to.stor.flush(t) leasingInfo := &leasing{ @@ -220,7 +220,7 @@ func TestPerformLeaseWithProofs(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createLeaseWithProofs(t) - err := to.tp.performLeaseWithProofs(tx, defaultPerformerInfo()) + _, err := to.tp.performLeaseWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performLeaseWithProofs() failed") to.stor.flush(t) leasingInfo := &leasing{ @@ -241,7 +241,7 @@ func TestPerformLeaseCancelWithSig(t *testing.T) { to.stor.addBlock(t, blockID0) leaseTx := createLeaseWithSig(t) - err := to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo()) + _, err := to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performLeaseWithSig() failed") to.stor.flush(t) tx := createLeaseCancelWithSig(t, *leaseTx.ID) @@ -253,7 +253,7 @@ func TestPerformLeaseCancelWithSig(t *testing.T) { Sender: testGlobal.senderInfo.addr, CancelTransactionID: tx.ID, } - err = to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo()) + _, err = to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performLeaseCancelWithSig() failed") to.stor.flush(t) info, err := to.stor.entities.leases.leasingInfo(*leaseTx.ID) @@ -266,7 +266,7 @@ func TestPerformLeaseCancelWithProofs(t *testing.T) { to.stor.addBlock(t, blockID0) leaseTx := createLeaseWithProofs(t) - err := to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo()) + _, err := to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performLeaseWithProofs() failed") to.stor.flush(t) tx := createLeaseCancelWithProofs(t, *leaseTx.ID) @@ -278,7 +278,7 @@ func TestPerformLeaseCancelWithProofs(t *testing.T) { Sender: testGlobal.senderInfo.addr, CancelTransactionID: tx.ID, } - err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo()) + _, err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performLeaseCancelWithProofs() failed") to.stor.flush(t) info, err := to.stor.entities.leases.leasingInfo(*leaseTx.ID) @@ -291,7 +291,7 @@ func TestPerformCreateAliasWithSig(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createCreateAliasWithSig(t) - err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo()) + _, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performCreateAliasWithSig() failed") to.stor.flush(t) addr, err := to.stor.entities.aliases.addrByAlias(tx.Alias.Alias) @@ -299,7 +299,7 @@ func TestPerformCreateAliasWithSig(t *testing.T) { assert.Equal(t, testGlobal.senderInfo.addr, addr, "invalid address by alias after performing CreateAliasWithSig transaction") // Test stealing aliases. - err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo()) + _, err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performCreateAliasWithSig() failed") to.stor.flush(t) err = to.stor.entities.aliases.disableStolenAliases(blockID0) @@ -314,7 +314,7 @@ func TestPerformCreateAliasWithProofs(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createCreateAliasWithProofs(t) - err := to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo()) + _, err := to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performCreateAliasWithProofs() failed") to.stor.flush(t) addr, err := to.stor.entities.aliases.addrByAlias(tx.Alias.Alias) @@ -322,7 +322,7 @@ func TestPerformCreateAliasWithProofs(t *testing.T) { assert.Equal(t, testGlobal.senderInfo.addr, addr, "invalid address by alias after performing CreateAliasWithProofs transaction") // Test stealing aliases. - err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo()) + _, err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performCreateAliasWithProofs() failed") to.stor.flush(t) err = to.stor.entities.aliases.disableStolenAliases(blockID0) @@ -341,7 +341,7 @@ func TestPerformDataWithProofs(t *testing.T) { entry := &proto.IntegerDataEntry{Key: "TheKey", Value: int64(666)} tx.Entries = []proto.DataEntry{entry} - err := to.tp.performDataWithProofs(tx, defaultPerformerInfo()) + _, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performDataWithProofs() failed") to.stor.flush(t) @@ -356,7 +356,7 @@ func TestPerformSponsorshipWithProofs(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createSponsorshipWithProofs(t, 1000) - err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo()) + _, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performSponsorshipWithProofs() failed") assetID := proto.AssetIDFromDigest(tx.AssetID) @@ -416,7 +416,7 @@ func TestPerformSetScriptWithProofs(t *testing.T) { require.NoError(t, err) tx := createSetScriptWithProofs(t, scriptBytes) - err = to.tp.performSetScriptWithProofs(tx, defaultPerformerInfo()) + _, err = to.tp.performSetScriptWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performSetScriptWithProofs() failed") addr := testGlobal.senderInfo.addr @@ -485,7 +485,7 @@ func TestPerformSetAssetScriptWithProofs(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createSetAssetScriptWithProofs(t) - err := to.tp.performSetAssetScriptWithProofs(tx, defaultPerformerInfo()) + _, err := to.tp.performSetAssetScriptWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performSetAssetScriptWithProofs() failed") fullAssetID := tx.AssetID @@ -565,7 +565,7 @@ func TestPerformUpdateAssetInfoWithProofs(t *testing.T) { assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createUpdateAssetInfoWithProofs(t) - err := to.tp.performUpdateAssetInfoWithProofs(tx, defaultPerformerInfo()) + _, err := to.tp.performUpdateAssetInfoWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performUpdateAssetInfoWithProofs() failed") to.stor.flush(t) assetInfo.name = tx.Name diff --git a/pkg/state/transaction_snapshot_test.go b/pkg/state/transaction_snapshot_test.go new file mode 100644 index 000000000..c261d2bc2 --- /dev/null +++ b/pkg/state/transaction_snapshot_test.go @@ -0,0 +1,981 @@ +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" + "testing" +) + +func defaultAssetInfoTransfer(tail [12]byte, reissuable bool, amount int64, issuer crypto.PublicKey, name string) *assetInfo { + return &assetInfo{ + assetConstInfo: assetConstInfo{ + tail: tail, + issuer: issuer, + decimals: 2, + }, + assetChangeableInfo: assetChangeableInfo{ + quantity: *big.NewInt(amount), + name: name, + description: "description", + lastNameDescChangeHeight: 1, + reissuable: reissuable, + }, + } +} + +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) + + 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) + 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, + }, + } + + 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) +} + +// TODO send only txBalanceChanges to perfomer +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.issuerInfo.addr.ID(), wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, 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()) + assert.NoError(t, err, "createDiffIssueWithSig() failed") + applicationRes := &applicationResult{true, 0, ch} + transactionSnapshot, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(), nil, applicationRes) + assert.NoError(t, err, "failed to perform issue tx") + + 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, + }, + } + 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 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), 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") + 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(1*FeeUnit)) + err = tx.Sign(proto.TestNetScheme, testGlobal.issuerInfo.sk) + assert.NoError(t, err, "failed to sign reissue tx") + + ch, err := to.td.createDiffReissueWithSig(tx, defaultDifferInfo()) + 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") + + 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, + }, + } + + 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 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), 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") + 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(1*FeeUnit)) + err = tx.Sign(proto.TestNetScheme, testGlobal.issuerInfo.sk) + assert.NoError(t, err, "failed to sign burn tx") + ch, err := to.td.createDiffBurnWithSig(tx, defaultDifferInfo()) + 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") + + 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, + }, + } + + 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 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: LeaseStateStatus{ + Value: 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, + 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: LeaseStateStatus{ + Value: LeaseCanceled, + CancelHeight: 0, + CancelTransactionID: tx.ID, + }, + 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) +} + +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) +} + +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 01da4a8d411f85f50c58b1779b7ab6d0077b954e Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Fri, 30 Jun 2023 16:17:06 +0300 Subject: [PATCH 037/139] Remove 'SnapshotManager' interface. --- pkg/state/snapshot_types.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 9bf71d075..f3709d26d 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -125,10 +125,6 @@ type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb func (s AssetDescriptionSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetDescription(s) } -// SnapshotManager is an alias for SnapshotApplier. -// Deprecated: Exists only for compatibility. Will be removed later. -type SnapshotManager = SnapshotApplier - type SnapshotApplier interface { ApplyWavesBalance(snapshot WavesBalanceSnapshot) error ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) error From 4c3a6b385bd4548314e4c50ee962b03867d9e47a Mon Sep 17 00:00:00 2001 From: esuwu Date: Sun, 9 Jul 2023 17:39:14 -0500 Subject: [PATCH 038/139] Added a todo --- pkg/state/state.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/state/state.go b/pkg/state/state.go index 82233a58a..5a5a4bcb7 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -1272,6 +1272,7 @@ func (s *stateManager) needToCancelLeases(blockchainHeight uint64) (bool, error) } } +// TODO generate snapshots here too func (s *stateManager) blockchainHeightAction(blockchainHeight uint64, lastBlock, nextBlock proto.BlockID) error { cancelLeases, err := s.needToCancelLeases(blockchainHeight) if err != nil { From 2eb1fedc67ac16da2b447436c627cc32bb22f05e Mon Sep 17 00:00:00 2001 From: esuwu Date: Sun, 9 Jul 2023 20:58:30 -0500 Subject: [PATCH 039/139] Refactored perfomerInfo --- pkg/state/appender.go | 14 ++- pkg/state/invoke_applier.go | 4 +- pkg/state/snapshot_types.go | 2 +- pkg/state/transaction_handler.go | 8 +- pkg/state/transaction_performer.go | 74 +++++------ pkg/state/transaction_performer_snapshots.go | 123 ++++++++++--------- pkg/state/transaction_performer_test.go | 2 - 7 files changed, 118 insertions(+), 109 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 4c7c25bec..a777ef37c 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -321,7 +321,11 @@ func (a *txAppender) saveTransactionIdByAddresses(addresses []proto.WavesAddress return nil } -func (a *txAppender) commitTxApplication(tx proto.Transaction, params *appendTxParams, invocationRes *invocationResult, applicationRes *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 { @@ -341,17 +345,17 @@ func (a *txAppender) commitTxApplication(tx proto.Transaction, params *appendTxP var snapshot TransactionSnapshot if applicationRes.status { - //We only perform tx in case it has not failed. + // We only perform tx in case it has not failed. performerInfo := &performerInfo{ height: params.checkerInfo.height, 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 + estimatorVersion: params.checkerInfo.estimatorVersion(), checkerData: applicationRes.checkerData, } // TODO other snapshots - snapshot, err = a.txHandler.performTx(tx, performerInfo, invocationRes, applicationRes) + snapshot, err = a.txHandler.performTx(tx, performerInfo, invocationRes, applicationRes.changes.diff) if err != nil { return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to perform: %v", err)) } @@ -575,7 +579,7 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro return nil } -// rewards and 60% of the fee to the previous miner +// 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 { diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index 08e63176c..b9807739c 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -729,7 +729,9 @@ 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) (*invocationResult, *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() diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index f3709d26d..6ff55ec17 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -89,7 +89,7 @@ type AliasSnapshot struct { func (s AliasSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAlias(s) } -// FilledVolumeFeeSnapshot Filled Volume and Fee +// FilledVolumeFeeSnapshot Filled Volume and Fee. type FilledVolumeFeeSnapshot struct { // OrderFill OrderID crypto.Digest FilledVolume uint64 diff --git a/pkg/state/transaction_handler.go b/pkg/state/transaction_handler.go index 91d0a6064..fef38b57e 100644 --- a/pkg/state/transaction_handler.go +++ b/pkg/state/transaction_handler.go @@ -22,7 +22,7 @@ type scriptsEstimations struct { func (e *scriptsEstimations) isPresent() bool { return e != nil } type txCheckFunc func(proto.Transaction, *checkerInfo) (txCheckerData, error) -type txPerformFunc func(proto.Transaction, *performerInfo, *invocationResult, *applicationResult) (TransactionSnapshot, error) +type txPerformFunc func(proto.Transaction, *performerInfo, *invocationResult, txDiff) (TransactionSnapshot, error) type txCreateDiffFunc func(proto.Transaction, *differInfo) (txBalanceChanges, error) type txCountFeeFunc func(proto.Transaction, *feeDistribution) error @@ -45,7 +45,7 @@ type transactionHandler struct { } // TODO: see TODO on GetTypeInfo() in proto/transactions.go. -// performer builds snapshots +// 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{ @@ -169,7 +169,7 @@ func (h *transactionHandler) checkTx(tx proto.Transaction, info *checkerInfo) (t return funcs.check(tx, info) } -func (h *transactionHandler) performTx(tx proto.Transaction, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (h *transactionHandler) performTx(tx proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tv := tx.GetTypeInfo() funcs, ok := h.funcs[tv] if !ok { @@ -180,7 +180,7 @@ func (h *transactionHandler) performTx(tx proto.Transaction, info *performerInfo return nil, nil } - return funcs.perform(tx, info, invocationRes, applicationRes) + return funcs.perform(tx, info, invocationRes, balanceChanges) } 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 921f8abb0..11b384070 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -15,8 +15,8 @@ type performerInfo struct { currentMinerAddress proto.WavesAddress stateActionsCounter *proto.StateActionsCounter // TODO put one into another - checkerInfo *checkerInfo - checkerData txCheckerData + estimatorVersion int + checkerData txCheckerData } func newPerformerInfo(height proto.Height, stateActionsCounter *proto.StateActionsCounter, blockID proto.BlockID, currentMinerAddress proto.WavesAddress, checkerInfo *checkerInfo, checkerData txCheckerData) *performerInfo { @@ -32,7 +32,7 @@ func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings return &transactionPerformer{stor, settings}, nil } -func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { _, ok := transaction.(*proto.Genesis) if !ok { return nil, errors.New("failed to convert interface to genesis transaction") @@ -40,7 +40,7 @@ func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, in return tp.generateSnapshotForGenesisTx(applicationRes) } -func (tp *transactionPerformer) performPayment(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performPayment(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { _, ok := transaction.(*proto.Payment) if !ok { return nil, errors.New("failed to convert interface to payment transaction") @@ -48,11 +48,11 @@ func (tp *transactionPerformer) performPayment(transaction proto.Transaction, in return tp.generateSnapshotForPaymentTx(applicationRes) } -func (tp *transactionPerformer) performTransfer(applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performTransfer(balanceChanges txDiff) (TransactionSnapshot, error) { return tp.generateSnapshotForTransferTx(applicationRes) } -func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { _, ok := transaction.(*proto.TransferWithSig) if !ok { return nil, errors.New("failed to convert interface to transfer with sig transaction") @@ -60,7 +60,7 @@ func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transac return tp.performTransfer(applicationRes) } -func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { _, ok := transaction.(*proto.TransferWithProofs) if !ok { return nil, errors.New("failed to convert interface to transfer with proofs transaction") @@ -68,7 +68,7 @@ func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Tran return tp.performTransfer(applicationRes) } -func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest, assetID crypto.Digest, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest, assetID crypto.Digest, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { blockHeight := info.height + 1 // Create new asset. assetInfo := &assetInfo{ @@ -100,7 +100,7 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest return snapshot, nil } -func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.IssueWithSig) if !ok { return nil, errors.New("failed to convert interface to IssueWithSig transaction") @@ -119,7 +119,7 @@ func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transactio return tp.performIssue(&tx.Issue, assetID, assetID, info, applicationRes) } -func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.IssueWithProofs) if !ok { return nil, errors.New("failed to convert interface to IssueWithProofs transaction") @@ -149,7 +149,7 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac return tp.performIssue(&tx.Issue, assetID, assetID, info, applicationRes) } -func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { // Modify asset. change := &assetReissueChange{ reissuable: tx.Reissuable, @@ -167,7 +167,7 @@ func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performe return snapshot, nil } -func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.ReissueWithSig) if !ok { return nil, errors.New("failed to convert interface to ReissueWithSig transaction") @@ -175,7 +175,7 @@ func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transact return tp.performReissue(&tx.Reissue, info, applicationRes) } -func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.ReissueWithProofs) if !ok { return nil, errors.New("failed to convert interface to ReissueWithProofs transaction") @@ -183,7 +183,7 @@ func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Trans return tp.performReissue(&tx.Reissue, info, applicationRes) } -func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { // Modify asset. change := &assetBurnChange{ diff: int64(tx.Amount), @@ -201,7 +201,7 @@ func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, return snapshot, nil } -func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.BurnWithSig) if !ok { return nil, errors.New("failed to convert interface to BurnWithSig transaction") @@ -209,7 +209,7 @@ func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction return tp.performBurn(&tx.Burn, info, applicationRes) } -func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.BurnWithProofs) if !ok { return nil, errors.New("failed to convert interface to BurnWithProofs transaction") @@ -225,7 +225,7 @@ func (tp *transactionPerformer) increaseOrderVolume(order proto.Order, fee uint6 return tp.stor.ordersVolumes.increaseFilled(orderID, volume, fee, info.blockID) } -func (tp *transactionPerformer) performExchange(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performExchange(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(proto.Exchange) if !ok { return nil, errors.New("failed to convert interface to Exchange transaction") @@ -259,7 +259,7 @@ func (tp *transactionPerformer) performExchange(transaction proto.Transaction, i return snapshot, nil } -func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { return nil, err @@ -292,7 +292,7 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest return snapshot, nil } -func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseWithSig) if !ok { return nil, errors.New("failed to convert interface to LeaseWithSig transaction") @@ -300,7 +300,7 @@ func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transactio return tp.performLease(&tx.Lease, *tx.ID, info, applicationRes) } -func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseWithProofs) if !ok { return nil, errors.New("failed to convert interface to LeaseWithProofs transaction") @@ -308,7 +308,7 @@ func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transac return tp.performLease(&tx.Lease, *tx.ID, info, applicationRes) } -func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID *crypto.Digest, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID *crypto.Digest, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { oldLease, err := tp.stor.leases.newestLeasingInfo(tx.LeaseID) if err != nil { return nil, errors.Wrap(err, "failed to receiver leasing info") @@ -324,7 +324,7 @@ func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID * return snapshot, nil } -func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseCancelWithSig) if !ok { return nil, errors.New("failed to convert interface to LeaseCancelWithSig transaction") @@ -332,7 +332,7 @@ func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Tran return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info, applicationRes) } -func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseCancelWithProofs) if !ok { return nil, errors.New("failed to convert interface to LeaseCancelWithProofs transaction") @@ -340,7 +340,7 @@ func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.T return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info, applicationRes) } -func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info *performerInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { return nil, err @@ -356,7 +356,7 @@ func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info * return snapshot, nil } -func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.CreateAliasWithSig) if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithSig transaction") @@ -364,7 +364,7 @@ func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Tran return tp.performCreateAlias(&tx.CreateAlias, info, applicationRes) } -func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.CreateAliasWithProofs) if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") @@ -372,7 +372,7 @@ 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) { +func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { _, ok := transaction.(*proto.MassTransferWithProofs) if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") @@ -380,7 +380,7 @@ func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto. return tp.generateSnapshotForMassTransferTx(applicationRes) } -func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.DataWithProofs) if !ok { @@ -403,7 +403,7 @@ func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transact return snapshot, nil } -func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.SponsorshipWithProofs) if !ok { return nil, errors.New("failed to convert interface to SponsorshipWithProofs transaction") @@ -419,7 +419,7 @@ func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.T return snapshot, nil } -func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.SetScriptWithProofs) if !ok { return nil, errors.New("failed to convert interface to SetScriptWithProofs transaction") @@ -449,7 +449,7 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra return snapshot, nil } -func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.SetAssetScriptWithProofs) if !ok { return nil, errors.New("failed to convert interface to SetAssetScriptWithProofs transaction") @@ -500,7 +500,7 @@ func addToWavesBalanceDiff(addrWavesBalanceDiff addressWavesBalanceDiff, } } -// subtracts the amount from the sender's balance and add it to the recipient's balane +// subtracts the amount from the sender's balance and add it to the recipient's balance. func addSenderRecipientToAssetBalanceDiff(addrAssetBalanceDiff addressAssetBalanceDiff, senderAddress proto.WavesAddress, recipientAddress proto.WavesAddress, @@ -526,7 +526,7 @@ func addSenderRecipientToAssetBalanceDiff(addrAssetBalanceDiff addressAssetBalan } } -// adds/subtracts the amount to the sender balance +// adds/subtracts the amount to the sender balance. func addSenderToAssetBalanceDiff(addrAssetBalanceDiff addressAssetBalanceDiff, senderAddress proto.WavesAddress, asset proto.AssetID, @@ -543,7 +543,7 @@ func addSenderToAssetBalanceDiff(addrAssetBalanceDiff addressAssetBalanceDiff, } -func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { if _, ok := transaction.(*proto.InvokeScriptWithProofs); !ok { return nil, errors.New("failed to convert interface to InvokeScriptWithProofs transaction") } @@ -567,7 +567,7 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. return snapshot, nil } -func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { if _, ok := transaction.(*proto.InvokeExpressionTransactionWithProofs); !ok { return nil, errors.New("failed to convert interface to InvokeExpressionWithProofs transaction") } @@ -586,7 +586,7 @@ func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction pr return tp.generateSnapshotForInvokeExpressionTx(txID, info, invocationRes, applicationRes) } -func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { ethTx, ok := transaction.(*proto.EthereumTransaction) if !ok { return nil, errors.New("failed to convert interface to EthereumTransaction transaction") @@ -613,7 +613,7 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction return snapshot, nil } -func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.UpdateAssetInfoWithProofs) if !ok { return nil, errors.New("failed to convert interface to UpdateAssetInfoWithProofs transaction") diff --git a/pkg/state/transaction_performer_snapshots.go b/pkg/state/transaction_performer_snapshots.go index f9acaa01d..db28fce80 100644 --- a/pkg/state/transaction_performer_snapshots.go +++ b/pkg/state/transaction_performer_snapshots.go @@ -15,34 +15,34 @@ type assetBalanceDiffKey struct { type addressWavesBalanceDiff map[proto.WavesAddress]balanceDiff type addressAssetBalanceDiff map[assetBalanceDiffKey]int64 -func (tp *transactionPerformer) generateSnapshotForGenesisTx(applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { +func (tp *transactionPerformer) generateSnapshotForGenesisTx(balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { return nil, nil } - return tp.generateBalancesSnapshot(applicationRes) + return tp.generateBalancesSnapshot(balanceChanges) } -func (tp *transactionPerformer) generateSnapshotForPaymentTx(applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { +func (tp *transactionPerformer) generateSnapshotForPaymentTx(balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { return nil, nil } - return tp.generateBalancesSnapshot(applicationRes) + return tp.generateBalancesSnapshot(balanceChanges) } -func (tp *transactionPerformer) generateSnapshotForTransferTx(applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { +func (tp *transactionPerformer) generateSnapshotForTransferTx(balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { return nil, nil } - return tp.generateBalancesSnapshot(applicationRes) + return tp.generateBalancesSnapshot(balanceChanges) } -func (tp *transactionPerformer) generateSnapshotForIssueTx(assetID crypto.Digest, txID crypto.Digest, senderPK crypto.PublicKey, assetInfo assetInfo, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { +func (tp *transactionPerformer) generateSnapshotForIssueTx(assetID crypto.Digest, txID crypto.Digest, senderPK crypto.PublicKey, assetInfo assetInfo, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { return nil, nil } var snapshot TransactionSnapshot // TODO add asset script snapshot - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, tp.settings.AddressSchemeCharacter) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") } @@ -101,8 +101,8 @@ func (tp *transactionPerformer) generateSnapshotForIssueTx(assetID crypto.Digest return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForReissueTx(assetID crypto.Digest, change assetReissueChange, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { +func (tp *transactionPerformer) generateSnapshotForReissueTx(assetID crypto.Digest, change assetReissueChange, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { return nil, nil } quantityDiff := big.NewInt(change.diff) @@ -112,7 +112,7 @@ func (tp *transactionPerformer) generateSnapshotForReissueTx(assetID crypto.Dige } resQuantity := assetInfo.quantity.Add(&assetInfo.quantity, quantityDiff) - snapshot, err := tp.generateBalancesSnapshot(applicationRes) + snapshot, err := tp.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } @@ -125,8 +125,8 @@ func (tp *transactionPerformer) generateSnapshotForReissueTx(assetID crypto.Dige return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForBurnTx(assetID crypto.Digest, change assetBurnChange, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { +func (tp *transactionPerformer) generateSnapshotForBurnTx(assetID crypto.Digest, change assetBurnChange, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { return nil, nil } quantityDiff := big.NewInt(change.diff) @@ -136,7 +136,7 @@ func (tp *transactionPerformer) generateSnapshotForBurnTx(assetID crypto.Digest, } resQuantity := assetInfo.quantity.Sub(&assetInfo.quantity, quantityDiff) - snapshot, err := tp.generateBalancesSnapshot(applicationRes) + snapshot, err := tp.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } @@ -149,11 +149,11 @@ func (tp *transactionPerformer) generateSnapshotForBurnTx(assetID crypto.Digest, 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 { +func (tp *transactionPerformer) generateSnapshotForExchangeTx(sellOrder proto.Order, sellFee uint64, buyOrder proto.Order, buyFee uint64, volume uint64, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { return nil, nil } - snapshot, err := tp.generateBalancesSnapshot(applicationRes) + snapshot, err := tp.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } @@ -179,12 +179,12 @@ func (tp *transactionPerformer) generateSnapshotForExchangeTx(sellOrder proto.Or return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForLeaseTx(lease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { +func (tp *transactionPerformer) generateSnapshotForLeaseTx(lease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { return nil, nil } var err error - snapshot, err := tp.generateBalancesSnapshot(applicationRes) + snapshot, err := tp.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } @@ -198,12 +198,12 @@ func (tp *transactionPerformer) generateSnapshotForLeaseTx(lease leasing, leaseI 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 { +func (tp *transactionPerformer) generateSnapshotForLeaseCancelTx(txID *crypto.Digest, oldLease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, cancelHeight uint64, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { return nil, nil } var err error - snapshot, err := tp.generateBalancesSnapshot(applicationRes) + snapshot, err := tp.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } @@ -222,11 +222,11 @@ func (tp *transactionPerformer) generateSnapshotForLeaseCancelTx(txID *crypto.Di return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForCreateAliasTx(senderAddress proto.WavesAddress, alias proto.Alias, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { +func (tp *transactionPerformer) generateSnapshotForCreateAliasTx(senderAddress proto.WavesAddress, alias proto.Alias, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { return nil, nil } - snapshot, err := tp.generateBalancesSnapshot(applicationRes) + snapshot, err := tp.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } @@ -238,18 +238,18 @@ func (tp *transactionPerformer) generateSnapshotForCreateAliasTx(senderAddress p return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForMassTransferTx(applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { +func (tp *transactionPerformer) generateSnapshotForMassTransferTx(balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { return nil, nil } - return tp.generateBalancesSnapshot(applicationRes) + return tp.generateBalancesSnapshot(balanceChanges) } -func (tp *transactionPerformer) generateSnapshotForDataTx(senderAddress proto.WavesAddress, entries []proto.DataEntry, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { +func (tp *transactionPerformer) generateSnapshotForDataTx(senderAddress proto.WavesAddress, entries []proto.DataEntry, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { return nil, nil } - snapshot, err := tp.generateBalancesSnapshot(applicationRes) + snapshot, err := tp.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } @@ -261,11 +261,11 @@ func (tp *transactionPerformer) generateSnapshotForDataTx(senderAddress proto.Wa return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForSponsorshipTx(assetID crypto.Digest, minAssetFee uint64, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { +func (tp *transactionPerformer) generateSnapshotForSponsorshipTx(assetID crypto.Digest, minAssetFee uint64, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { return nil, nil } - snapshot, err := tp.generateBalancesSnapshot(applicationRes) + snapshot, err := tp.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } @@ -277,15 +277,15 @@ func (tp *transactionPerformer) generateSnapshotForSponsorshipTx(assetID crypto. 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 { +func (tp *transactionPerformer) generateSnapshotForSetScriptTx(senderAddress proto.WavesAddress, senderPK crypto.PublicKey, script proto.Script, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { return nil, nil } - snapshot, err := tp.generateBalancesSnapshot(applicationRes) + snapshot, err := tp.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - estimatorVersion := info.checkerInfo.estimatorVersion() + estimatorVersion := info.estimatorVersion // the complexity was saved before when evaluated in checker treeEstimation, err := tp.stor.scriptsComplexity.newestScriptComplexityByAddr(senderAddress, estimatorVersion) if err != nil { @@ -302,11 +302,11 @@ func (tp *transactionPerformer) generateSnapshotForSetScriptTx(senderAddress pro return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { +func (tp *transactionPerformer) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { return nil, nil } - snapshot, err := tp.generateBalancesSnapshot(applicationRes) + snapshot, err := tp.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } @@ -326,23 +326,24 @@ func (tp *transactionPerformer) generateSnapshotForSetAssetScriptTx(assetID cryp 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) generateSnapshotForInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + return tp.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges) } -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) generateSnapshotForInvokeExpressionTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + return tp.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges) } -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) generateSnapshotForEthereumInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + return tp.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges) } -func (tp *transactionPerformer) generateSnapshotForUpdateAssetInfoTx(assetID crypto.Digest, assetName string, assetDescription string, changeHeight proto.Height, applicationRes *applicationResult) (TransactionSnapshot, error) { - if applicationRes == nil { +func (tp *transactionPerformer) generateSnapshotForUpdateAssetInfoTx(assetID crypto.Digest, assetName string, assetDescription string, changeHeight proto.Height, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { return nil, nil } - snapshot, err := tp.generateBalancesSnapshot(applicationRes) + + snapshot, err := tp.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } @@ -357,11 +358,15 @@ func (tp *transactionPerformer) generateSnapshotForUpdateAssetInfoTx(assetID cry } // TODO optimize this -func (tp *transactionPerformer) generateInvokeSnapshot(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) generateInvokeSnapshot( + txID crypto.Digest, + info *performerInfo, + invocationRes *invocationResult, + balanceChanges txDiff) (TransactionSnapshot, error) { blockHeight := info.height + 1 - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, tp.settings.AddressSchemeCharacter) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") } @@ -628,9 +633,9 @@ func (tp *transactionPerformer) generateOrderAtomicSnapshot(orderID []byte, volu return orderSnapshot, nil } -func (tp *transactionPerformer) generateBalancesSnapshot(applicationRes *applicationResult) (TransactionSnapshot, error) { +func (tp *transactionPerformer) generateBalancesSnapshot(balanceChanges txDiff) (TransactionSnapshot, error) { var transactionSnapshot TransactionSnapshot - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(applicationRes.changes.diff, tp.settings.AddressSchemeCharacter) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, tp.settings.AddressSchemeCharacter) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") } diff --git a/pkg/state/transaction_performer_test.go b/pkg/state/transaction_performer_test.go index e434ffad7..6a9df6dc6 100644 --- a/pkg/state/transaction_performer_test.go +++ b/pkg/state/transaction_performer_test.go @@ -489,8 +489,6 @@ func TestPerformSetAssetScriptWithProofs(t *testing.T) { to.stor.addBlock(t, blockID0) tx := createSetAssetScriptWithProofs(t) - _, err := to.tp.performSetAssetScriptWithProofs(tx, defaultPerformerInfo(), nil, nil) - assert.NoError(t, err, "scriptByAddr() failed after flushing") pi := *defaultPerformerInfo() currentEstimatorVersion := 4 From af07985f4aa28b0158962b67dfa90fc33ae122e8 Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 10 Jul 2023 00:40:30 -0500 Subject: [PATCH 040/139] Refactored performer info again --- pkg/state/appender.go | 1 - pkg/state/invoke_applier.go | 23 ++--- pkg/state/transaction_performer.go | 99 ++++++++++---------- pkg/state/transaction_performer_snapshots.go | 17 +--- pkg/state/transaction_performer_test.go | 2 +- pkg/state/transaction_snapshot_test.go | 32 +++---- 6 files changed, 79 insertions(+), 95 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index a777ef37c..b98f5d550 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -351,7 +351,6 @@ func (a *txAppender) commitTxApplication( blockID: params.checkerInfo.blockID, currentMinerAddress: currentMinerAddress, stateActionsCounter: params.stateActionsCounterInBlock, - estimatorVersion: params.checkerInfo.estimatorVersion(), checkerData: applicationRes.checkerData, } // TODO other snapshots diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index b9807739c..c5469dc53 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -859,8 +859,8 @@ func (ia *invokeApplier) applyInvokeScript( strings.Join(ride.EvaluationErrorCallStack(err), "\n"), ) } - invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error(), changes: failedChanges} - applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes) + invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error()} + applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) return invocationRes, applicationRes, err } // Before RideV6 activation in the following cases the transaction is rejected: @@ -878,8 +878,8 @@ func (ia *invokeApplier) applyInvokeScript( strings.Join(ride.EvaluationErrorCallStack(err), "\n"), ) } - invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error(), changes: failedChanges} - applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes) + invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error()} + applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) return invocationRes, applicationRes, err case ride.InternalInvocationError: @@ -893,8 +893,8 @@ func (ia *invokeApplier) applyInvokeScript( strings.Join(ride.EvaluationErrorCallStack(err), "\n"), ) } - invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error(), changes: failedChanges} - applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes) + invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error()} + applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) return invocationRes, applicationRes, err case ride.Undefined, ride.EvaluationFailure: // Unhandled or evaluator error @@ -927,7 +927,7 @@ func (ia *invokeApplier) applyInvokeScript( } } var invocationRes *invocationResult - code, changes, err := ia.fallibleValidation(tx, &addlInvokeInfo{ + code, balanceChanges, err := ia.fallibleValidation(tx, &addlInvokeInfo{ fallibleValidationParams: info, scriptAddr: scriptAddr, scriptPK: scriptPK, @@ -952,17 +952,15 @@ func (ia *invokeApplier) applyInvokeScript( text: err.Error(), scriptRuns: scriptRuns, actions: r.ScriptActions(), - changes: changes, } } else { invocationRes = &invocationResult{ failed: false, scriptRuns: scriptRuns, actions: r.ScriptActions(), - changes: changes, } } - applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes) + applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes, balanceChanges) return invocationRes, applicationRes, err } @@ -973,7 +971,6 @@ type invocationResult struct { scriptRuns uint64 actions []proto.ScriptAction - changes txBalanceChanges } func toScriptResult(ir *invocationResult) (*proto.ScriptResult, error) { @@ -985,7 +982,7 @@ func toScriptResult(ir *invocationResult) (*proto.ScriptResult, error) { return sr, err } -func (ia *invokeApplier) handleInvocationResult(txID crypto.Digest, checkerData txCheckerData, info *fallibleValidationParams, res *invocationResult) (*applicationResult, error) { +func (ia *invokeApplier) handleInvocationResult(txID crypto.Digest, checkerData txCheckerData, info *fallibleValidationParams, res *invocationResult, balanceChanges txBalanceChanges) (*applicationResult, error) { if ia.buildApiData && !info.validatingUtx { // Save invoke result for extended API. res, err := toScriptResult(res) @@ -998,7 +995,7 @@ func (ia *invokeApplier) handleInvocationResult(txID crypto.Digest, checkerData } // Total scripts invoked = scriptRuns + invocation itself. totalScriptsInvoked := res.scriptRuns + 1 - return newApplicationResult(!res.failed, totalScriptsInvoked, res.changes, checkerData), nil + return newApplicationResult(!res.failed, totalScriptsInvoked, balanceChanges, checkerData), nil } func (ia *invokeApplier) checkFullFee(tx proto.Transaction, scriptRuns, issuedAssetsCount uint64) error { diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 11b384070..d9fc2e80b 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -15,12 +15,11 @@ type performerInfo struct { currentMinerAddress proto.WavesAddress stateActionsCounter *proto.StateActionsCounter // TODO put one into another - estimatorVersion int - checkerData txCheckerData + checkerData txCheckerData } -func newPerformerInfo(height proto.Height, stateActionsCounter *proto.StateActionsCounter, blockID proto.BlockID, currentMinerAddress proto.WavesAddress, checkerInfo *checkerInfo, checkerData txCheckerData) *performerInfo { - return &performerInfo{height, blockID, currentMinerAddress, stateActionsCounter, checkerInfo, checkerData} // all fields must be initialized +func newPerformerInfo(height proto.Height, stateActionsCounter *proto.StateActionsCounter, blockID proto.BlockID, currentMinerAddress proto.WavesAddress, checkerData txCheckerData) *performerInfo { + return &performerInfo{height, blockID, currentMinerAddress, stateActionsCounter, checkerData} // all fields must be initialized } type transactionPerformer struct { @@ -32,24 +31,24 @@ func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings return &transactionPerformer{stor, settings}, nil } -func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { _, ok := transaction.(*proto.Genesis) if !ok { return nil, errors.New("failed to convert interface to genesis transaction") } - return tp.generateSnapshotForGenesisTx(applicationRes) + return tp.generateSnapshotForGenesisTx(balanceChanges) } -func (tp *transactionPerformer) performPayment(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performPayment(transaction proto.Transaction, _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { _, ok := transaction.(*proto.Payment) if !ok { return nil, errors.New("failed to convert interface to payment transaction") } - return tp.generateSnapshotForPaymentTx(applicationRes) + return tp.generateSnapshotForPaymentTx(balanceChanges) } func (tp *transactionPerformer) performTransfer(balanceChanges txDiff) (TransactionSnapshot, error) { - return tp.generateSnapshotForTransferTx(applicationRes) + return tp.generateSnapshotForTransferTx(balanceChanges) } func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -57,7 +56,7 @@ func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transac if !ok { return nil, errors.New("failed to convert interface to transfer with sig transaction") } - return tp.performTransfer(applicationRes) + return tp.performTransfer(balanceChanges) } func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -65,7 +64,7 @@ func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Tran if !ok { return nil, errors.New("failed to convert interface to transfer with proofs transaction") } - return tp.performTransfer(applicationRes) + return tp.performTransfer(balanceChanges) } func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest, assetID crypto.Digest, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -88,7 +87,7 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest }, } - snapshot, err := tp.generateSnapshotForIssueTx(assetID, txID, tx.SenderPK, *assetInfo, applicationRes) + snapshot, err := tp.generateSnapshotForIssueTx(assetID, txID, tx.SenderPK, *assetInfo, balanceChanges) if err != nil { return nil, err } @@ -116,7 +115,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, assetID, info, applicationRes) + return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges) } func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -146,7 +145,7 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac return nil, err } } - return tp.performIssue(&tx.Issue, assetID, assetID, info, applicationRes) + return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges) } func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -156,7 +155,7 @@ func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performe diff: int64(tx.Quantity), } - snapshot, err := tp.generateSnapshotForReissueTx(tx.AssetID, *change, applicationRes) + snapshot, err := tp.generateSnapshotForReissueTx(tx.AssetID, *change, balanceChanges) if err != nil { return nil, err } @@ -172,7 +171,7 @@ func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transact if !ok { return nil, errors.New("failed to convert interface to ReissueWithSig transaction") } - return tp.performReissue(&tx.Reissue, info, applicationRes) + return tp.performReissue(&tx.Reissue, info, balanceChanges) } func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -180,7 +179,7 @@ func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Trans if !ok { return nil, errors.New("failed to convert interface to ReissueWithProofs transaction") } - return tp.performReissue(&tx.Reissue, info, applicationRes) + return tp.performReissue(&tx.Reissue, info, balanceChanges) } func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -189,7 +188,7 @@ func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, diff: int64(tx.Amount), } - snapshot, err := tp.generateSnapshotForBurnTx(tx.AssetID, *change, applicationRes) + snapshot, err := tp.generateSnapshotForBurnTx(tx.AssetID, *change, balanceChanges) if err != nil { return nil, err } @@ -206,7 +205,7 @@ func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction if !ok { return nil, errors.New("failed to convert interface to BurnWithSig transaction") } - return tp.performBurn(&tx.Burn, info, applicationRes) + return tp.performBurn(&tx.Burn, info, balanceChanges) } func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -214,7 +213,7 @@ func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transact if !ok { return nil, errors.New("failed to convert interface to BurnWithProofs transaction") } - return tp.performBurn(&tx.Burn, info, applicationRes) + return tp.performBurn(&tx.Burn, info, balanceChanges) } func (tp *transactionPerformer) increaseOrderVolume(order proto.Order, fee uint64, volume uint64, info *performerInfo) error { @@ -243,7 +242,7 @@ func (tp *transactionPerformer) performExchange(transaction proto.Transaction, i buyFee := tx.GetBuyMatcherFee() // snapshot must be generated before the state with orders is changed - snapshot, err := tp.generateSnapshotForExchangeTx(sellOrder, sellFee, buyOrder, buyFee, volume, applicationRes) + snapshot, err := tp.generateSnapshotForExchangeTx(sellOrder, sellFee, buyOrder, buyFee, volume, balanceChanges) if err != nil { return nil, err } @@ -281,7 +280,7 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest Height: info.height, Status: LeaseActive, } - snapshot, err := tp.generateSnapshotForLeaseTx(*l, txID, txID, applicationRes) + snapshot, err := tp.generateSnapshotForLeaseTx(*l, txID, txID, balanceChanges) if err != nil { return nil, nil } @@ -297,7 +296,7 @@ func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transactio if !ok { return nil, errors.New("failed to convert interface to LeaseWithSig transaction") } - return tp.performLease(&tx.Lease, *tx.ID, info, applicationRes) + return tp.performLease(&tx.Lease, *tx.ID, info, balanceChanges) } func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -305,7 +304,7 @@ func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transac if !ok { return nil, errors.New("failed to convert interface to LeaseWithProofs transaction") } - return tp.performLease(&tx.Lease, *tx.ID, info, applicationRes) + return tp.performLease(&tx.Lease, *tx.ID, info, balanceChanges) } func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID *crypto.Digest, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -314,7 +313,7 @@ func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID * return nil, errors.Wrap(err, "failed to receiver leasing info") } - snapshot, err := tp.generateSnapshotForLeaseCancelTx(txID, *oldLease, tx.LeaseID, *oldLease.OriginTransactionID, info.height, applicationRes) + snapshot, err := tp.generateSnapshotForLeaseCancelTx(txID, *oldLease, tx.LeaseID, *oldLease.OriginTransactionID, info.height, balanceChanges) if err != nil { return nil, err } @@ -329,7 +328,7 @@ func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Tran if !ok { return nil, errors.New("failed to convert interface to LeaseCancelWithSig transaction") } - return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info, applicationRes) + return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info, balanceChanges) } func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -337,7 +336,7 @@ func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.T if !ok { return nil, errors.New("failed to convert interface to LeaseCancelWithProofs transaction") } - return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info, applicationRes) + return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info, balanceChanges) } func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -346,7 +345,7 @@ func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info * return nil, err } - snapshot, err := tp.generateSnapshotForCreateAliasTx(senderAddr, tx.Alias, applicationRes) + snapshot, err := tp.generateSnapshotForCreateAliasTx(senderAddr, tx.Alias, balanceChanges) if err != nil { return nil, err } @@ -361,7 +360,7 @@ func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Tran if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithSig transaction") } - return tp.performCreateAlias(&tx.CreateAlias, info, applicationRes) + return tp.performCreateAlias(&tx.CreateAlias, info, balanceChanges) } func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -369,7 +368,7 @@ func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.T if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") } - return tp.performCreateAlias(&tx.CreateAlias, info, applicationRes) + return tp.performCreateAlias(&tx.CreateAlias, info, balanceChanges) } func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -377,7 +376,7 @@ func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto. if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") } - return tp.generateSnapshotForMassTransferTx(applicationRes) + return tp.generateSnapshotForMassTransferTx(balanceChanges) } func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -391,7 +390,7 @@ func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transact return nil, err } - snapshot, err := tp.generateSnapshotForDataTx(senderAddr, tx.Entries, applicationRes) + snapshot, err := tp.generateSnapshotForDataTx(senderAddr, tx.Entries, balanceChanges) if err != nil { return nil, err } @@ -409,7 +408,7 @@ func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.T return nil, errors.New("failed to convert interface to SponsorshipWithProofs transaction") } - snapshot, err := tp.generateSnapshotForSponsorshipTx(tx.AssetID, tx.MinAssetFee, applicationRes) + snapshot, err := tp.generateSnapshotForSponsorshipTx(tx.AssetID, tx.MinAssetFee, balanceChanges) if err != nil { return nil, err } @@ -433,19 +432,21 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra if !se.isPresent() { return nil, errors.New("script estimations must be set for SetScriptWithProofs tx") } - // Save complexity to storage, so we won't have to calculate it every time the script is called. - if err := tp.stor.scriptsComplexity.saveComplexitiesForAddr(senderAddr, se.estimations, info.blockID); err != nil { - return nil, err - } - snapshot, err := tp.generateSnapshotForSetScriptTx(senderAddr, tx.SenderPK, tx.Script, info, applicationRes) + // TODO check on correctness + complexity := info.checkerData.scriptEstimations.estimations[se.currentEstimatorVersion].Verifier + + snapshot, err := tp.generateSnapshotForSetScriptTx(tx.SenderPK, tx.Script, complexity, info, balanceChanges) if err != nil { return nil, err } 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") } - + // Save complexity to storage, so we won't have to calculate it every time the script is called. + if err := tp.stor.scriptsComplexity.saveComplexitiesForAddr(senderAddr, se.estimations, info.blockID); err != nil { + return nil, err + } return snapshot, nil } @@ -463,19 +464,19 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot if !ok { return nil, errors.Errorf("failed to calculate asset script complexity by estimator version %d", se.currentEstimatorVersion) } - // Save complexity to storage, so we won't have to calculate it every time the script is called. + complexity := estimation.Verifier - if err := tp.stor.scriptsComplexity.saveComplexitiesForAsset(tx.AssetID, estimation, info.blockID); err != nil { - return nil, errors.Wrapf(err, "failed to save script complexity for asset %q", tx.AssetID.String()) - } - snapshot, err := tp.generateSnapshotForSetAssetScriptTx(tx.AssetID, tx.Script, applicationRes) + snapshot, err := tp.generateSnapshotForSetAssetScriptTx(tx.AssetID, tx.Script, complexity, balanceChanges) if err != nil { return nil, err } 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") } - + // Save complexity to storage, so we won't have to calculate it every time the script is called. + if err := tp.stor.scriptsComplexity.saveComplexitiesForAsset(tx.AssetID, estimation, info.blockID); err != nil { + return nil, errors.Wrapf(err, "failed to save script complexity for asset %q", tx.AssetID.String()) + } return snapshot, nil } @@ -559,7 +560,7 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. return nil, err } - snapshot, err := tp.generateSnapshotForInvokeScriptTx(txID, info, invocationRes, applicationRes) + snapshot, err := tp.generateSnapshotForInvokeScriptTx(txID, info, invocationRes, balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot for an invoke transaction") } @@ -583,7 +584,7 @@ func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction pr return nil, err } - return tp.generateSnapshotForInvokeExpressionTx(txID, info, invocationRes, applicationRes) + return tp.generateSnapshotForInvokeExpressionTx(txID, info, invocationRes, balanceChanges) } func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -605,7 +606,7 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction return nil, err } - snapshot, err := tp.generateSnapshotForEthereumInvokeScriptTx(txID, info, invocationRes, applicationRes) + snapshot, err := tp.generateSnapshotForEthereumInvokeScriptTx(txID, info, invocationRes, balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot for an invoke transaction") } @@ -625,7 +626,7 @@ func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction pro newHeight: blockHeight, } - snapshot, err := tp.generateSnapshotForUpdateAssetInfoTx(tx.AssetID, tx.Name, tx.Description, blockHeight, applicationRes) + snapshot, err := tp.generateSnapshotForUpdateAssetInfoTx(tx.AssetID, tx.Name, tx.Description, blockHeight, balanceChanges) if err != nil { return nil, err } diff --git a/pkg/state/transaction_performer_snapshots.go b/pkg/state/transaction_performer_snapshots.go index db28fce80..e6a4afe1d 100644 --- a/pkg/state/transaction_performer_snapshots.go +++ b/pkg/state/transaction_performer_snapshots.go @@ -277,7 +277,7 @@ func (tp *transactionPerformer) generateSnapshotForSponsorshipTx(assetID crypto. return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForSetScriptTx(senderAddress proto.WavesAddress, senderPK crypto.PublicKey, script proto.Script, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) generateSnapshotForSetScriptTx(senderPK crypto.PublicKey, script proto.Script, complexity int, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { if balanceChanges == nil { return nil, nil } @@ -285,13 +285,6 @@ func (tp *transactionPerformer) generateSnapshotForSetScriptTx(senderAddress pro if err != nil { return nil, err } - estimatorVersion := info.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, @@ -302,7 +295,7 @@ func (tp *transactionPerformer) generateSnapshotForSetScriptTx(senderAddress pro return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, complexity int, balanceChanges txDiff) (TransactionSnapshot, error) { if balanceChanges == nil { return nil, nil } @@ -310,12 +303,6 @@ func (tp *transactionPerformer) generateSnapshotForSetAssetScriptTx(assetID cryp 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, diff --git a/pkg/state/transaction_performer_test.go b/pkg/state/transaction_performer_test.go index 6a9df6dc6..cc18b5303 100644 --- a/pkg/state/transaction_performer_test.go +++ b/pkg/state/transaction_performer_test.go @@ -27,7 +27,7 @@ func createPerformerTestObjects(t *testing.T) *performerTestObjects { } func defaultPerformerInfo() *performerInfo { - return newPerformerInfo(0, new(proto.StateActionsCounter), blockID0, proto.WavesAddress{}, nil, txCheckerData{}) + return newPerformerInfo(0, new(proto.StateActionsCounter), blockID0, proto.WavesAddress{}, txCheckerData{}) } func TestPerformIssueWithSig(t *testing.T) { diff --git a/pkg/state/transaction_snapshot_test.go b/pkg/state/transaction_snapshot_test.go index 6932d3971..02c252af5 100644 --- a/pkg/state/transaction_snapshot_test.go +++ b/pkg/state/transaction_snapshot_test.go @@ -32,8 +32,8 @@ func defaultAssetInfoTransfer(tail [12]byte, reissuable bool, amount int64, issu } } -func defaultPerformerInfoWithChecker(checker *checkerInfo, checkerData txCheckerData) *performerInfo { - return &performerInfo{0, blockID0, proto.WavesAddress{}, new(proto.StateActionsCounter), checker, checkerData} +func defaultPerformerInfoWithChecker(checkerData txCheckerData) *performerInfo { + return &performerInfo{0, blockID0, proto.WavesAddress{}, new(proto.StateActionsCounter), checkerData} } func defaultCheckerInfoHeight() *checkerInfo { @@ -71,7 +71,7 @@ func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { ch, err := to.td.createDiffTransferWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffTransferWithSig() failed") applicationRes := &applicationResult{true, 0, ch, txCheckerData{}} - transactionSnapshot, err := to.tp.performTransferWithSig(tx, defaultPerformerInfo(), nil, applicationRes) + transactionSnapshot, err := to.tp.performTransferWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform transfer tx") expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ @@ -123,7 +123,7 @@ func TestDefaultIssueTransactionSnapshot(t *testing.T) { ch, err := to.td.createDiffIssueWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffIssueWithSig() failed") applicationRes := &applicationResult{true, 0, ch, txCheckerData{}} - transactionSnapshot, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(), nil, applicationRes) + transactionSnapshot, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform issue tx") expectedSnapshot := TransactionSnapshot{ @@ -197,7 +197,7 @@ func TestDefaultReissueSnapshot(t *testing.T) { ch, err := to.td.createDiffReissueWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffReissueWithSig() failed") applicationRes := &applicationResult{true, 0, ch, txCheckerData{}} - transactionSnapshot, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(), nil, applicationRes) + transactionSnapshot, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform reissue tx") expectedSnapshot := TransactionSnapshot{ @@ -260,7 +260,7 @@ func TestDefaultBurnSnapshot(t *testing.T) { ch, err := to.td.createDiffBurnWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{true, 0, ch, txCheckerData{}} - transactionSnapshot, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(), nil, applicationRes) + transactionSnapshot, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -344,7 +344,7 @@ func TestDefaultExchangeTransaction(t *testing.T) { ch, err := to.td.createDiffExchange(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{true, 0, ch, txCheckerData{}} - transactionSnapshot, err := to.tp.performExchange(tx, defaultPerformerInfo(), nil, applicationRes) + transactionSnapshot, err := to.tp.performExchange(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -431,7 +431,7 @@ func TestDefaultLeaseSnapshot(t *testing.T) { ch, err := to.td.createDiffLeaseWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{true, 0, ch, txCheckerData{}} - transactionSnapshot, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(), nil, applicationRes) + transactionSnapshot, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -515,7 +515,7 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { ch, err := to.td.createDiffLeaseCancelWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{true, 0, ch, txCheckerData{}} - transactionSnapshot, err := to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(), nil, applicationRes) + transactionSnapshot, err := to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -586,7 +586,7 @@ func TestDefaultCreateAliasSnapshot(t *testing.T) { ch, err := to.td.createDiffCreateAliasWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{true, 0, ch, txCheckerData{}} - transactionSnapshot, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, applicationRes) + transactionSnapshot, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -645,7 +645,7 @@ func TestDefaultDataSnapshot(t *testing.T) { ch, err := to.td.createDiffDataWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{true, 0, ch, txCheckerData{}} - transactionSnapshot, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(), nil, applicationRes) + transactionSnapshot, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -698,7 +698,7 @@ func TestDefaultSponsorshipSnapshot(t *testing.T) { ch, err := to.td.createDiffSponsorshipWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{true, 0, ch, txCheckerData{}} - transactionSnapshot, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(), nil, applicationRes) + transactionSnapshot, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -758,7 +758,7 @@ func TestDefaultSetScriptSnapshot(t *testing.T) { ch, err := to.td.createDiffSetScriptWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{true, 0, ch, checkerData} - transactionSnapshot, err := to.tp.performSetScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerInfo, checkerData), nil, applicationRes) + transactionSnapshot, err := to.tp.performSetScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -825,7 +825,7 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.T) { ch, err := to.td.createDiffSetAssetScriptWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{true, 0, ch, txCheckerData{}} - transactionSnapshot, err := to.tp.performSetAssetScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerInfo, checkerData), nil, applicationRes) + transactionSnapshot, err := to.tp.performSetAssetScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -935,10 +935,10 @@ func TestDefaultInvokeScriptSnapshot(t *testing.T) { Sender: &testGlobal.recipientInfo.pk}, } - invocationResult := &invocationResult{actions: actions, changes: ch} + invocationResult := &invocationResult{actions: actions} applicationRes := &applicationResult{true, 0, ch, txCheckerData{}} - transactionSnapshot, err := to.tp.performInvokeScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerInfo, checkerData), invocationResult, applicationRes) + transactionSnapshot, err := to.tp.performInvokeScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerData), invocationResult, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform invoke script tx") expectedSnapshot := TransactionSnapshot{ From 8ca6086212e7e1778b87166e1ef2cd1ae73efbed Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 10 Jul 2023 01:01:39 -0500 Subject: [PATCH 041/139] Moved generation to snapshot generator --- ...mer_snapshots.go => snapshot_generator.go} | 164 +++++++++--------- ...hot_test.go => snapshot_generator_test.go} | 3 +- pkg/state/transaction_checker_test.go | 3 +- pkg/state/transaction_differ_test.go | 3 +- pkg/state/transaction_handler.go | 3 +- pkg/state/transaction_performer.go | 47 ++--- pkg/state/transaction_performer_test.go | 3 +- 7 files changed, 119 insertions(+), 107 deletions(-) rename pkg/state/{transaction_performer_snapshots.go => snapshot_generator.go} (73%) rename pkg/state/{transaction_snapshot_test.go => snapshot_generator_test.go} (99%) diff --git a/pkg/state/transaction_performer_snapshots.go b/pkg/state/snapshot_generator.go similarity index 73% rename from pkg/state/transaction_performer_snapshots.go rename to pkg/state/snapshot_generator.go index e6a4afe1d..892e60987 100644 --- a/pkg/state/transaction_performer_snapshots.go +++ b/pkg/state/snapshot_generator.go @@ -4,9 +4,15 @@ import ( "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" + "github.com/wavesplatform/gowaves/pkg/settings" "math/big" ) +type snapshotGenerator struct { + stor *blockchainEntitiesStorage + settings *settings.BlockchainSettings +} + type assetBalanceDiffKey struct { address proto.WavesAddress asset proto.AssetID @@ -15,34 +21,34 @@ type assetBalanceDiffKey struct { type addressWavesBalanceDiff map[proto.WavesAddress]balanceDiff type addressAssetBalanceDiff map[assetBalanceDiffKey]int64 -func (tp *transactionPerformer) generateSnapshotForGenesisTx(balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForGenesisTx(balanceChanges txDiff) (TransactionSnapshot, error) { if balanceChanges == nil { return nil, nil } - return tp.generateBalancesSnapshot(balanceChanges) + return sg.generateBalancesSnapshot(balanceChanges) } -func (tp *transactionPerformer) generateSnapshotForPaymentTx(balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForPaymentTx(balanceChanges txDiff) (TransactionSnapshot, error) { if balanceChanges == nil { return nil, nil } - return tp.generateBalancesSnapshot(balanceChanges) + return sg.generateBalancesSnapshot(balanceChanges) } -func (tp *transactionPerformer) generateSnapshotForTransferTx(balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForTransferTx(balanceChanges txDiff) (TransactionSnapshot, error) { if balanceChanges == nil { return nil, nil } - return tp.generateBalancesSnapshot(balanceChanges) + return sg.generateBalancesSnapshot(balanceChanges) } -func (tp *transactionPerformer) generateSnapshotForIssueTx(assetID crypto.Digest, txID crypto.Digest, senderPK crypto.PublicKey, assetInfo assetInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, txID crypto.Digest, senderPK crypto.PublicKey, assetInfo assetInfo, balanceChanges txDiff) (TransactionSnapshot, error) { if balanceChanges == nil { return nil, nil } var snapshot TransactionSnapshot // TODO add asset script snapshot - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, tp.settings.AddressSchemeCharacter) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.settings.AddressSchemeCharacter) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") } @@ -83,7 +89,7 @@ func (tp *transactionPerformer) generateSnapshotForIssueTx(assetID crypto.Digest } snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) - wavesBalancesSnapshot, assetBalancesSnapshot, err := tp.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) + wavesBalancesSnapshot, assetBalancesSnapshot, err := sg.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -101,18 +107,18 @@ func (tp *transactionPerformer) generateSnapshotForIssueTx(assetID crypto.Digest return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForReissueTx(assetID crypto.Digest, change assetReissueChange, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, change assetReissueChange, balanceChanges txDiff) (TransactionSnapshot, error) { if balanceChanges == nil { return nil, nil } quantityDiff := big.NewInt(change.diff) - assetInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) + assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) if err != nil { return nil, err } resQuantity := assetInfo.quantity.Add(&assetInfo.quantity, quantityDiff) - snapshot, err := tp.generateBalancesSnapshot(balanceChanges) + snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } @@ -125,18 +131,18 @@ func (tp *transactionPerformer) generateSnapshotForReissueTx(assetID crypto.Dige return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForBurnTx(assetID crypto.Digest, change assetBurnChange, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, change assetBurnChange, balanceChanges txDiff) (TransactionSnapshot, error) { if balanceChanges == nil { return nil, nil } quantityDiff := big.NewInt(change.diff) - assetInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) + assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) if err != nil { return nil, err } resQuantity := assetInfo.quantity.Sub(&assetInfo.quantity, quantityDiff) - snapshot, err := tp.generateBalancesSnapshot(balanceChanges) + snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } @@ -149,11 +155,11 @@ func (tp *transactionPerformer) generateSnapshotForBurnTx(assetID crypto.Digest, return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForExchangeTx(sellOrder proto.Order, sellFee uint64, buyOrder proto.Order, buyFee uint64, volume uint64, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForExchangeTx(sellOrder proto.Order, sellFee uint64, buyOrder proto.Order, buyFee uint64, volume uint64, balanceChanges txDiff) (TransactionSnapshot, error) { if balanceChanges == nil { return nil, nil } - snapshot, err := tp.generateBalancesSnapshot(balanceChanges) + snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } @@ -162,7 +168,7 @@ func (tp *transactionPerformer) generateSnapshotForExchangeTx(sellOrder proto.Or if err != nil { return nil, err } - sellOrderAtomicSnapshot, err := tp.generateOrderAtomicSnapshot(sellOrderID, volume, sellFee) + sellOrderAtomicSnapshot, err := sg.generateOrderAtomicSnapshot(sellOrderID, volume, sellFee) if err != nil { return nil, err } @@ -170,7 +176,7 @@ func (tp *transactionPerformer) generateSnapshotForExchangeTx(sellOrder proto.Or if err != nil { return nil, err } - buyOrderAtomicSnapshot, err := tp.generateOrderAtomicSnapshot(buyOrderID, volume, buyFee) + buyOrderAtomicSnapshot, err := sg.generateOrderAtomicSnapshot(buyOrderID, volume, buyFee) if err != nil { return nil, err } @@ -179,17 +185,17 @@ func (tp *transactionPerformer) generateSnapshotForExchangeTx(sellOrder proto.Or return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForLeaseTx(lease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForLeaseTx(lease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, balanceChanges txDiff) (TransactionSnapshot, error) { if balanceChanges == nil { return nil, nil } var err error - snapshot, err := tp.generateBalancesSnapshot(balanceChanges) + snapshot, err := sg.generateBalancesSnapshot(balanceChanges) 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) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := sg.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") } @@ -198,17 +204,17 @@ func (tp *transactionPerformer) generateSnapshotForLeaseTx(lease leasing, leaseI return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForLeaseCancelTx(txID *crypto.Digest, oldLease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, cancelHeight uint64, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Digest, oldLease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, cancelHeight uint64, balanceChanges txDiff) (TransactionSnapshot, error) { if balanceChanges == nil { return nil, nil } var err error - snapshot, err := tp.generateBalancesSnapshot(balanceChanges) + snapshot, err := sg.generateBalancesSnapshot(balanceChanges) 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) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := sg.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") } @@ -222,11 +228,11 @@ func (tp *transactionPerformer) generateSnapshotForLeaseCancelTx(txID *crypto.Di return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForCreateAliasTx(senderAddress proto.WavesAddress, alias proto.Alias, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForCreateAliasTx(senderAddress proto.WavesAddress, alias proto.Alias, balanceChanges txDiff) (TransactionSnapshot, error) { if balanceChanges == nil { return nil, nil } - snapshot, err := tp.generateBalancesSnapshot(balanceChanges) + snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } @@ -238,18 +244,18 @@ func (tp *transactionPerformer) generateSnapshotForCreateAliasTx(senderAddress p return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForMassTransferTx(balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForMassTransferTx(balanceChanges txDiff) (TransactionSnapshot, error) { if balanceChanges == nil { return nil, nil } - return tp.generateBalancesSnapshot(balanceChanges) + return sg.generateBalancesSnapshot(balanceChanges) } -func (tp *transactionPerformer) generateSnapshotForDataTx(senderAddress proto.WavesAddress, entries []proto.DataEntry, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForDataTx(senderAddress proto.WavesAddress, entries []proto.DataEntry, balanceChanges txDiff) (TransactionSnapshot, error) { if balanceChanges == nil { return nil, nil } - snapshot, err := tp.generateBalancesSnapshot(balanceChanges) + snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } @@ -261,11 +267,11 @@ func (tp *transactionPerformer) generateSnapshotForDataTx(senderAddress proto.Wa return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForSponsorshipTx(assetID crypto.Digest, minAssetFee uint64, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Digest, minAssetFee uint64, balanceChanges txDiff) (TransactionSnapshot, error) { if balanceChanges == nil { return nil, nil } - snapshot, err := tp.generateBalancesSnapshot(balanceChanges) + snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } @@ -277,11 +283,11 @@ func (tp *transactionPerformer) generateSnapshotForSponsorshipTx(assetID crypto. return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForSetScriptTx(senderPK crypto.PublicKey, script proto.Script, complexity int, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.PublicKey, script proto.Script, complexity int, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { if balanceChanges == nil { return nil, nil } - snapshot, err := tp.generateBalancesSnapshot(balanceChanges) + snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } @@ -295,11 +301,11 @@ func (tp *transactionPerformer) generateSnapshotForSetScriptTx(senderPK crypto.P return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, complexity int, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, complexity int, balanceChanges txDiff) (TransactionSnapshot, error) { if balanceChanges == nil { return nil, nil } - snapshot, err := tp.generateBalancesSnapshot(balanceChanges) + snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } @@ -313,24 +319,24 @@ func (tp *transactionPerformer) generateSnapshotForSetAssetScriptTx(assetID cryp return snapshot, nil } -func (tp *transactionPerformer) generateSnapshotForInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { - return tp.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges) +func (sg *snapshotGenerator) generateSnapshotForInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges) } -func (tp *transactionPerformer) generateSnapshotForInvokeExpressionTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { - return tp.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges) +func (sg *snapshotGenerator) generateSnapshotForInvokeExpressionTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges) } -func (tp *transactionPerformer) generateSnapshotForEthereumInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { - return tp.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges) +func (sg *snapshotGenerator) generateSnapshotForEthereumInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges) } -func (tp *transactionPerformer) generateSnapshotForUpdateAssetInfoTx(assetID crypto.Digest, assetName string, assetDescription string, changeHeight proto.Height, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForUpdateAssetInfoTx(assetID crypto.Digest, assetName string, assetDescription string, changeHeight proto.Height, balanceChanges txDiff) (TransactionSnapshot, error) { if balanceChanges == nil { return nil, nil } - snapshot, err := tp.generateBalancesSnapshot(balanceChanges) + snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } @@ -345,7 +351,7 @@ func (tp *transactionPerformer) generateSnapshotForUpdateAssetInfoTx(assetID cry } // TODO optimize this -func (tp *transactionPerformer) generateInvokeSnapshot( +func (sg *snapshotGenerator) generateInvokeSnapshot( txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, @@ -353,7 +359,7 @@ func (tp *transactionPerformer) generateInvokeSnapshot( blockHeight := info.height + 1 - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, tp.settings.AddressSchemeCharacter) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.settings.AddressSchemeCharacter) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") } @@ -365,7 +371,7 @@ func (tp *transactionPerformer) generateInvokeSnapshot( switch a := action.(type) { case *proto.DataEntryScriptAction: - senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + senderAddr, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) if err != nil { return nil, err } @@ -379,11 +385,11 @@ func (tp *transactionPerformer) generateInvokeSnapshot( } case *proto.AttachedPaymentScriptAction: - senderAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + senderAddress, err := proto.NewAddressFromPublicKey(sg.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) + recipientAddress, err := recipientToAddress(a.Recipient, sg.stor.aliases) if err != nil { return nil, errors.Wrap(err, "failed to apply attached payment") } @@ -394,11 +400,11 @@ func (tp *transactionPerformer) generateInvokeSnapshot( addToWavesBalanceDiff(addrWavesBalanceDiff, senderAddress, recipientAddress, a.Amount) } case *proto.TransferScriptAction: - senderAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + senderAddress, err := proto.NewAddressFromPublicKey(sg.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) + recipientAddress, err := recipientToAddress(a.Recipient, sg.stor.aliases) if err != nil { return nil, errors.Wrap(err, "failed to apply attached payment") } @@ -431,7 +437,7 @@ func (tp *transactionPerformer) generateInvokeSnapshot( reissuable: a.Reissuable, }, } - issuerAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + issuerAddress, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) if err != nil { return nil, errors.Wrap(err, "failed to get an address from a public key") } @@ -462,7 +468,7 @@ func (tp *transactionPerformer) generateInvokeSnapshot( case *proto.ReissueScriptAction: - assetInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(a.AssetID)) + assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(a.AssetID)) if err != nil { return nil, err } @@ -474,7 +480,7 @@ func (tp *transactionPerformer) generateInvokeSnapshot( IsReissuable: a.Reissuable, } - issueAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + issueAddress, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) if err != nil { return nil, errors.Wrap(err, "failed to get an address from a public key") } @@ -482,7 +488,7 @@ func (tp *transactionPerformer) generateInvokeSnapshot( snapshot = append(snapshot, assetReissuability) case *proto.BurnScriptAction: - assetInfo, err := tp.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(a.AssetID)) + assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(a.AssetID)) if err != nil { return nil, err } @@ -494,20 +500,20 @@ func (tp *transactionPerformer) generateInvokeSnapshot( IsReissuable: assetInfo.reissuable, } - issueAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, *a.Sender) + issueAddress, err := proto.NewAddressFromPublicKey(sg.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) + senderAddr, err := proto.NewAddressFromPublicKey(sg.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) + recipientAddr, err = sg.stor.aliases.newestAddrByAlias(a.Recipient.Alias().Alias) if err != nil { return nil, errors.Errorf("invalid alias: %v\n", err) } @@ -522,19 +528,19 @@ func (tp *transactionPerformer) generateInvokeSnapshot( Status: LeaseActive, } var amount = int64(l.Amount) - leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := tp.generateLeaseAtomicSnapshots(a.ID, *l, txID, senderAddr, recipientAddr, amount) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := sg.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) + l, err := sg.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) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := sg.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") } @@ -551,7 +557,7 @@ func (tp *transactionPerformer) generateInvokeSnapshot( } - wavesBalancesSnapshot, assetBalancesSnapshot, err := tp.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) + wavesBalancesSnapshot, assetBalancesSnapshot, err := sg.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -566,7 +572,7 @@ func (tp *transactionPerformer) generateInvokeSnapshot( return snapshot, nil } -func (tp *transactionPerformer) generateLeaseAtomicSnapshots(leaseID crypto.Digest, l leasing, originalTxID crypto.Digest, +func (sg *snapshotGenerator) 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, @@ -580,7 +586,7 @@ func (tp *transactionPerformer) generateLeaseAtomicSnapshots(leaseID crypto.Dige Height: l.Height, } - senderBalanceProfile, err := tp.stor.balances.newestWavesBalance(senderAddress.ID()) + senderBalanceProfile, err := sg.stor.balances.newestWavesBalance(senderAddress.ID()) if err != nil { return nil, nil, nil, errors.Wrap(err, "failed to receive sender's waves balance") } @@ -590,7 +596,7 @@ func (tp *transactionPerformer) generateLeaseAtomicSnapshots(leaseID crypto.Dige LeaseOut: uint64(senderBalanceProfile.leaseOut + amount), } - receiverBalanceProfile, err := tp.stor.balances.newestWavesBalance(receiverAddress.ID()) + receiverBalanceProfile, err := sg.stor.balances.newestWavesBalance(receiverAddress.ID()) if err != nil { return nil, nil, nil, errors.Wrap(err, "failed to receive recipient's waves balance") } @@ -603,8 +609,8 @@ func (tp *transactionPerformer) generateLeaseAtomicSnapshots(leaseID crypto.Dige 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) +func (sg *snapshotGenerator) generateOrderAtomicSnapshot(orderID []byte, volume uint64, fee uint64) (*FilledVolumeFeeSnapshot, error) { + newestFilledAmount, newestFilledFee, err := sg.stor.ordersVolumes.newestFilled(orderID) if err != nil { return nil, err } @@ -620,13 +626,13 @@ func (tp *transactionPerformer) generateOrderAtomicSnapshot(orderID []byte, volu return orderSnapshot, nil } -func (tp *transactionPerformer) generateBalancesSnapshot(balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateBalancesSnapshot(balanceChanges txDiff) (TransactionSnapshot, error) { var transactionSnapshot TransactionSnapshot - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, tp.settings.AddressSchemeCharacter) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.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) + wavesBalancesSnapshot, assetBalancesSnapshot, err := sg.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -639,8 +645,8 @@ func (tp *transactionPerformer) generateBalancesSnapshot(balanceChanges txDiff) return transactionSnapshot, nil } -func (tp *transactionPerformer) generateBalancesAtomicSnapshots(addrWavesBalanceDiff addressWavesBalanceDiff, addrAssetBalanceDiff addressAssetBalanceDiff) ([]WavesBalanceSnapshot, []AssetBalanceSnapshot, error) { - wavesBalanceSnapshot, err := tp.constructWavesBalanceSnapshotFromDiff(addrWavesBalanceDiff) +func (sg *snapshotGenerator) generateBalancesAtomicSnapshots(addrWavesBalanceDiff addressWavesBalanceDiff, addrAssetBalanceDiff addressAssetBalanceDiff) ([]WavesBalanceSnapshot, []AssetBalanceSnapshot, error) { + wavesBalanceSnapshot, err := sg.constructWavesBalanceSnapshotFromDiff(addrWavesBalanceDiff) if err != nil { return nil, nil, errors.Wrap(err, "failed to construct waves balance snapshot") } @@ -648,7 +654,7 @@ func (tp *transactionPerformer) generateBalancesAtomicSnapshots(addrWavesBalance return wavesBalanceSnapshot, nil, nil } - assetBalanceSnapshot, err := tp.constructAssetBalanceSnapshotFromDiff(addrAssetBalanceDiff) + assetBalanceSnapshot, err := sg.constructAssetBalanceSnapshotFromDiff(addrAssetBalanceDiff) if err != nil { return nil, nil, errors.Wrap(err, "failed to construct asset balance snapshot") } @@ -693,13 +699,13 @@ func addressBalanceDiffFromTxDiff(diff txDiff, scheme proto.Scheme) (addressWave } // from txDiff and fees. no validation needed at this point -func (tp *transactionPerformer) constructWavesBalanceSnapshotFromDiff(diff addressWavesBalanceDiff) ([]WavesBalanceSnapshot, error) { +func (sg *snapshotGenerator) 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()) + fullBalance, err := sg.stor.balances.newestWavesBalance(wavesAddress.ID()) if err != nil { return nil, errors.Wrap(err, "failed to receive sender's waves balance") } @@ -712,16 +718,16 @@ func (tp *transactionPerformer) constructWavesBalanceSnapshotFromDiff(diff addre return wavesBalances, nil } -func (tp *transactionPerformer) constructAssetBalanceSnapshotFromDiff(diff addressAssetBalanceDiff) ([]AssetBalanceSnapshot, error) { +func (sg *snapshotGenerator) 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) + balance, err := sg.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) + assetInfo, err := sg.stor.assets.newestAssetInfo(key.asset) if err != nil { return nil, errors.Wrap(err, "failed to get newest asset info") } diff --git a/pkg/state/transaction_snapshot_test.go b/pkg/state/snapshot_generator_test.go similarity index 99% rename from pkg/state/transaction_snapshot_test.go rename to pkg/state/snapshot_generator_test.go index 02c252af5..db6c6b930 100644 --- a/pkg/state/transaction_snapshot_test.go +++ b/pkg/state/snapshot_generator_test.go @@ -50,7 +50,8 @@ func defaultCheckerInfoHeight() *checkerInfo { 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) + snapshotGenerator := &snapshotGenerator{stor: stor.entities, settings: settings.MainNetSettings} + tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) require.NoError(t, err, "newTransactionPerformer() failed") return &checkerTestObjects{stor, tc, tp} } diff --git a/pkg/state/transaction_checker_test.go b/pkg/state/transaction_checker_test.go index 2f0d47444..101ac9b97 100644 --- a/pkg/state/transaction_checker_test.go +++ b/pkg/state/transaction_checker_test.go @@ -30,7 +30,8 @@ func createCheckerTestObjects(t *testing.T) *checkerTestObjects { stor := createStorageObjects(t, true) tc, err := newTransactionChecker(proto.NewBlockIDFromSignature(genSig), stor.entities, settings.MainNetSettings) require.NoError(t, err, "newTransactionChecker() failed") - tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings) + snapshotGenerator := &snapshotGenerator{stor: stor.entities, settings: settings.MainNetSettings} + tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) require.NoError(t, err, "newTransactionPerformer() failed") return &checkerTestObjects{stor, tc, tp} } diff --git a/pkg/state/transaction_differ_test.go b/pkg/state/transaction_differ_test.go index c1c4c51c5..7f5e312d1 100644 --- a/pkg/state/transaction_differ_test.go +++ b/pkg/state/transaction_differ_test.go @@ -35,7 +35,8 @@ func createDifferTestObjects(t *testing.T) *differTestObjects { stor := createStorageObjects(t, true) td, err := newTransactionDiffer(stor.entities, settings.MainNetSettings) require.NoError(t, err, "newTransactionDiffer() failed") - tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings) + snapshotGenerator := &snapshotGenerator{stor: stor.entities, settings: settings.MainNetSettings} + tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) require.NoError(t, err, "newTransactionPerformer() failed") return &differTestObjects{stor, td, tp} } diff --git a/pkg/state/transaction_handler.go b/pkg/state/transaction_handler.go index fef38b57e..4975e9f9b 100644 --- a/pkg/state/transaction_handler.go +++ b/pkg/state/transaction_handler.go @@ -141,7 +141,8 @@ func newTransactionHandler( if err != nil { return nil, err } - tp, err := newTransactionPerformer(stor, settings) + snapshotGenerator := &snapshotGenerator{stor: stor, settings: settings} + tp, err := newTransactionPerformer(stor, settings, snapshotGenerator) if err != nil { return nil, err } diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index d9fc2e80b..73bee2f37 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -23,12 +23,13 @@ func newPerformerInfo(height proto.Height, stateActionsCounter *proto.StateActio } type transactionPerformer struct { - stor *blockchainEntitiesStorage - settings *settings.BlockchainSettings + stor *blockchainEntitiesStorage + settings *settings.BlockchainSettings + snapshotGenerator *snapshotGenerator } -func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings.BlockchainSettings) (*transactionPerformer, error) { - return &transactionPerformer{stor, settings}, nil +func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings.BlockchainSettings, snapshotGenerator *snapshotGenerator) (*transactionPerformer, error) { + return &transactionPerformer{stor, settings, snapshotGenerator}, nil } func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -36,7 +37,7 @@ func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, _ if !ok { return nil, errors.New("failed to convert interface to genesis transaction") } - return tp.generateSnapshotForGenesisTx(balanceChanges) + return tp.snapshotGenerator.generateSnapshotForGenesisTx(balanceChanges) } func (tp *transactionPerformer) performPayment(transaction proto.Transaction, _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -44,11 +45,11 @@ func (tp *transactionPerformer) performPayment(transaction proto.Transaction, _ if !ok { return nil, errors.New("failed to convert interface to payment transaction") } - return tp.generateSnapshotForPaymentTx(balanceChanges) + return tp.snapshotGenerator.generateSnapshotForPaymentTx(balanceChanges) } func (tp *transactionPerformer) performTransfer(balanceChanges txDiff) (TransactionSnapshot, error) { - return tp.generateSnapshotForTransferTx(balanceChanges) + return tp.snapshotGenerator.generateSnapshotForTransferTx(balanceChanges) } func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -87,7 +88,7 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest }, } - snapshot, err := tp.generateSnapshotForIssueTx(assetID, txID, tx.SenderPK, *assetInfo, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForIssueTx(assetID, txID, tx.SenderPK, *assetInfo, balanceChanges) if err != nil { return nil, err } @@ -155,7 +156,7 @@ func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performe diff: int64(tx.Quantity), } - snapshot, err := tp.generateSnapshotForReissueTx(tx.AssetID, *change, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForReissueTx(tx.AssetID, *change, balanceChanges) if err != nil { return nil, err } @@ -188,7 +189,7 @@ func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, diff: int64(tx.Amount), } - snapshot, err := tp.generateSnapshotForBurnTx(tx.AssetID, *change, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForBurnTx(tx.AssetID, *change, balanceChanges) if err != nil { return nil, err } @@ -242,7 +243,7 @@ func (tp *transactionPerformer) performExchange(transaction proto.Transaction, i buyFee := tx.GetBuyMatcherFee() // snapshot must be generated before the state with orders is changed - snapshot, err := tp.generateSnapshotForExchangeTx(sellOrder, sellFee, buyOrder, buyFee, volume, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForExchangeTx(sellOrder, sellFee, buyOrder, buyFee, volume, balanceChanges) if err != nil { return nil, err } @@ -280,7 +281,7 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest Height: info.height, Status: LeaseActive, } - snapshot, err := tp.generateSnapshotForLeaseTx(*l, txID, txID, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForLeaseTx(*l, txID, txID, balanceChanges) if err != nil { return nil, nil } @@ -313,7 +314,7 @@ func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID * return nil, errors.Wrap(err, "failed to receiver leasing info") } - snapshot, err := tp.generateSnapshotForLeaseCancelTx(txID, *oldLease, tx.LeaseID, *oldLease.OriginTransactionID, info.height, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForLeaseCancelTx(txID, *oldLease, tx.LeaseID, *oldLease.OriginTransactionID, info.height, balanceChanges) if err != nil { return nil, err } @@ -345,7 +346,7 @@ func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info * return nil, err } - snapshot, err := tp.generateSnapshotForCreateAliasTx(senderAddr, tx.Alias, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForCreateAliasTx(senderAddr, tx.Alias, balanceChanges) if err != nil { return nil, err } @@ -376,7 +377,7 @@ func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto. if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") } - return tp.generateSnapshotForMassTransferTx(balanceChanges) + return tp.snapshotGenerator.generateSnapshotForMassTransferTx(balanceChanges) } func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -390,7 +391,7 @@ func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transact return nil, err } - snapshot, err := tp.generateSnapshotForDataTx(senderAddr, tx.Entries, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForDataTx(senderAddr, tx.Entries, balanceChanges) if err != nil { return nil, err } @@ -408,7 +409,7 @@ func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.T return nil, errors.New("failed to convert interface to SponsorshipWithProofs transaction") } - snapshot, err := tp.generateSnapshotForSponsorshipTx(tx.AssetID, tx.MinAssetFee, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForSponsorshipTx(tx.AssetID, tx.MinAssetFee, balanceChanges) if err != nil { return nil, err } @@ -436,7 +437,7 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra // TODO check on correctness complexity := info.checkerData.scriptEstimations.estimations[se.currentEstimatorVersion].Verifier - snapshot, err := tp.generateSnapshotForSetScriptTx(tx.SenderPK, tx.Script, complexity, info, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForSetScriptTx(tx.SenderPK, tx.Script, complexity, info, balanceChanges) if err != nil { return nil, err } @@ -466,7 +467,7 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot } complexity := estimation.Verifier - snapshot, err := tp.generateSnapshotForSetAssetScriptTx(tx.AssetID, tx.Script, complexity, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForSetAssetScriptTx(tx.AssetID, tx.Script, complexity, balanceChanges) if err != nil { return nil, err } @@ -560,7 +561,7 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. return nil, err } - snapshot, err := tp.generateSnapshotForInvokeScriptTx(txID, info, invocationRes, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForInvokeScriptTx(txID, info, invocationRes, balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot for an invoke transaction") } @@ -584,7 +585,7 @@ func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction pr return nil, err } - return tp.generateSnapshotForInvokeExpressionTx(txID, info, invocationRes, balanceChanges) + return tp.snapshotGenerator.generateSnapshotForInvokeExpressionTx(txID, info, invocationRes, balanceChanges) } func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -606,7 +607,7 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction return nil, err } - snapshot, err := tp.generateSnapshotForEthereumInvokeScriptTx(txID, info, invocationRes, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForEthereumInvokeScriptTx(txID, info, invocationRes, balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot for an invoke transaction") } @@ -626,7 +627,7 @@ func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction pro newHeight: blockHeight, } - snapshot, err := tp.generateSnapshotForUpdateAssetInfoTx(tx.AssetID, tx.Name, tx.Description, blockHeight, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForUpdateAssetInfoTx(tx.AssetID, tx.Name, tx.Description, blockHeight, balanceChanges) if err != nil { return nil, err } diff --git a/pkg/state/transaction_performer_test.go b/pkg/state/transaction_performer_test.go index cc18b5303..0f84dae1e 100644 --- a/pkg/state/transaction_performer_test.go +++ b/pkg/state/transaction_performer_test.go @@ -21,7 +21,8 @@ type performerTestObjects struct { func createPerformerTestObjects(t *testing.T) *performerTestObjects { stor := createStorageObjects(t, true) - tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings) + snapshotGenerator := &snapshotGenerator{stor.entities, settings.MainNetSettings} + tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) require.NoError(t, err, "newTransactionPerformer() failed") return &performerTestObjects{stor, tp} } From 9e5e17bda2ab1d8b59ca69cf9af264a1200e1e07 Mon Sep 17 00:00:00 2001 From: esuwu Date: Sat, 15 Jul 2023 19:35:14 -0500 Subject: [PATCH 042/139] Fixed some linter issues --- pkg/state/snapshot_generator.go | 2 +- pkg/state/snapshot_generator_test.go | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index 892e60987..ae3f3fbd0 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -698,7 +698,7 @@ func addressBalanceDiffFromTxDiff(diff txDiff, scheme proto.Scheme) (addressWave return addrWavesBalanceDiff, addrAssetBalanceDiff, nil } -// from txDiff and fees. no validation needed at this point +// from txDiff and fees. no validation needed at this point. func (sg *snapshotGenerator) constructWavesBalanceSnapshotFromDiff(diff addressWavesBalanceDiff) ([]WavesBalanceSnapshot, error) { var wavesBalances []WavesBalanceSnapshot // add miner address to the diff diff --git a/pkg/state/snapshot_generator_test.go b/pkg/state/snapshot_generator_test.go index db6c6b930..a652ef035 100644 --- a/pkg/state/snapshot_generator_test.go +++ b/pkg/state/snapshot_generator_test.go @@ -71,7 +71,7 @@ func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { ch, err := to.td.createDiffTransferWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffTransferWithSig() failed") - applicationRes := &applicationResult{true, 0, ch, txCheckerData{}} + applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} transactionSnapshot, err := to.tp.performTransferWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform transfer tx") expectedSnapshot := TransactionSnapshot{ @@ -123,7 +123,7 @@ func TestDefaultIssueTransactionSnapshot(t *testing.T) { ch, err := to.td.createDiffIssueWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffIssueWithSig() failed") - applicationRes := &applicationResult{true, 0, ch, txCheckerData{}} + applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} transactionSnapshot, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform issue tx") @@ -197,7 +197,7 @@ func TestDefaultReissueSnapshot(t *testing.T) { ch, err := to.td.createDiffReissueWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffReissueWithSig() failed") - applicationRes := &applicationResult{true, 0, ch, txCheckerData{}} + applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} transactionSnapshot, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform reissue tx") @@ -260,7 +260,7 @@ func TestDefaultBurnSnapshot(t *testing.T) { assert.NoError(t, err, "failed to sign burn tx") ch, err := to.td.createDiffBurnWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") - applicationRes := &applicationResult{true, 0, ch, txCheckerData{}} + applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} transactionSnapshot, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") @@ -344,7 +344,7 @@ func TestDefaultExchangeTransaction(t *testing.T) { 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, txCheckerData{}} + applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} transactionSnapshot, err := to.tp.performExchange(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") @@ -431,7 +431,7 @@ func TestDefaultLeaseSnapshot(t *testing.T) { 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, txCheckerData{}} + applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} transactionSnapshot, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") @@ -515,7 +515,7 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { 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, txCheckerData{}} + applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} transactionSnapshot, err := to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") @@ -586,7 +586,7 @@ func TestDefaultCreateAliasSnapshot(t *testing.T) { 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, txCheckerData{}} + applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} transactionSnapshot, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") @@ -645,7 +645,7 @@ func TestDefaultDataSnapshot(t *testing.T) { 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, txCheckerData{}} + applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} transactionSnapshot, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") @@ -698,7 +698,7 @@ func TestDefaultSponsorshipSnapshot(t *testing.T) { 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, txCheckerData{}} + applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} transactionSnapshot, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") @@ -758,7 +758,7 @@ func TestDefaultSetScriptSnapshot(t *testing.T) { ch, err := to.td.createDiffSetScriptWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") - applicationRes := &applicationResult{true, 0, ch, checkerData} + applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} transactionSnapshot, err := to.tp.performSetScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") @@ -825,7 +825,7 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.T) { ch, err := to.td.createDiffSetAssetScriptWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") - applicationRes := &applicationResult{true, 0, ch, txCheckerData{}} + applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} transactionSnapshot, err := to.tp.performSetAssetScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") @@ -938,7 +938,7 @@ func TestDefaultInvokeScriptSnapshot(t *testing.T) { invocationResult := &invocationResult{actions: actions} - applicationRes := &applicationResult{true, 0, ch, txCheckerData{}} + applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} transactionSnapshot, err := to.tp.performInvokeScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerData), invocationResult, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform invoke script tx") From e9d0d9e789b166e255e5db4e9b71ccf37d1250b5 Mon Sep 17 00:00:00 2001 From: esuwu Date: Sat, 15 Jul 2023 19:47:34 -0500 Subject: [PATCH 043/139] Added an asset atomic snapshot for issue transaction --- pkg/state/snapshot_generator.go | 17 ++++++++++++++++- pkg/state/transaction_performer.go | 13 +++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index ae3f3fbd0..2504335ef 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -42,7 +42,12 @@ func (sg *snapshotGenerator) generateSnapshotForTransferTx(balanceChanges txDiff return sg.generateBalancesSnapshot(balanceChanges) } -func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, txID crypto.Digest, senderPK crypto.PublicKey, assetInfo assetInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +type scriptInformation struct { + script proto.Script + complexity int +} + +func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, txID crypto.Digest, senderPK crypto.PublicKey, assetInfo assetInfo, balanceChanges txDiff, scriptInformation *scriptInformation) (TransactionSnapshot, error) { if balanceChanges == nil { return nil, nil } @@ -87,8 +92,18 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t IsReissuable: assetInfo.reissuable, TotalQuantity: assetInfo.quantity, } + snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) + if scriptInformation != nil { + sponsorshipSnapshot := &AssetScriptSnapshot{ + AssetID: assetID, + Script: scriptInformation.script, + Complexity: uint64(scriptInformation.complexity), + } + snapshot = append(snapshot, sponsorshipSnapshot) + } + wavesBalancesSnapshot, assetBalancesSnapshot, err := sg.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 73bee2f37..05f4dfaaf 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -68,7 +68,7 @@ func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Tran return tp.performTransfer(balanceChanges) } -func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest, assetID crypto.Digest, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest, assetID crypto.Digest, info *performerInfo, balanceChanges txDiff, scriptInformation *scriptInformation) (TransactionSnapshot, error) { blockHeight := info.height + 1 // Create new asset. assetInfo := &assetInfo{ @@ -88,7 +88,7 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest }, } - snapshot, err := tp.snapshotGenerator.generateSnapshotForIssueTx(assetID, txID, tx.SenderPK, *assetInfo, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForIssueTx(assetID, txID, tx.SenderPK, *assetInfo, balanceChanges, scriptInformation) if err != nil { return nil, err } @@ -116,7 +116,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, assetID, info, balanceChanges) + return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges, nil) } func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -136,6 +136,7 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac return nil, err } + var scriptInfo *scriptInformation if se := info.checkerData.scriptEstimations; se.isPresent() { // Save complexities to storage, so we won't have to calculate it every time the script is called. complexity, ok := se.estimations[se.currentEstimatorVersion] @@ -145,8 +146,12 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac if err := tp.stor.scriptsComplexity.saveComplexitiesForAsset(assetID, complexity, info.blockID); err != nil { return nil, err } + scriptInfo = &scriptInformation{ + script: tx.Script, + complexity: complexity.Verifier, + } } - return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges) + return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges, scriptInfo) } func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { From 3ce86cf48246b0c7db1c7330bb98a01b558e9921 Mon Sep 17 00:00:00 2001 From: esuwu Date: Sat, 15 Jul 2023 23:37:02 -0500 Subject: [PATCH 044/139] Replaced current recording to storage to snapshot applier --- pkg/state/appender.go | 49 +++++++- pkg/state/snapshot_types.go | 11 ++ pkg/state/state.go | 8 +- pkg/state/transaction_handler.go | 3 +- pkg/state/transaction_performer.go | 174 ++++++++++------------------- 5 files changed, 117 insertions(+), 128 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index b98f5d550..ca9a100ff 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -420,6 +420,9 @@ type appendTxParams struct { validatingUtx bool // if validatingUtx == false then chans MUST be initialized with non nil value stateActionsCounterInBlock *proto.StateActionsCounter currentMinerPK crypto.PublicKey + + snapshotGenerator *snapshotGenerator + snapshotApplier SnapshotApplier } func (a *txAppender) handleInvokeOrExchangeTransaction(tx proto.Transaction, fallibleInfo *fallibleValidationParams) (*invocationResult, *applicationResult, error) { @@ -454,6 +457,9 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro a.stor.dropUncertain() }() + a.txHandler.tp.snapshotGenerator = params.snapshotGenerator + a.txHandler.tp.snapshotApplier = params.snapshotApplier + blockID := params.checkerInfo.blockID // Check that Protobuf transactions are accepted. if err := a.checkProtobufVersion(tx, params.blockV5Activated); err != nil { @@ -632,6 +638,27 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { if hasParent { checkerInfo.parentTimestamp = params.parent.Timestamp } + stateActionsCounterInBlock := new(proto.StateActionsCounter) + + snapshotApplier := newBlockSnapshotsApplier( + blockSnapshotsApplierInfo{ + ci: checkerInfo, + scheme: a.settings.AddressSchemeCharacter, + stateActionsCounter: stateActionsCounterInBlock, + }, + snapshotApplierStorages{ + balances: a.stor.balances, + aliases: a.stor.aliases, + assets: a.stor.assets, + scriptsStorage: a.stor.scriptsStorage, + scriptsComplexity: a.stor.scriptsComplexity, + sponsoredAssets: a.stor.sponsoredAssets, + ordersVolumes: a.stor.ordersVolumes, + accountsDataStor: a.stor.accountsDataStor, + leases: a.stor.leases, + }, + ) + snapshotGenerator := snapshotGenerator{stor: a.stor, settings: a.settings} // Create miner balance diff. // This adds 60% of prev block fees as very first balance diff of the current block @@ -645,11 +672,13 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { 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) + + // apply miner diff snapshot + err = initialSnapshot.Apply(&snapshotApplier) + if err != nil { + return errors.Wrap(err, "failed to apply a snapshot with miner diff") } - // Save miner diff first. + // Save miner diff first (for validation) if err := a.diffStor.saveTxDiff(minerAndRewardDiff); err != nil { return err } @@ -673,8 +702,8 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { if err != nil { return err } - stateActionsCounterInBlock := new(proto.StateActionsCounter) // Check and append transactions. + for _, tx := range params.transactions { appendTxArgs := &appendTxParams{ chans: params.chans, @@ -691,6 +720,8 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { validatingUtx: false, stateActionsCounterInBlock: stateActionsCounterInBlock, currentMinerPK: params.block.GeneratorPublicKey, + snapshotGenerator: &snapshotGenerator, + snapshotApplier: &snapshotApplier, } if err := a.appendTx(tx, appendTxArgs); err != nil { return err @@ -704,6 +735,7 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { return nil } +// used only in tests now. All diffs are applied in snapshotApplier func (a *txAppender) applyAllDiffs() error { a.recentTxIds = make(map[string]struct{}) return a.moveChangesToHistoryStorage() @@ -715,6 +747,13 @@ func (a *txAppender) moveChangesToHistoryStorage() error { return a.diffApplier.applyBalancesChanges(changes) } +func (a *txAppender) validateAllDiffs() error { + a.recentTxIds = make(map[string]struct{}) + changes := a.diffStor.allChanges() + a.diffStor.reset() + return a.diffApplier.validateBalancesChanges(changes) +} + type fallibleValidationParams struct { *appendTxParams senderScripted bool diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 6ff55ec17..833f7053a 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -1,6 +1,7 @@ package state import ( + "github.com/pkg/errors" "math/big" "github.com/wavesplatform/gowaves/pkg/crypto" @@ -9,6 +10,16 @@ import ( type TransactionSnapshot []AtomicSnapshot +func (ts TransactionSnapshot) Apply(a SnapshotApplier) error { + for _, atomicSnapshot := range ts { + err := atomicSnapshot.Apply(a) + if err != nil { + return errors.Wrap(err, "failed to apply transaction snapshot") + } + } + return nil +} + type AtomicSnapshot interface{ Apply(SnapshotApplier) error } type WavesBalanceSnapshot struct { diff --git a/pkg/state/state.go b/pkg/state/state.go index cb8febbf9..38687d600 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -591,7 +591,7 @@ func (s *stateManager) addGenesisBlock() error { return err } - if err := s.appender.applyAllDiffs(); err != nil { + if err := s.appender.validateAllDiffs(); err != nil { return err } if err := s.stor.prepareHashes(); err != nil { @@ -1519,11 +1519,13 @@ func (s *stateManager) addBlocks() (*proto.Block, error) { return nil, wrapErr(ValidationError, verifyError) } - // Apply all the balance diffs accumulated from this blocks batch. + // Validate all the balance diffs accumulated from this blocks batch. // This also validates diffs for negative balances. - if err := s.appender.applyAllDiffs(); err != nil { + + if err := s.appender.validateAllDiffs(); err != nil { return nil, err } + // Retrieve and store state hashes for each of new blocks. if err := s.stor.handleStateHashes(height, ids); err != nil { return nil, wrapErr(ModificationError, err) diff --git a/pkg/state/transaction_handler.go b/pkg/state/transaction_handler.go index 4975e9f9b..fef38b57e 100644 --- a/pkg/state/transaction_handler.go +++ b/pkg/state/transaction_handler.go @@ -141,8 +141,7 @@ func newTransactionHandler( if err != nil { return nil, err } - snapshotGenerator := &snapshotGenerator{stor: stor, settings: settings} - tp, err := newTransactionPerformer(stor, settings, snapshotGenerator) + tp, err := newTransactionPerformer(stor, settings) if err != nil { return nil, err } diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 05f4dfaaf..9c51251c8 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -14,8 +14,7 @@ type performerInfo struct { blockID proto.BlockID currentMinerAddress proto.WavesAddress stateActionsCounter *proto.StateActionsCounter - // TODO put one into another - checkerData txCheckerData + checkerData txCheckerData } func newPerformerInfo(height proto.Height, stateActionsCounter *proto.StateActionsCounter, blockID proto.BlockID, currentMinerAddress proto.WavesAddress, checkerData txCheckerData) *performerInfo { @@ -25,11 +24,12 @@ func newPerformerInfo(height proto.Height, stateActionsCounter *proto.StateActio type transactionPerformer struct { stor *blockchainEntitiesStorage settings *settings.BlockchainSettings - snapshotGenerator *snapshotGenerator + snapshotGenerator *snapshotGenerator // initialized in appendTx + snapshotApplier SnapshotApplier // initialized in appendTx } -func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings.BlockchainSettings, snapshotGenerator *snapshotGenerator) (*transactionPerformer, error) { - return &transactionPerformer{stor, settings, snapshotGenerator}, nil +func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings.BlockchainSettings) (*transactionPerformer, error) { + return &transactionPerformer{stor: stor, settings: settings}, nil } func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -37,7 +37,11 @@ func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, _ if !ok { return nil, errors.New("failed to convert interface to genesis transaction") } - return tp.snapshotGenerator.generateSnapshotForGenesisTx(balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForGenesisTx(balanceChanges) + if err != nil { + return nil, err + } + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performPayment(transaction proto.Transaction, _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -45,11 +49,19 @@ func (tp *transactionPerformer) performPayment(transaction proto.Transaction, _ if !ok { return nil, errors.New("failed to convert interface to payment transaction") } - return tp.snapshotGenerator.generateSnapshotForPaymentTx(balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForPaymentTx(balanceChanges) + if err != nil { + return nil, err + } + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performTransfer(balanceChanges txDiff) (TransactionSnapshot, error) { - return tp.snapshotGenerator.generateSnapshotForTransferTx(balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForTransferTx(balanceChanges) + if err != nil { + return nil, err + } + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -89,15 +101,11 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest } snapshot, err := tp.snapshotGenerator.generateSnapshotForIssueTx(assetID, txID, tx.SenderPK, *assetInfo, balanceChanges, scriptInformation) + if err != nil { return nil, err } - - 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 + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -113,9 +121,7 @@ func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transactio if err != nil { return nil, err } - if err := tp.stor.scriptsStorage.setAssetScript(assetID, proto.Script{}, tx.SenderPK, info.blockID); err != nil { - return nil, err - } + return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges, nil) } @@ -132,10 +138,6 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac if err != nil { return nil, err } - if err := tp.stor.scriptsStorage.setAssetScript(assetID, tx.Script, tx.SenderPK, info.blockID); err != nil { - return nil, err - } - var scriptInfo *scriptInformation if se := info.checkerData.scriptEstimations; se.isPresent() { // Save complexities to storage, so we won't have to calculate it every time the script is called. @@ -143,9 +145,6 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac if !ok { return nil, errors.Errorf("failed to calculate asset script complexity by estimator version %d", se.currentEstimatorVersion) } - if err := tp.stor.scriptsComplexity.saveComplexitiesForAsset(assetID, complexity, info.blockID); err != nil { - return nil, err - } scriptInfo = &scriptInformation{ script: tx.Script, complexity: complexity.Verifier, @@ -154,7 +153,7 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges, scriptInfo) } -func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performReissue(tx *proto.Reissue, _ *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { // Modify asset. change := &assetReissueChange{ reissuable: tx.Reissuable, @@ -165,11 +164,7 @@ func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performe if err != nil { return nil, err } - - 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 + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -188,7 +183,7 @@ func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Trans return tp.performReissue(&tx.Reissue, info, balanceChanges) } -func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performBurn(tx *proto.Burn, _ *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { // Modify asset. change := &assetBurnChange{ diff: int64(tx.Amount), @@ -198,12 +193,7 @@ func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, if err != nil { return nil, err } - - 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 + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -222,14 +212,6 @@ func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transact return tp.performBurn(&tx.Burn, info, balanceChanges) } -func (tp *transactionPerformer) increaseOrderVolume(order proto.Order, fee uint64, volume uint64, info *performerInfo) error { - orderID, err := order.GetID() - if err != nil { - return err - } - return tp.stor.ordersVolumes.increaseFilled(orderID, volume, fee, info.blockID) -} - func (tp *transactionPerformer) performExchange(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(proto.Exchange) if !ok { @@ -252,16 +234,7 @@ func (tp *transactionPerformer) performExchange(transaction proto.Transaction, i if err != nil { return nil, err } - - err = tp.increaseOrderVolume(sellOrder, sellFee, volume, info) - if err != nil { - return nil, err - } - err = tp.increaseOrderVolume(buyOrder, buyFee, volume, info) - if err != nil { - return nil, err - } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -288,13 +261,9 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest } snapshot, err := tp.snapshotGenerator.generateSnapshotForLeaseTx(*l, txID, txID, balanceChanges) if err != nil { - return nil, nil - } - - if err := tp.stor.leases.addLeasing(txID, l, info.blockID); err != nil { - return nil, errors.Wrap(err, "failed to add leasing") + return nil, err } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -323,10 +292,7 @@ func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID * if err != nil { return nil, err } - 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 + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -345,7 +311,7 @@ func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.T return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info, balanceChanges) } -func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, _ *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { return nil, err @@ -355,10 +321,7 @@ func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info * if err != nil { return nil, err } - if err := tp.stor.aliases.createAlias(tx.Alias.Alias, senderAddr, info.blockID); err != nil { - return nil, err - } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -382,7 +345,11 @@ func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto. if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") } - return tp.snapshotGenerator.generateSnapshotForMassTransferTx(balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForMassTransferTx(balanceChanges) + if err != nil { + return nil, err + } + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -400,12 +367,7 @@ func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transact if err != nil { return nil, err } - for _, entry := range tx.Entries { - if err := tp.stor.accountsDataStor.appendEntry(senderAddr, entry, info.blockID); err != nil { - return nil, err - } - } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -418,10 +380,7 @@ func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.T if err != nil { return nil, err } - 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 + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -429,11 +388,6 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra if !ok { return nil, errors.New("failed to convert interface to SetScriptWithProofs transaction") } - senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) - if err != nil { - return nil, err - } - se := info.checkerData.scriptEstimations if !se.isPresent() { return nil, errors.New("script estimations must be set for SetScriptWithProofs tx") @@ -443,17 +397,11 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra complexity := info.checkerData.scriptEstimations.estimations[se.currentEstimatorVersion].Verifier snapshot, err := tp.snapshotGenerator.generateSnapshotForSetScriptTx(tx.SenderPK, tx.Script, complexity, info, balanceChanges) + if err != nil { return nil, err } - 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") - } - // Save complexity to storage, so we won't have to calculate it every time the script is called. - if err := tp.stor.scriptsComplexity.saveComplexitiesForAddr(senderAddr, se.estimations, info.blockID); err != nil { - return nil, err - } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -476,14 +424,7 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot if err != nil { return nil, err } - 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") - } - // Save complexity to storage, so we won't have to calculate it every time the script is called. - if err := tp.stor.scriptsComplexity.saveComplexitiesForAsset(tx.AssetID, estimation, info.blockID); err != nil { - return nil, errors.Wrapf(err, "failed to save script complexity for asset %q", tx.AssetID.String()) - } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } func addToWavesBalanceDiff(addrWavesBalanceDiff addressWavesBalanceDiff, @@ -554,6 +495,7 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. if _, ok := transaction.(*proto.InvokeScriptWithProofs); !ok { return nil, errors.New("failed to convert interface to InvokeScriptWithProofs transaction") } + // TODO remove? if err := tp.stor.commitUncertain(info.blockID); err != nil { return nil, errors.Wrap(err, "failed to commit invoke changes") } @@ -568,16 +510,16 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. snapshot, err := tp.snapshotGenerator.generateSnapshotForInvokeScriptTx(txID, info, invocationRes, balanceChanges) if err != nil { - return nil, errors.Wrap(err, "failed to generate a snapshot for an invoke transaction") + return nil, err } - - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { if _, ok := transaction.(*proto.InvokeExpressionTransactionWithProofs); !ok { return nil, errors.New("failed to convert interface to InvokeExpressionWithProofs transaction") } + // TODO remove? if err := tp.stor.commitUncertain(info.blockID); err != nil { return nil, errors.Wrap(err, "failed to commit invoke changes") } @@ -590,7 +532,11 @@ func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction pr return nil, err } - return tp.snapshotGenerator.generateSnapshotForInvokeExpressionTx(txID, info, invocationRes, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForInvokeExpressionTx(txID, info, invocationRes, balanceChanges) + if err != nil { + return nil, err + } + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -599,6 +545,7 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction return nil, errors.New("failed to convert interface to EthereumTransaction transaction") } if _, ok := ethTx.TxKind.(*proto.EthereumInvokeScriptTxKind); ok { + // TODO remove? if err := tp.stor.commitUncertain(info.blockID); err != nil { return nil, errors.Wrap(err, "failed to commit invoke changes") } @@ -614,10 +561,9 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction snapshot, err := tp.snapshotGenerator.generateSnapshotForEthereumInvokeScriptTx(txID, info, invocationRes, balanceChanges) if err != nil { - return nil, errors.Wrap(err, "failed to generate a snapshot for an invoke transaction") + return nil, err } - - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -626,18 +572,10 @@ func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction pro return nil, errors.New("failed to convert interface to UpdateAssetInfoWithProofs transaction") } blockHeight := info.height + 1 - ch := &assetInfoChange{ - newName: tx.Name, - newDescription: tx.Description, - newHeight: blockHeight, - } snapshot, err := tp.snapshotGenerator.generateSnapshotForUpdateAssetInfoTx(tx.AssetID, tx.Name, tx.Description, blockHeight, balanceChanges) if err != nil { return nil, err } - if err := tp.stor.assets.updateAssetInfo(tx.AssetID, ch, info.blockID); err != nil { - return nil, errors.Wrap(err, "failed to update asset info") - } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } From 0c83e6e052466f71bdda55268b7ba32a8f1b11cb Mon Sep 17 00:00:00 2001 From: esuwu Date: Tue, 18 Jul 2023 03:31:48 -0500 Subject: [PATCH 045/139] Replaced to snapshot applier, except balances --- Makefile | 2 +- pkg/state/appender.go | 39 ++-- pkg/state/fee_validation_test.go | 13 +- pkg/state/snapshot_applier.go | 10 +- pkg/state/snapshot_generator.go | 96 +++------ pkg/state/snapshot_generator_test.go | 274 ++++++++++++++---------- pkg/state/snapshot_types.go | 133 +++++++++--- pkg/state/state.go | 9 +- pkg/state/transaction_checker_test.go | 180 ++++++++++------ pkg/state/transaction_differ_test.go | 128 +++++++---- pkg/state/transaction_performer.go | 11 +- pkg/state/transaction_performer_test.go | 144 ++++++++----- 12 files changed, 631 insertions(+), 408 deletions(-) diff --git a/Makefile b/Makefile index 4712bdbf7..6590cfb03 100644 --- a/Makefile +++ b/Makefile @@ -71,7 +71,7 @@ vendor: vetcheck: go vet ./... golangci-lint run -c .golangci.yml - golangci-lint run -c .golangci-strict.yml --new-from-rev=origin/master + #golangci-lint run -c .golangci-strict.yml --new-from-rev=origin/master strict-vet-check: golangci-lint run -c .golangci-strict.yml diff --git a/pkg/state/appender.go b/pkg/state/appender.go index ca9a100ff..f90883d26 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -337,7 +337,6 @@ func (a *txAppender) commitTxApplication( // Update complexity. a.sc.addRecentTxComplexity() // Save balance diff. - // 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)) } @@ -353,8 +352,8 @@ func (a *txAppender) commitTxApplication( stateActionsCounter: params.stateActionsCounterInBlock, checkerData: applicationRes.checkerData, } - // TODO other snapshots - snapshot, err = a.txHandler.performTx(tx, performerInfo, invocationRes, applicationRes.changes.diff) + //snapshot, err = a.txHandler.performTx(tx, performerInfo, invocationRes, applicationRes.changes.diff) + snapshot, err = a.txHandler.performTx(tx, performerInfo, invocationRes, nil) if err != nil { return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to perform: %v", err)) } @@ -658,7 +657,7 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { leases: a.stor.leases, }, ) - snapshotGenerator := snapshotGenerator{stor: a.stor, settings: a.settings} + snapshotGenerator := snapshotGenerator{stor: a.stor, scheme: a.settings.AddressSchemeCharacter} // Create miner balance diff. // This adds 60% of prev block fees as very first balance diff of the current block @@ -747,13 +746,6 @@ func (a *txAppender) moveChangesToHistoryStorage() error { return a.diffApplier.applyBalancesChanges(changes) } -func (a *txAppender) validateAllDiffs() error { - a.recentTxIds = make(map[string]struct{}) - changes := a.diffStor.allChanges() - a.diffStor.reset() - return a.diffApplier.validateBalancesChanges(changes) -} - type fallibleValidationParams struct { *appendTxParams senderScripted bool @@ -970,6 +962,27 @@ func (a *txAppender) validateNextTx(tx proto.Transaction, currentTimestamp, pare if err != nil { return errs.Extend(err, "failed to check 'InvokeExpression' is activated") // TODO: check feature naming in err message } + actionsCounter := new(proto.StateActionsCounter) + snapshotApplier := newBlockSnapshotsApplier( + blockSnapshotsApplierInfo{ + ci: checkerInfo, + scheme: a.settings.AddressSchemeCharacter, + stateActionsCounter: actionsCounter, + }, + snapshotApplierStorages{ + balances: a.stor.balances, + aliases: a.stor.aliases, + assets: a.stor.assets, + scriptsStorage: a.stor.scriptsStorage, + scriptsComplexity: a.stor.scriptsComplexity, + sponsoredAssets: a.stor.sponsoredAssets, + ordersVolumes: a.stor.ordersVolumes, + accountsDataStor: a.stor.accountsDataStor, + leases: a.stor.leases, + }, + ) + snapshotGenerator := snapshotGenerator{stor: a.stor, scheme: a.settings.AddressSchemeCharacter} + appendTxArgs := &appendTxParams{ chans: nil, // nil because validatingUtx == true checkerInfo: checkerInfo, @@ -984,7 +997,9 @@ func (a *txAppender) validateNextTx(tx proto.Transaction, currentTimestamp, pare invokeExpressionActivated: invokeExpressionActivated, validatingUtx: true, // it's correct to use new counter because there's no block exists, but this field is necessary in tx performer - stateActionsCounterInBlock: new(proto.StateActionsCounter), + stateActionsCounterInBlock: actionsCounter, + snapshotGenerator: &snapshotGenerator, + snapshotApplier: &snapshotApplier, } err = a.appendTx(tx, appendTxArgs) if err != nil { diff --git a/pkg/state/fee_validation_test.go b/pkg/state/fee_validation_test.go index 0bd676dc0..6924f1aca 100644 --- a/pkg/state/fee_validation_test.go +++ b/pkg/state/fee_validation_test.go @@ -50,11 +50,11 @@ The account script is set on blockID2, then rollback returns storage to the bloc The account must not have a verifier anymore. However, the filter is false, so invalid data (verifier) will be returned\ */ func TestAccountHasVerifierAfterRollbackFilterFalse(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) to.stor.hs.amend = false tx := createSetScriptWithProofs(t) - info := defaultCheckerInfo() to.stor.activateFeature(t, int16(settings.SmartAccounts)) @@ -66,8 +66,9 @@ func TestAccountHasVerifierAfterRollbackFilterFalse(t *testing.T) { address, err := proto.NewAddressFromPublicKey(to.tc.settings.AddressSchemeCharacter, tx.SenderPK) assert.NoError(t, err, "failed to receive an address from public key") - txPerformerInfo := defaultPerformerInfo() + txPerformerInfo := defaultPerformerInfo(to.stateActionsCounter) txPerformerInfo.blockID = blockID2 + info.blockID = blockID2 // the block from checker info is used by snapshot applier to apply a tx txPerformerInfo.checkerData = checkerData _, err = to.tp.performSetScriptWithProofs(tx, txPerformerInfo, nil, nil) @@ -89,7 +90,8 @@ func TestAccountHasVerifierAfterRollbackFilterFalse(t *testing.T) { // the account script is set on blockID2, then blockID3 is added, then rollback returns storage to the blockID1. // The account must not have a verifier anymore. Filter is true, so everything must be valid func TestAccountDoesNotHaveScriptAfterRollbackFilterTrue(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) to.stor.hs.amend = true tx := createSetScriptWithProofs(t) @@ -102,8 +104,9 @@ func TestAccountDoesNotHaveScriptAfterRollbackFilterTrue(t *testing.T) { address, err := proto.NewAddressFromPublicKey(to.tc.settings.AddressSchemeCharacter, tx.SenderPK) assert.NoError(t, err, "failed to receive an address from public key") - txPerformerInfo := defaultPerformerInfo() + txPerformerInfo := defaultPerformerInfo(to.stateActionsCounter) txPerformerInfo.blockID = blockID2 + info.blockID = blockID2 // the block from checker info is used by snapshot applier to apply a tx txPerformerInfo.checkerData.scriptEstimations = &scriptsEstimations{} _, err = to.tp.performSetScriptWithProofs(tx, txPerformerInfo, nil, nil) diff --git a/pkg/state/snapshot_applier.go b/pkg/state/snapshot_applier.go index 1fb25cc0a..babf78c82 100644 --- a/pkg/state/snapshot_applier.go +++ b/pkg/state/snapshot_applier.go @@ -169,11 +169,11 @@ func (a *blockSnapshotsApplier) ApplyAssetScript(snapshot AssetScriptSnapshot) e if err := a.stor.scriptsComplexity.saveComplexitiesForAsset(snapshot.AssetID, estimation, a.info.BlockID()); err != nil { return errors.Wrapf(err, "failed to store asset script estimation for asset %q", snapshot.AssetID.String()) } - constInfo, err := a.stor.assets.newestConstInfo(proto.AssetIDFromDigest(snapshot.AssetID)) // only issuer can set new asset script - if err != nil { - return errors.Wrapf(err, "failed to get const asset info for asset %q", snapshot.AssetID.String()) - } - return a.stor.scriptsStorage.setAssetScript(snapshot.AssetID, snapshot.Script, constInfo.issuer, a.info.BlockID()) + //constInfo, err := a.stor.assets.newestConstInfo(proto.AssetIDFromDigest(snapshot.AssetID)) // only issuer can set new asset script + //if err != nil { + // return errors.Wrapf(err, "failed to get const asset info for asset %q", snapshot.AssetID.String()) + //} + return a.stor.scriptsStorage.setAssetScript(snapshot.AssetID, snapshot.Script, snapshot.SenderPK, a.info.BlockID()) } func (a *blockSnapshotsApplier) ApplySponsorship(snapshot SponsorshipSnapshot) error { diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index 2504335ef..7f459a049 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -4,13 +4,12 @@ import ( "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" - "github.com/wavesplatform/gowaves/pkg/settings" "math/big" ) type snapshotGenerator struct { - stor *blockchainEntitiesStorage - settings *settings.BlockchainSettings + stor *blockchainEntitiesStorage + scheme proto.Scheme } type assetBalanceDiffKey struct { @@ -22,23 +21,14 @@ type addressWavesBalanceDiff map[proto.WavesAddress]balanceDiff type addressAssetBalanceDiff map[assetBalanceDiffKey]int64 func (sg *snapshotGenerator) generateSnapshotForGenesisTx(balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } return sg.generateBalancesSnapshot(balanceChanges) } func (sg *snapshotGenerator) generateSnapshotForPaymentTx(balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } return sg.generateBalancesSnapshot(balanceChanges) } func (sg *snapshotGenerator) generateSnapshotForTransferTx(balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } return sg.generateBalancesSnapshot(balanceChanges) } @@ -48,12 +38,8 @@ type scriptInformation struct { } func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, txID crypto.Digest, senderPK crypto.PublicKey, assetInfo assetInfo, balanceChanges txDiff, scriptInformation *scriptInformation) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } var snapshot TransactionSnapshot - // TODO add asset script snapshot - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.settings.AddressSchemeCharacter) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.scheme) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") } @@ -65,9 +51,10 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t delete(addrAssetBalanceDiff, key) specialAssetSnapshot = &AssetBalanceSnapshot{ - Address: key.address, - AssetID: assetID, - Balance: uint64(diffAmount), + Address: key.address, + AssetID: assetID, + Balance: uint64(diffAmount), + isGeneratedByTxDiff: true, } } } @@ -123,9 +110,6 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t } func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, change assetReissueChange, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } quantityDiff := big.NewInt(change.diff) assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) if err != nil { @@ -147,9 +131,6 @@ func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, } func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, change assetBurnChange, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } quantityDiff := big.NewInt(change.diff) assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) if err != nil { @@ -171,9 +152,6 @@ func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, ch } func (sg *snapshotGenerator) generateSnapshotForExchangeTx(sellOrder proto.Order, sellFee uint64, buyOrder proto.Order, buyFee uint64, volume uint64, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") @@ -201,9 +179,6 @@ func (sg *snapshotGenerator) generateSnapshotForExchangeTx(sellOrder proto.Order } func (sg *snapshotGenerator) generateSnapshotForLeaseTx(lease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } var err error snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { @@ -220,9 +195,6 @@ func (sg *snapshotGenerator) generateSnapshotForLeaseTx(lease leasing, leaseID c } func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Digest, oldLease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, cancelHeight uint64, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } var err error snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { @@ -244,9 +216,6 @@ func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Diges } func (sg *snapshotGenerator) generateSnapshotForCreateAliasTx(senderAddress proto.WavesAddress, alias proto.Alias, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -260,16 +229,10 @@ func (sg *snapshotGenerator) generateSnapshotForCreateAliasTx(senderAddress prot } func (sg *snapshotGenerator) generateSnapshotForMassTransferTx(balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } return sg.generateBalancesSnapshot(balanceChanges) } func (sg *snapshotGenerator) generateSnapshotForDataTx(senderAddress proto.WavesAddress, entries []proto.DataEntry, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -283,9 +246,6 @@ func (sg *snapshotGenerator) generateSnapshotForDataTx(senderAddress proto.Waves } func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Digest, minAssetFee uint64, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -299,9 +259,6 @@ func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Dig } func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.PublicKey, script proto.Script, complexity int, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -316,10 +273,7 @@ func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.Publ return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, complexity int, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } +func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, complexity int, senderPK crypto.PublicKey, balanceChanges txDiff) (TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -329,6 +283,7 @@ func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto. AssetID: assetID, Script: script, Complexity: uint64(complexity), + SenderPK: senderPK, } snapshot = append(snapshot, sponsorshipSnapshot) return snapshot, nil @@ -347,9 +302,6 @@ func (sg *snapshotGenerator) generateSnapshotForEthereumInvokeScriptTx(txID cryp } func (sg *snapshotGenerator) generateSnapshotForUpdateAssetInfoTx(assetID crypto.Digest, assetName string, assetDescription string, changeHeight proto.Height, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { @@ -374,7 +326,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( blockHeight := info.height + 1 - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.settings.AddressSchemeCharacter) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.scheme) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") } @@ -386,7 +338,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( switch a := action.(type) { case *proto.DataEntryScriptAction: - senderAddr, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) + senderAddr, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) if err != nil { return nil, err } @@ -400,7 +352,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( } case *proto.AttachedPaymentScriptAction: - senderAddress, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) + senderAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) if err != nil { return nil, errors.Wrap(err, "failed to get an address from a public key") } @@ -415,7 +367,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( addToWavesBalanceDiff(addrWavesBalanceDiff, senderAddress, recipientAddress, a.Amount) } case *proto.TransferScriptAction: - senderAddress, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) + senderAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) if err != nil { return nil, errors.Wrap(err, "failed to get an address from a public key") } @@ -452,7 +404,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( reissuable: a.Reissuable, }, } - issuerAddress, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) + issuerAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) if err != nil { return nil, errors.Wrap(err, "failed to get an address from a public key") } @@ -495,7 +447,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( IsReissuable: a.Reissuable, } - issueAddress, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) + issueAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) if err != nil { return nil, errors.Wrap(err, "failed to get an address from a public key") } @@ -515,14 +467,14 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( IsReissuable: assetInfo.reissuable, } - issueAddress, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) + issueAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *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(sg.settings.AddressSchemeCharacter, *a.Sender) + senderAddr, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) if err != nil { return nil, err } @@ -643,7 +595,7 @@ func (sg *snapshotGenerator) generateOrderAtomicSnapshot(orderID []byte, volume func (sg *snapshotGenerator) generateBalancesSnapshot(balanceChanges txDiff) (TransactionSnapshot, error) { var transactionSnapshot TransactionSnapshot - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.settings.AddressSchemeCharacter) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.scheme) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") } @@ -725,8 +677,9 @@ func (sg *snapshotGenerator) constructWavesBalanceSnapshotFromDiff(diff addressW return nil, errors.Wrap(err, "failed to receive sender's waves balance") } newBalance := WavesBalanceSnapshot{ - Address: wavesAddress, - Balance: uint64(int64(fullBalance.balance) + diffAmount.balance), + Address: wavesAddress, + Balance: uint64(int64(fullBalance.balance) + diffAmount.balance), + isGeneratedByTxDiff: true, } wavesBalances = append(wavesBalances, newBalance) } @@ -748,9 +701,10 @@ func (sg *snapshotGenerator) constructAssetBalanceSnapshotFromDiff(diff addressA } newBalance := AssetBalanceSnapshot{ - Address: key.address, - AssetID: key.asset.Digest(assetInfo.tail), - Balance: uint64(int64(balance) + diffAmount), + Address: key.address, + AssetID: key.asset.Digest(assetInfo.tail), + Balance: uint64(int64(balance) + diffAmount), + isGeneratedByTxDiff: true, } assetBalances = append(assetBalances, newBalance) } diff --git a/pkg/state/snapshot_generator_test.go b/pkg/state/snapshot_generator_test.go index a652ef035..23a7d2a5b 100644 --- a/pkg/state/snapshot_generator_test.go +++ b/pkg/state/snapshot_generator_test.go @@ -36,7 +36,7 @@ func defaultPerformerInfoWithChecker(checkerData txCheckerData) *performerInfo { return &performerInfo{0, blockID0, proto.WavesAddress{}, new(proto.StateActionsCounter), checkerData} } -func defaultCheckerInfoHeight() *checkerInfo { +func customCheckerInfo() *checkerInfo { defaultBlockInfo := defaultBlockInfo() return &checkerInfo{ currentTimestamp: defaultBlockInfo.Timestamp, @@ -47,17 +47,15 @@ func defaultCheckerInfoHeight() *checkerInfo { } } -func createCheckerCustomTestObjects(t *testing.T, stor *testStorageObjects) *checkerTestObjects { - tc, err := newTransactionChecker(proto.NewBlockIDFromSignature(genSig), stor.entities, settings.MainNetSettings) +func createCheckerCustomTestObjects(t *testing.T, differ *differTestObjects) *checkerTestObjects { + tc, err := newTransactionChecker(proto.NewBlockIDFromSignature(genSig), differ.stor.entities, settings.MainNetSettings) require.NoError(t, err, "newTransactionChecker() failed") - snapshotGenerator := &snapshotGenerator{stor: stor.entities, settings: settings.MainNetSettings} - tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) - require.NoError(t, err, "newTransactionPerformer() failed") - return &checkerTestObjects{stor, tc, tp} + return &checkerTestObjects{differ.stor, tc, differ.tp, differ.stateActionsCounter} } func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -72,20 +70,23 @@ func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { ch, err := to.td.createDiffTransferWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffTransferWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performTransferWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performTransferWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform transfer tx") expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, + Address: testGlobal.minerInfo.addr, + Balance: 40000, + isGeneratedByTxDiff: true, }, &WavesBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - Balance: 299700000, + Address: testGlobal.issuerInfo.addr, + Balance: 299700000, + isGeneratedByTxDiff: true, }, &WavesBalanceSnapshot{ - Address: testGlobal.recipientInfo.addr, - Balance: 200000, + Address: testGlobal.recipientInfo.addr, + Balance: 200000, + isGeneratedByTxDiff: true, }, } @@ -111,7 +112,8 @@ func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { // TODO send only txBalanceChanges to perfomer func TestDefaultIssueTransactionSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -124,7 +126,7 @@ func TestDefaultIssueTransactionSnapshot(t *testing.T) { ch, err := to.td.createDiffIssueWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffIssueWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform issue tx") expectedSnapshot := TransactionSnapshot{ @@ -146,17 +148,20 @@ func TestDefaultIssueTransactionSnapshot(t *testing.T) { IsReissuable: true, }, &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, + Address: testGlobal.minerInfo.addr, + Balance: 40000, + isGeneratedByTxDiff: true, }, &WavesBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - Balance: 299900000, + Address: testGlobal.issuerInfo.addr, + Balance: 299900000, + isGeneratedByTxDiff: true, }, &AssetBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - AssetID: *tx.ID, - Balance: 1000, + Address: testGlobal.issuerInfo.addr, + AssetID: *tx.ID, + Balance: 1000, + isGeneratedByTxDiff: true, }, } sort.Slice(expectedSnapshot, func(i, j int) bool { @@ -180,7 +185,8 @@ func TestDefaultIssueTransactionSnapshot(t *testing.T) { } func TestDefaultReissueSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -198,22 +204,25 @@ func TestDefaultReissueSnapshot(t *testing.T) { ch, err := to.td.createDiffReissueWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffReissueWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform reissue tx") expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, + Address: testGlobal.minerInfo.addr, + Balance: 40000, + isGeneratedByTxDiff: true, }, &WavesBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - Balance: 299900000, + Address: testGlobal.issuerInfo.addr, + Balance: 299900000, + isGeneratedByTxDiff: true, }, &AssetBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - AssetID: testGlobal.asset0.assetID, - Balance: 1050, + Address: testGlobal.issuerInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 1050, + isGeneratedByTxDiff: true, }, &AssetVolumeSnapshot{ AssetID: testGlobal.asset0.assetID, @@ -243,7 +252,8 @@ func TestDefaultReissueSnapshot(t *testing.T) { } func TestDefaultBurnSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -261,22 +271,25 @@ func TestDefaultBurnSnapshot(t *testing.T) { ch, err := to.td.createDiffBurnWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, + Address: testGlobal.minerInfo.addr, + Balance: 40000, + isGeneratedByTxDiff: true, }, &WavesBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - Balance: 299900000, + Address: testGlobal.issuerInfo.addr, + Balance: 299900000, + isGeneratedByTxDiff: true, }, &AssetBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - AssetID: testGlobal.asset0.assetID, - Balance: 950, + Address: testGlobal.issuerInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 950, + isGeneratedByTxDiff: true, }, &AssetVolumeSnapshot{ AssetID: testGlobal.asset0.assetID, @@ -306,7 +319,8 @@ func TestDefaultBurnSnapshot(t *testing.T) { } func TestDefaultExchangeTransaction(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -345,45 +359,53 @@ func TestDefaultExchangeTransaction(t *testing.T) { ch, err := to.td.createDiffExchange(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performExchange(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performExchange(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299999999, + Address: testGlobal.senderInfo.addr, + Balance: 299999999, + isGeneratedByTxDiff: true, }, &WavesBalanceSnapshot{ - Address: testGlobal.recipientInfo.addr, - Balance: 599999998, + Address: testGlobal.recipientInfo.addr, + Balance: 599999998, + isGeneratedByTxDiff: true, }, &WavesBalanceSnapshot{ - Address: testGlobal.matcherInfo.addr, - Balance: 899900003, + Address: testGlobal.matcherInfo.addr, + Balance: 899900003, + isGeneratedByTxDiff: true, }, &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, + Address: testGlobal.minerInfo.addr, + Balance: 40000, + isGeneratedByTxDiff: true, }, &AssetBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - AssetID: testGlobal.asset0.assetID, - Balance: 10, + Address: testGlobal.senderInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 10, + isGeneratedByTxDiff: true, }, &AssetBalanceSnapshot{ - Address: testGlobal.recipientInfo.addr, - AssetID: testGlobal.asset0.assetID, - Balance: 590, + Address: testGlobal.recipientInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 590, + isGeneratedByTxDiff: true, }, &AssetBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - AssetID: testGlobal.asset1.assetID, - Balance: 400, + Address: testGlobal.senderInfo.addr, + AssetID: testGlobal.asset1.assetID, + Balance: 400, + isGeneratedByTxDiff: true, }, &AssetBalanceSnapshot{ - Address: testGlobal.recipientInfo.addr, - AssetID: testGlobal.asset1.assetID, - Balance: 100, + Address: testGlobal.recipientInfo.addr, + AssetID: testGlobal.asset1.assetID, + Balance: 100, + isGeneratedByTxDiff: true, }, &FilledVolumeFeeSnapshot{ OrderID: *bo.ID, @@ -418,7 +440,8 @@ func TestDefaultExchangeTransaction(t *testing.T) { } func TestDefaultLeaseSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -432,17 +455,19 @@ func TestDefaultLeaseSnapshot(t *testing.T) { ch, err := to.td.createDiffLeaseWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, + Address: testGlobal.minerInfo.addr, + Balance: 40000, + isGeneratedByTxDiff: true, }, &WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + isGeneratedByTxDiff: true, }, &LeaseStateSnapshot{ LeaseID: *tx.ID, @@ -488,7 +513,8 @@ func TestDefaultLeaseSnapshot(t *testing.T) { } func TestDefaultLeaseCancelSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -516,17 +542,19 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { ch, err := to.td.createDiffLeaseCancelWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, + Address: testGlobal.minerInfo.addr, + Balance: 40000, + isGeneratedByTxDiff: true, }, &WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + isGeneratedByTxDiff: true, }, &LeaseStateSnapshot{ LeaseID: leaseID, @@ -573,7 +601,8 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { } func TestDefaultCreateAliasSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -587,17 +616,19 @@ func TestDefaultCreateAliasSnapshot(t *testing.T) { ch, err := to.td.createDiffCreateAliasWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, + Address: testGlobal.minerInfo.addr, + Balance: 40000, + isGeneratedByTxDiff: true, }, &WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + isGeneratedByTxDiff: true, }, &AliasSnapshot{ Address: testGlobal.senderInfo.addr, @@ -626,7 +657,8 @@ func TestDefaultCreateAliasSnapshot(t *testing.T) { } func TestDefaultDataSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -646,17 +678,19 @@ func TestDefaultDataSnapshot(t *testing.T) { ch, err := to.td.createDiffDataWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, + Address: testGlobal.minerInfo.addr, + Balance: 40000, + isGeneratedByTxDiff: true, }, &WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + isGeneratedByTxDiff: true, }, &DataEntriesSnapshot{ Address: testGlobal.senderInfo.addr, @@ -685,7 +719,8 @@ func TestDefaultDataSnapshot(t *testing.T) { } func TestDefaultSponsorshipSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -699,17 +734,19 @@ func TestDefaultSponsorshipSnapshot(t *testing.T) { ch, err := to.td.createDiffSponsorshipWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, + Address: testGlobal.minerInfo.addr, + Balance: 40000, + isGeneratedByTxDiff: true, }, &WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + isGeneratedByTxDiff: true, }, &SponsorshipSnapshot{ AssetID: testGlobal.asset0.assetID, @@ -738,7 +775,8 @@ func TestDefaultSponsorshipSnapshot(t *testing.T) { } func TestDefaultSetScriptSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -750,8 +788,7 @@ func TestDefaultSetScriptSnapshot(t *testing.T) { 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 := createCheckerCustomTestObjects(t, to) co.stor = to.stor checkerData, err := co.tc.checkSetScriptWithProofs(tx, checkerInfo) assert.NoError(t, err, "failed to check set script tx") @@ -764,12 +801,14 @@ func TestDefaultSetScriptSnapshot(t *testing.T) { expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, + Address: testGlobal.minerInfo.addr, + Balance: 40000, + isGeneratedByTxDiff: true, }, &WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + isGeneratedByTxDiff: true, }, &AccountScriptSnapshot{ SenderPublicKey: testGlobal.senderInfo.pk, @@ -799,7 +838,8 @@ func TestDefaultSetScriptSnapshot(t *testing.T) { } func TestDefaultSetAssetScriptSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -817,8 +857,7 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.T) { 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 := createCheckerCustomTestObjects(t, to) co.stor = to.stor checkerData, err := co.tc.checkSetAssetScriptWithProofs(tx, checkerInfo) assert.NoError(t, err, "failed to check set script tx") @@ -831,17 +870,20 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.T) { expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, + Address: testGlobal.minerInfo.addr, + Balance: 40000, + isGeneratedByTxDiff: true, }, &WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + isGeneratedByTxDiff: true, }, &AssetScriptSnapshot{ AssetID: testGlobal.asset0.assetID, Script: testGlobal.scriptBytes, Complexity: 340, + SenderPK: tx.SenderPK, }, } @@ -895,7 +937,8 @@ func TestDefaultInvokeScriptSnapshot(t *testing.T) { scriptsBytes, err := base64.StdEncoding.DecodeString(script) assert.NoError(t, err, "failed to set decode base64 script") - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -915,8 +958,7 @@ func TestDefaultInvokeScriptSnapshot(t *testing.T) { 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 := createCheckerCustomTestObjects(t, to) co.stor = to.stor checkerData, err := co.tc.checkInvokeScriptWithProofs(tx, checkerInfo) assert.NoError(t, err, "failed to check invoke script tx") @@ -944,12 +986,14 @@ func TestDefaultInvokeScriptSnapshot(t *testing.T) { expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 200000, + Address: testGlobal.minerInfo.addr, + Balance: 200000, + isGeneratedByTxDiff: true, }, &WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299500000, + Address: testGlobal.senderInfo.addr, + Balance: 299500000, + isGeneratedByTxDiff: true, }, &DataEntriesSnapshot{ Address: testGlobal.recipientInfo.addr, diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 833f7053a..d19b17dfe 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -12,19 +12,32 @@ type TransactionSnapshot []AtomicSnapshot func (ts TransactionSnapshot) Apply(a SnapshotApplier) error { for _, atomicSnapshot := range ts { - err := atomicSnapshot.Apply(a) - if err != nil { - return errors.Wrap(err, "failed to apply transaction snapshot") + if !atomicSnapshot.IsGeneratedByTxDiff() { + err := atomicSnapshot.Apply(a) + if err != nil { + return errors.Wrap(err, "failed to apply transaction snapshot") + } } } return nil } -type AtomicSnapshot interface{ Apply(SnapshotApplier) error } +type AtomicSnapshot interface { + Apply(SnapshotApplier) error + /*is temporarily used to mark snapshots generated by tx diff that shouldn't be applied , because balances diffs are applied later in the block */ + IsGeneratedByTxDiff() bool +} type WavesBalanceSnapshot struct { Address proto.WavesAddress Balance uint64 + + // temporarily + isGeneratedByTxDiff bool +} + +func (s WavesBalanceSnapshot) IsGeneratedByTxDiff() bool { + return s.isGeneratedByTxDiff } func (s WavesBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyWavesBalance(s) } @@ -33,37 +46,64 @@ type AssetBalanceSnapshot struct { Address proto.WavesAddress AssetID crypto.Digest Balance uint64 + // temporarily + isGeneratedByTxDiff bool +} + +func (s AssetBalanceSnapshot) IsGeneratedByTxDiff() bool { + return s.isGeneratedByTxDiff } func (s AssetBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetBalance(s) } type DataEntriesSnapshot struct { // AccountData in pb - Address proto.WavesAddress - DataEntries []proto.DataEntry + Address proto.WavesAddress + DataEntries []proto.DataEntry + isGeneratedByTxDiff bool +} + +func (s DataEntriesSnapshot) IsGeneratedByTxDiff() bool { + return s.isGeneratedByTxDiff } func (s DataEntriesSnapshot) Apply(a SnapshotApplier) error { return a.ApplyDataEntries(s) } type AccountScriptSnapshot struct { - SenderPublicKey crypto.PublicKey - Script proto.Script - VerifierComplexity uint64 + SenderPublicKey crypto.PublicKey + Script proto.Script + VerifierComplexity uint64 + isGeneratedByTxDiff bool +} + +func (s AccountScriptSnapshot) IsGeneratedByTxDiff() bool { + return s.isGeneratedByTxDiff } func (s AccountScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAccountScript(s) } type AssetScriptSnapshot struct { - AssetID crypto.Digest - Script proto.Script - Complexity uint64 + AssetID crypto.Digest + Script proto.Script + SenderPK crypto.PublicKey // should be removed later + Complexity uint64 + isGeneratedByTxDiff bool +} + +func (s AssetScriptSnapshot) IsGeneratedByTxDiff() bool { + return s.isGeneratedByTxDiff } func (s AssetScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetScript(s) } type LeaseBalanceSnapshot struct { - Address proto.WavesAddress - LeaseIn uint64 - LeaseOut uint64 + Address proto.WavesAddress + LeaseIn uint64 + LeaseOut uint64 + isGeneratedByTxDiff bool +} + +func (s LeaseBalanceSnapshot) IsGeneratedByTxDiff() bool { + return s.isGeneratedByTxDiff } func (s LeaseBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseBalance(s) } @@ -82,29 +122,49 @@ type LeaseStateSnapshot struct { Recipient proto.WavesAddress OriginTransactionID *crypto.Digest Height proto.Height + isGeneratedByTxDiff bool +} + +func (s LeaseStateSnapshot) IsGeneratedByTxDiff() bool { + return s.isGeneratedByTxDiff } func (s LeaseStateSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseState(s) } type SponsorshipSnapshot struct { - AssetID crypto.Digest - MinSponsoredFee uint64 + AssetID crypto.Digest + MinSponsoredFee uint64 + isGeneratedByTxDiff bool +} + +func (s SponsorshipSnapshot) IsGeneratedByTxDiff() bool { + return s.isGeneratedByTxDiff } func (s SponsorshipSnapshot) Apply(a SnapshotApplier) error { return a.ApplySponsorship(s) } type AliasSnapshot struct { - Address proto.WavesAddress - Alias proto.Alias + Address proto.WavesAddress + Alias proto.Alias + isGeneratedByTxDiff bool +} + +func (s AliasSnapshot) IsGeneratedByTxDiff() bool { + return s.isGeneratedByTxDiff } func (s AliasSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAlias(s) } // FilledVolumeFeeSnapshot Filled Volume and Fee. type FilledVolumeFeeSnapshot struct { // OrderFill - OrderID crypto.Digest - FilledVolume uint64 - FilledFee uint64 + OrderID crypto.Digest + FilledVolume uint64 + FilledFee uint64 + isGeneratedByTxDiff bool +} + +func (s FilledVolumeFeeSnapshot) IsGeneratedByTxDiff() bool { + return s.isGeneratedByTxDiff } func (s FilledVolumeFeeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyFilledVolumeAndFee(s) } @@ -115,23 +175,38 @@ type StaticAssetInfoSnapshot struct { IssuerPublicKey crypto.PublicKey Decimals uint8 IsNFT bool + isGeneratedByTxDiff bool +} + +func (s StaticAssetInfoSnapshot) IsGeneratedByTxDiff() bool { + return s.isGeneratedByTxDiff } func (s StaticAssetInfoSnapshot) Apply(a SnapshotApplier) error { return a.ApplyStaticAssetInfo(s) } type AssetVolumeSnapshot struct { // AssetVolume in pb - AssetID crypto.Digest - TotalQuantity big.Int // volume in protobuf - IsReissuable bool + AssetID crypto.Digest + TotalQuantity big.Int // volume in protobuf + IsReissuable bool + isGeneratedByTxDiff bool +} + +func (s AssetVolumeSnapshot) IsGeneratedByTxDiff() bool { + return s.isGeneratedByTxDiff } func (s AssetVolumeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetVolume(s) } type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb - AssetID crypto.Digest - AssetName string - AssetDescription string - ChangeHeight proto.Height // last_updated in pb + AssetID crypto.Digest + AssetName string + AssetDescription string + ChangeHeight proto.Height // last_updated in pb + isGeneratedByTxDiff bool +} + +func (s AssetDescriptionSnapshot) IsGeneratedByTxDiff() bool { + return s.isGeneratedByTxDiff } func (s AssetDescriptionSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetDescription(s) } diff --git a/pkg/state/state.go b/pkg/state/state.go index 38687d600..2206e36a5 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -591,7 +591,7 @@ func (s *stateManager) addGenesisBlock() error { return err } - if err := s.appender.validateAllDiffs(); err != nil { + if err := s.appender.applyAllDiffs(); err != nil { return err } if err := s.stor.prepareHashes(); err != nil { @@ -1272,7 +1272,7 @@ func (s *stateManager) needToCancelLeases(blockchainHeight uint64) (bool, error) } } -// TODO generate snapshots here too +// TODO what to do with stolen aliases in snapshots? func (s *stateManager) blockchainHeightAction(blockchainHeight uint64, lastBlock, nextBlock proto.BlockID) error { cancelLeases, err := s.needToCancelLeases(blockchainHeight) if err != nil { @@ -1519,10 +1519,9 @@ func (s *stateManager) addBlocks() (*proto.Block, error) { return nil, wrapErr(ValidationError, verifyError) } - // Validate all the balance diffs accumulated from this blocks batch. + // Apply all the balance diffs accumulated from this blocks batch. // This also validates diffs for negative balances. - - if err := s.appender.validateAllDiffs(); err != nil { + if err := s.appender.applyAllDiffs(); err != nil { return nil, err } diff --git a/pkg/state/transaction_checker_test.go b/pkg/state/transaction_checker_test.go index 101ac9b97..ff7f81942 100644 --- a/pkg/state/transaction_checker_test.go +++ b/pkg/state/transaction_checker_test.go @@ -21,19 +21,43 @@ var ( ) type checkerTestObjects struct { - stor *testStorageObjects - tc *transactionChecker - tp *transactionPerformer + stor *testStorageObjects + tc *transactionChecker + tp *transactionPerformer + stateActionsCounter *proto.StateActionsCounter } -func createCheckerTestObjects(t *testing.T) *checkerTestObjects { +func createCheckerTestObjects(t *testing.T, checkerInfo *checkerInfo) *checkerTestObjects { stor := createStorageObjects(t, true) tc, err := newTransactionChecker(proto.NewBlockIDFromSignature(genSig), stor.entities, settings.MainNetSettings) require.NoError(t, err, "newTransactionChecker() failed") - snapshotGenerator := &snapshotGenerator{stor: stor.entities, settings: settings.MainNetSettings} - tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) + + actionsCounter := new(proto.StateActionsCounter) + snapshotApplier := newBlockSnapshotsApplier( + blockSnapshotsApplierInfo{ + ci: checkerInfo, + scheme: settings.MainNetSettings.AddressSchemeCharacter, + stateActionsCounter: actionsCounter, + }, + snapshotApplierStorages{ + balances: stor.entities.balances, + aliases: stor.entities.aliases, + assets: stor.entities.assets, + scriptsStorage: stor.entities.scriptsStorage, + scriptsComplexity: stor.entities.scriptsComplexity, + sponsoredAssets: stor.entities.sponsoredAssets, + ordersVolumes: stor.entities.ordersVolumes, + accountsDataStor: stor.entities.accountsDataStor, + leases: stor.entities.leases, + }, + ) + snapshotGenerator := snapshotGenerator{stor: stor.entities, scheme: settings.MainNetSettings.AddressSchemeCharacter} + + tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings) + tp.snapshotApplier = &snapshotApplier + tp.snapshotGenerator = &snapshotGenerator require.NoError(t, err, "newTransactionPerformer() failed") - return &checkerTestObjects{stor, tc, tp} + return &checkerTestObjects{stor, tc, tp, actionsCounter} } func defaultCheckerInfo() *checkerInfo { @@ -47,10 +71,11 @@ func defaultCheckerInfo() *checkerInfo { } func TestCheckGenesis(t *testing.T) { - to := createCheckerTestObjects(t) - tx := createGenesis() info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) + + tx := createGenesis() _, err := to.tc.checkGenesis(tx, info) assert.EqualError(t, err, "genesis transaction inside of non-genesis block") @@ -69,10 +94,11 @@ func TestCheckGenesis(t *testing.T) { } func TestCheckPayment(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createPayment(t) - info := defaultCheckerInfo() + info.height = settings.MainNetSettings.BlockVersion3AfterHeight _, err := to.tc.checkPayment(tx, info) assert.Error(t, err, "checkPayment accepted payment tx after Block v3 height") @@ -86,10 +112,10 @@ func TestCheckPayment(t *testing.T) { } func TestCheckTransferWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createTransferWithSig(t) - info := defaultCheckerInfo() assetId := tx.FeeAsset.ID @@ -124,10 +150,10 @@ func TestCheckTransferWithSig(t *testing.T) { } func TestCheckTransferWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createTransferWithProofs(t) - info := defaultCheckerInfo() assetId := tx.FeeAsset.ID @@ -169,7 +195,8 @@ func TestCheckTransferWithProofs(t *testing.T) { } func TestCheckIsValidUtf8(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) err := to.tc.isValidUtf8("just a normal string") assert.NoError(t, err) @@ -187,10 +214,11 @@ func TestCheckIsValidUtf8(t *testing.T) { } func TestCheckIssueWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createIssueWithSig(t, 1000) - info := defaultCheckerInfo() + _, err := to.tc.checkIssueWithSig(tx, info) assert.NoError(t, err, "checkIssueWithSig failed with valid issue tx") @@ -200,10 +228,11 @@ func TestCheckIssueWithSig(t *testing.T) { } func TestCheckIssueWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createIssueWithProofs(t, 1000) - info := defaultCheckerInfo() + to.stor.addBlock(t, blockID0) _, err := to.tc.checkIssueWithProofs(tx, info) @@ -215,13 +244,14 @@ func TestCheckIssueWithProofs(t *testing.T) { } func TestCheckReissueWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithSig(t, 1000) tx.SenderPK = assetInfo.issuer - info := defaultCheckerInfo() + info.currentTimestamp = settings.MainNetSettings.ReissueBugWindowTimeEnd + 1 _, err := to.tc.checkReissueWithSig(tx, info) assert.NoError(t, err, "checkReissueWithSig failed with valid reissue tx") @@ -246,7 +276,7 @@ func TestCheckReissueWithSig(t *testing.T) { tx.SenderPK = assetInfo.issuer tx.Reissuable = false - _, err = to.tp.performReissueWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performReissueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performReissueWithSig failed") to.stor.addBlock(t, blockID0) to.stor.flush(t) @@ -257,13 +287,14 @@ func TestCheckReissueWithSig(t *testing.T) { } func TestCheckReissueWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithProofs(t, 1000) tx.SenderPK = assetInfo.issuer - info := defaultCheckerInfo() + info.currentTimestamp = settings.MainNetSettings.ReissueBugWindowTimeEnd + 1 _, err := to.tc.checkReissueWithProofs(tx, info) @@ -294,7 +325,7 @@ func TestCheckReissueWithProofs(t *testing.T) { tx.SenderPK = assetInfo.issuer tx.Reissuable = false - _, err = to.tp.performReissueWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performReissueWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performReissueWithProofs failed") to.stor.addBlock(t, blockID0) to.stor.flush(t) @@ -305,12 +336,12 @@ func TestCheckReissueWithProofs(t *testing.T) { } func TestCheckBurnWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithSig(t) tx.SenderPK = assetInfo.issuer - info := defaultCheckerInfo() _, err := to.tc.checkBurnWithSig(tx, info) assert.NoError(t, err, "checkBurnWithSig failed with valid burn tx") @@ -339,12 +370,12 @@ func TestCheckBurnWithSig(t *testing.T) { } func TestCheckBurnWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithProofs(t) tx.SenderPK = assetInfo.issuer - info := defaultCheckerInfo() _, err := to.tc.checkBurnWithProofs(tx, info) assert.Error(t, err, "checkBurnWithProofs did not fail prior to SmartAccounts activation") @@ -378,10 +409,11 @@ func TestCheckBurnWithProofs(t *testing.T) { } func TestCheckExchangeWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createExchangeWithSig(t) - info := defaultCheckerInfo() + _, err := to.tc.checkExchangeWithSig(tx, info) assert.Error(t, err, "checkExchangeWithSig did not fail with exchange with unknown assets") @@ -444,10 +476,11 @@ func TestCheckExchangeWithSig(t *testing.T) { } func TestCheckExchangeWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) txOV2 := createExchangeWithProofs(t) - info := defaultCheckerInfo() + _, err := to.tc.checkExchangeWithProofs(txOV2, info) assert.Error(t, err, "checkExchangeWithProofs did not fail with exchange with unknown assets") @@ -539,10 +572,10 @@ func TestCheckExchangeWithProofs(t *testing.T) { } func TestCheckUnorderedExchangeV2WithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createUnorderedExchangeWithProofs(t, 2) - info := defaultCheckerInfo() to.stor.createAsset(t, testGlobal.asset0.asset.ID) to.stor.createAsset(t, testGlobal.asset1.asset.ID) @@ -558,10 +591,10 @@ func TestCheckUnorderedExchangeV2WithProofs(t *testing.T) { } func TestCheckUnorderedExchangeV3WithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createUnorderedExchangeWithProofs(t, 3) - info := defaultCheckerInfo() to.stor.createAsset(t, testGlobal.asset0.asset.ID) to.stor.createAsset(t, testGlobal.asset1.asset.ID) @@ -577,10 +610,11 @@ func TestCheckUnorderedExchangeV3WithProofs(t *testing.T) { } func TestCheckLeaseWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createLeaseWithSig(t) - info := defaultCheckerInfo() + tx.Recipient = proto.NewRecipientFromAddress(testGlobal.senderInfo.addr) _, err := to.tc.checkLeaseWithSig(tx, info) assert.Error(t, err, "checkLeaseWithSig did not fail when leasing to self") @@ -591,10 +625,11 @@ func TestCheckLeaseWithSig(t *testing.T) { } func TestCheckLeaseWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createLeaseWithProofs(t) - info := defaultCheckerInfo() + tx.Recipient = proto.NewRecipientFromAddress(testGlobal.senderInfo.addr) _, err := to.tc.checkLeaseWithProofs(tx, info) assert.Error(t, err, "checkLeaseWithProofs did not fail when leasing to self") @@ -611,10 +646,11 @@ func TestCheckLeaseWithProofs(t *testing.T) { } func TestCheckLeaseCancelWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) leaseTx := createLeaseWithSig(t) - info := defaultCheckerInfo() + info.currentTimestamp = settings.MainNetSettings.AllowMultipleLeaseCancelUntilTime + 1 tx := createLeaseCancelWithSig(t, *leaseTx.ID) @@ -622,7 +658,7 @@ func TestCheckLeaseCancelWithSig(t *testing.T) { assert.Error(t, err, "checkLeaseCancelWithSig did not fail when cancelling nonexistent lease") to.stor.addBlock(t, blockID0) - _, err = to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseWithSig failed") to.stor.flush(t) @@ -639,10 +675,11 @@ func TestCheckLeaseCancelWithSig(t *testing.T) { } func TestCheckLeaseCancelWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) leaseTx := createLeaseWithProofs(t) - info := defaultCheckerInfo() + info.currentTimestamp = settings.MainNetSettings.AllowMultipleLeaseCancelUntilTime + 1 tx := createLeaseCancelWithProofs(t, *leaseTx.ID) @@ -650,7 +687,7 @@ func TestCheckLeaseCancelWithProofs(t *testing.T) { assert.Error(t, err, "checkLeaseCancelWithProofs did not fail when cancelling nonexistent lease") to.stor.addBlock(t, blockID0) - _, err = to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseWithProofs failed") to.stor.flush(t) @@ -666,7 +703,7 @@ func TestCheckLeaseCancelWithProofs(t *testing.T) { _, err = to.tc.checkLeaseCancelWithProofs(tx, info) assert.NoError(t, err, "checkLeaseCancelWithProofs failed with valid leaseCancel tx") - _, err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseCancelWithProofs() failed") _, err = to.tc.checkLeaseCancelWithProofs(tx, info) @@ -674,16 +711,16 @@ func TestCheckLeaseCancelWithProofs(t *testing.T) { } func TestCheckCreateAliasWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createCreateAliasWithSig(t) - info := defaultCheckerInfo() _, err := to.tc.checkCreateAliasWithSig(tx, info) assert.NoError(t, err, "checkCreateAliasWithSig failed with valid createAlias tx") to.stor.addBlock(t, blockID0) - _, err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performCreateAliasWithSig failed") to.stor.flush(t) @@ -697,10 +734,10 @@ func TestCheckCreateAliasWithSig(t *testing.T) { } func TestCheckCreateAliasWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createCreateAliasWithProofs(t) - info := defaultCheckerInfo() _, err := to.tc.checkCreateAliasWithProofs(tx, info) assert.Error(t, err, "checkCreateAliasWithProofs did not fail prior to SmartAccounts activation") @@ -711,7 +748,7 @@ func TestCheckCreateAliasWithProofs(t *testing.T) { assert.NoError(t, err, "checkCreateAliasWithProofs failed with valid createAlias tx") to.stor.addBlock(t, blockID0) - _, err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performCreateAliasWithProofs failed") to.stor.flush(t) @@ -725,12 +762,12 @@ func TestCheckCreateAliasWithProofs(t *testing.T) { } func TestCheckMassTransferWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) entriesNum := 50 entries := generateMassTransferEntries(t, entriesNum) tx := createMassTransferWithProofs(t, entries) - info := defaultCheckerInfo() _, err := to.tc.checkMassTransferWithProofs(tx, info) assert.Error(t, err, "checkMassTransferWithProofs did not fail prior to feature activation") @@ -756,10 +793,10 @@ func TestCheckMassTransferWithProofs(t *testing.T) { } func TestCheckDataWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createDataWithProofs(t, 1) - info := defaultCheckerInfo() _, err := to.tc.checkDataWithProofs(tx, info) assert.Error(t, err, "checkDataWithProofs did not fail prior to feature activation") @@ -802,12 +839,12 @@ func TestCheckDataWithProofs(t *testing.T) { } func TestCheckSponsorshipWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createSponsorshipWithProofs(t, 1000) assetInfo := to.stor.createAsset(t, tx.AssetID) tx.SenderPK = assetInfo.issuer - info := defaultCheckerInfo() _, err := to.tc.checkSponsorshipWithProofs(tx, info) assert.Error(t, err, "checkSponsorshipWithProofs did not fail prior to feature activation") @@ -845,10 +882,10 @@ func TestCheckSponsorshipWithProofs(t *testing.T) { } func TestCheckSetScriptWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createSetScriptWithProofs(t) - info := defaultCheckerInfo() // Activate sponsorship. to.stor.activateSponsorship(t) @@ -1343,10 +1380,10 @@ func TestCheckSetScriptWithProofsCheckDAppCallables(t *testing.T) { } func TestCheckSetAssetScriptWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createSetAssetScriptWithProofs(t) - info := defaultCheckerInfo() assetInfo := defaultAssetInfo(proto.DigestTail(tx.AssetID), true) assetInfo.issuer = tx.SenderPK @@ -1379,13 +1416,14 @@ func TestCheckSetAssetScriptWithProofs(t *testing.T) { } func TestCheckInvokeScriptWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) payments := []proto.ScriptPayment{ {Amount: 1, Asset: *testGlobal.asset0.asset}, } tx := createInvokeScriptWithProofs(t, payments, proto.FunctionCall{}, proto.OptionalAsset{}, 1) - info := defaultCheckerInfo() + to.stor.addBlock(t, blockID0) assetId := tx.Payments[0].Asset.ID to.stor.createAsset(t, assetId) @@ -1418,7 +1456,8 @@ func TestCheckInvokeScriptWithProofs(t *testing.T) { } func TestCheckUpdateAssetInfoWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createUpdateAssetInfoWithProofs(t) // We create asset using random block here on purpose, this way @@ -1427,7 +1466,6 @@ func TestCheckUpdateAssetInfoWithProofs(t *testing.T) { to.stor.createAsset(t, tx.FeeAsset.ID) tx.SenderPK = assetInfo.issuer - info := defaultCheckerInfo() info.height = 100001 // Check fail prior to activation. @@ -1460,10 +1498,10 @@ func TestCheckUpdateAssetInfoWithProofs(t *testing.T) { } func TestCheckInvokeExpressionWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createInvokeExpressionWithProofs(t, make([]byte, 1), proto.OptionalAsset{}, 1) - info := defaultCheckerInfo() // Check activation. _, err := to.tc.checkInvokeScriptWithProofs(tx, info) diff --git a/pkg/state/transaction_differ_test.go b/pkg/state/transaction_differ_test.go index 7f5e312d1..a20236f51 100644 --- a/pkg/state/transaction_differ_test.go +++ b/pkg/state/transaction_differ_test.go @@ -26,19 +26,43 @@ var ( ) type differTestObjects struct { - stor *testStorageObjects - td *transactionDiffer - tp *transactionPerformer + stor *testStorageObjects + td *transactionDiffer + tp *transactionPerformer + stateActionsCounter *proto.StateActionsCounter } -func createDifferTestObjects(t *testing.T) *differTestObjects { +func createDifferTestObjects(t *testing.T, checkerInfo *checkerInfo) *differTestObjects { stor := createStorageObjects(t, true) td, err := newTransactionDiffer(stor.entities, settings.MainNetSettings) require.NoError(t, err, "newTransactionDiffer() failed") - snapshotGenerator := &snapshotGenerator{stor: stor.entities, settings: settings.MainNetSettings} - tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) + + actionsCounter := new(proto.StateActionsCounter) + + snapshotApplier := newBlockSnapshotsApplier( + blockSnapshotsApplierInfo{ + ci: checkerInfo, + scheme: settings.MainNetSettings.AddressSchemeCharacter, + stateActionsCounter: actionsCounter, + }, + snapshotApplierStorages{ + balances: stor.entities.balances, + aliases: stor.entities.aliases, + assets: stor.entities.assets, + scriptsStorage: stor.entities.scriptsStorage, + scriptsComplexity: stor.entities.scriptsComplexity, + sponsoredAssets: stor.entities.sponsoredAssets, + ordersVolumes: stor.entities.ordersVolumes, + accountsDataStor: stor.entities.accountsDataStor, + leases: stor.entities.leases, + }, + ) + snapshotGenerator := snapshotGenerator{stor: stor.entities, scheme: settings.MainNetSettings.AddressSchemeCharacter} + tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings) + tp.snapshotApplier = &snapshotApplier + tp.snapshotGenerator = &snapshotGenerator require.NoError(t, err, "newTransactionPerformer() failed") - return &differTestObjects{stor, td, tp} + return &differTestObjects{stor, td, tp, actionsCounter} } func createGenesis() *proto.Genesis { @@ -46,7 +70,8 @@ func createGenesis() *proto.Genesis { } func TestCreateDiffGenesis(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createGenesis() ch, err := to.td.createDiffGenesis(tx, defaultDifferInfo()) @@ -67,7 +92,8 @@ func createPayment(t *testing.T) *proto.Payment { } func TestCreateDiffPayment(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createPayment(t) ch, err := to.td.createDiffPayment(tx, defaultDifferInfo()) @@ -94,7 +120,8 @@ func createTransferWithSig(t *testing.T) *proto.TransferWithSig { } func TestCreateDiffTransferWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createTransferWithSig(t) feeFullAssetID := tx.FeeAsset.ID @@ -151,7 +178,8 @@ func createTransferWithProofs(t *testing.T) *proto.TransferWithProofs { } func TestCreateDiffTransferWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createTransferWithProofs(t) feeFullAssetID := tx.FeeAsset.ID @@ -215,7 +243,8 @@ func createNFTIssueWithSig(t *testing.T) *proto.IssueWithSig { } func TestCreateDiffIssueWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createIssueWithSig(t, 1000) ch, err := to.td.createDiffIssueWithSig(tx, defaultDifferInfo()) @@ -249,7 +278,8 @@ func createNFTIssueWithProofs(t *testing.T) *proto.IssueWithProofs { } func TestCreateDiffIssueWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createIssueWithProofs(t, 1000) ch, err := to.td.createDiffIssueWithProofs(tx, defaultDifferInfo()) @@ -276,7 +306,8 @@ func createReissueWithSig(t *testing.T, feeUnits int) *proto.ReissueWithSig { } func TestCreateDiffReissueWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createReissueWithSig(t, 1000) ch, err := to.td.createDiffReissueWithSig(tx, defaultDifferInfo()) @@ -302,7 +333,8 @@ func createReissueWithProofs(t *testing.T, feeUnits int) *proto.ReissueWithProof } func TestCreateDiffReissueWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createReissueWithProofs(t, 1000) ch, err := to.td.createDiffReissueWithProofs(tx, defaultDifferInfo()) @@ -328,7 +360,8 @@ func createBurnWithSig(t *testing.T) *proto.BurnWithSig { } func TestCreateDiffBurnWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createBurnWithSig(t) ch, err := to.td.createDiffBurnWithSig(tx, defaultDifferInfo()) @@ -354,7 +387,8 @@ func createBurnWithProofs(t *testing.T) *proto.BurnWithProofs { } func TestCreateDiffBurnWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createBurnWithProofs(t) ch, err := to.td.createDiffBurnWithProofs(tx, defaultDifferInfo()) @@ -400,7 +434,8 @@ func createExchangeWithSig(t *testing.T) *proto.ExchangeWithSig { //} func TestCreateDiffExchangeWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createExchangeWithSig(t) ch, err := to.td.createDiffExchange(tx, defaultDifferInfo()) @@ -453,7 +488,8 @@ func createUnorderedExchangeWithProofs(t *testing.T, v int) *proto.ExchangeWithP } func TestCreateDiffExchangeWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createExchangeWithProofs(t) ch, err := to.td.createDiffExchange(tx, defaultDifferInfo()) @@ -562,7 +598,8 @@ func createExchangeV2WithProofsWithOrdersV3(t *testing.T, info orderBuildInfo) * } func TestCreateDiffExchangeV2WithProofsWithOrdersV3(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createExchangeV2WithProofsWithOrdersV3(t, orderBuildInfo{ price: 10e8, @@ -593,7 +630,8 @@ func TestCreateDiffExchangeV2WithProofsWithOrdersV3(t *testing.T) { } func TestCreateDiffExchangeV3WithProofsWithMixedOrders(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) const ( asset0Decimals = 5 @@ -700,7 +738,7 @@ func TestCreateDiffExchangeV3WithProofsWithMixedOrders(t *testing.T) { // and produces an incorrect or unexpected diff, should be fixes some how // // func TestCreateDiffExchangeWithSignature(t *testing.T) { -// to, path := createDifferTestObjects(t) +// to, path := createDifferTestObjects(t, checkerInfo // // to.stor.createAssetWithDecimals(t, testGlobal.asset0.asset.ID, 8) // to.stor.createAssetWithDecimals(t, testGlobal.asset1.asset.ID, 8) @@ -734,7 +772,8 @@ func TestCreateDiffExchangeV3WithProofsWithMixedOrders(t *testing.T) { // assert.Equal(t, correctAddrs, ch.addrs) // } func TestCreateDiffExchangeV3WithProofsWithOrdersV4(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.createAssetWithDecimals(t, testGlobal.asset0.asset.ID, 0) to.stor.createAssetWithDecimals(t, testGlobal.asset1.asset.ID, 8) @@ -807,7 +846,8 @@ func createLeaseWithSig(t *testing.T) *proto.LeaseWithSig { } func TestCreateDiffLeaseWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createLeaseWithSig(t) ch, err := to.td.createDiffLeaseWithSig(tx, defaultDifferInfo()) @@ -834,7 +874,8 @@ func createLeaseWithProofs(t *testing.T) *proto.LeaseWithProofs { } func TestCreateDiffLeaseWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createLeaseWithProofs(t) ch, err := to.td.createDiffLeaseWithProofs(tx, defaultDifferInfo()) @@ -861,10 +902,11 @@ func createLeaseCancelWithSig(t *testing.T, leaseID crypto.Digest) *proto.LeaseC } func TestCreateDiffLeaseCancelWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) leaseTx := createLeaseWithSig(t) - info := defaultPerformerInfo() + info := defaultPerformerInfo(to.stateActionsCounter) to.stor.addBlock(t, blockID0) _, err := to.tp.performLeaseWithSig(leaseTx, info, nil, nil) assert.NoError(t, err, "performLeaseWithSig failed") @@ -894,10 +936,11 @@ func createLeaseCancelWithProofs(t *testing.T, leaseID crypto.Digest) *proto.Lea } func TestCreateDiffLeaseCancelWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) leaseTx := createLeaseWithProofs(t) - info := defaultPerformerInfo() + info := defaultPerformerInfo(to.stateActionsCounter) to.stor.addBlock(t, blockID0) _, err := to.tp.performLeaseWithProofs(leaseTx, info, nil, nil) assert.NoError(t, err, "performLeaseWithProofs failed") @@ -931,7 +974,8 @@ func createCreateAliasWithSig(t *testing.T) *proto.CreateAliasWithSig { } func TestCreateDiffCreateAliasWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createCreateAliasWithSig(t) ch, err := to.td.createDiffCreateAliasWithSig(tx, defaultDifferInfo()) @@ -960,7 +1004,8 @@ func createCreateAliasWithProofs(t *testing.T) *proto.CreateAliasWithProofs { } func TestCreateDiffCreateAliasWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createCreateAliasWithProofs(t) ch, err := to.td.createDiffCreateAliasWithProofs(tx, defaultDifferInfo()) @@ -996,7 +1041,8 @@ func createMassTransferWithProofs(t *testing.T, transfers []proto.MassTransferEn } func TestCreateDiffMassTransferWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) entriesNum := 66 entries := generateMassTransferEntries(t, entriesNum) @@ -1036,7 +1082,8 @@ func createDataWithProofs(t *testing.T, entriesNum int) *proto.DataWithProofs { } func TestCreateDiffDataWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createDataWithProofs(t, 1) ch, err := to.td.createDiffDataWithProofs(tx, defaultDifferInfo()) @@ -1061,7 +1108,8 @@ func createSponsorshipWithProofs(t *testing.T, fee uint64) *proto.SponsorshipWit } func TestCreateDiffSponsorshipWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createSponsorshipWithProofs(t, 1000) ch, err := to.td.createDiffSponsorshipWithProofs(tx, defaultDifferInfo()) @@ -1093,7 +1141,8 @@ func createSetScriptWithProofs(t *testing.T, customScriptBytes ...[]byte) *proto } func TestCreateDiffSetScriptWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createSetScriptWithProofs(t) ch, err := to.td.createDiffSetScriptWithProofs(tx, defaultDifferInfo()) @@ -1120,7 +1169,8 @@ func createSetAssetScriptWithProofs(t *testing.T) *proto.SetAssetScriptWithProof } func TestCreateDiffSetAssetScriptWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createSetAssetScriptWithProofs(t) ch, err := to.td.createDiffSetAssetScriptWithProofs(tx, defaultDifferInfo()) @@ -1145,7 +1195,8 @@ func createInvokeScriptWithProofs(t *testing.T, pmts proto.ScriptPayments, fc pr } func TestCreateDiffInvokeScriptWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) feeConst, ok := feeConstants[proto.InvokeScriptTransaction] assert.Equal(t, ok, true) @@ -1207,7 +1258,8 @@ func createUpdateAssetInfoWithProofs(t *testing.T) *proto.UpdateAssetInfoWithPro } func TestCreateDiffUpdateAssetInfoWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createUpdateAssetInfoWithProofs(t) ch, err := to.td.createDiffUpdateAssetInfoWithProofs(tx, defaultDifferInfo()) diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 9c51251c8..d05afc5fd 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -85,11 +85,10 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest // Create new asset. assetInfo := &assetInfo{ assetConstInfo: assetConstInfo{ - tail: proto.DigestTail(assetID), - issuer: tx.SenderPK, - decimals: tx.Decimals, - issueHeight: blockHeight, - issueSequenceInBlock: info.stateActionsCounter.NextIssueActionNumber(), + tail: proto.DigestTail(assetID), + issuer: tx.SenderPK, + decimals: tx.Decimals, + issueHeight: blockHeight, }, assetChangeableInfo: assetChangeableInfo{ quantity: *big.NewInt(int64(tx.Quantity)), @@ -420,7 +419,7 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot } complexity := estimation.Verifier - snapshot, err := tp.snapshotGenerator.generateSnapshotForSetAssetScriptTx(tx.AssetID, tx.Script, complexity, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForSetAssetScriptTx(tx.AssetID, tx.Script, complexity, tx.SenderPK, balanceChanges) if err != nil { return nil, err } diff --git a/pkg/state/transaction_performer_test.go b/pkg/state/transaction_performer_test.go index 0f84dae1e..96400f168 100644 --- a/pkg/state/transaction_performer_test.go +++ b/pkg/state/transaction_performer_test.go @@ -15,28 +15,53 @@ import ( ) type performerTestObjects struct { - stor *testStorageObjects - tp *transactionPerformer + stor *testStorageObjects + tp *transactionPerformer + stateActionsCounter *proto.StateActionsCounter } -func createPerformerTestObjects(t *testing.T) *performerTestObjects { +func createPerformerTestObjects(t *testing.T, checkerInfo *checkerInfo) *performerTestObjects { stor := createStorageObjects(t, true) - snapshotGenerator := &snapshotGenerator{stor.entities, settings.MainNetSettings} - tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) + tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings) + + actionsCounter := new(proto.StateActionsCounter) + + snapshotApplier := newBlockSnapshotsApplier( + blockSnapshotsApplierInfo{ + ci: checkerInfo, + scheme: settings.MainNetSettings.AddressSchemeCharacter, + stateActionsCounter: actionsCounter, + }, + snapshotApplierStorages{ + balances: stor.entities.balances, + aliases: stor.entities.aliases, + assets: stor.entities.assets, + scriptsStorage: stor.entities.scriptsStorage, + scriptsComplexity: stor.entities.scriptsComplexity, + sponsoredAssets: stor.entities.sponsoredAssets, + ordersVolumes: stor.entities.ordersVolumes, + accountsDataStor: stor.entities.accountsDataStor, + leases: stor.entities.leases, + }, + ) + snapshotGenerator := snapshotGenerator{stor: stor.entities, scheme: settings.MainNetSettings.AddressSchemeCharacter} + tp.snapshotApplier = &snapshotApplier + tp.snapshotGenerator = &snapshotGenerator require.NoError(t, err, "newTransactionPerformer() failed") - return &performerTestObjects{stor, tp} + return &performerTestObjects{stor, tp, actionsCounter} } -func defaultPerformerInfo() *performerInfo { - return newPerformerInfo(0, new(proto.StateActionsCounter), blockID0, proto.WavesAddress{}, txCheckerData{}) +func defaultPerformerInfo(stateActionsCounter *proto.StateActionsCounter) *performerInfo { + return newPerformerInfo(0, stateActionsCounter, blockID0, proto.WavesAddress{}, txCheckerData{}) } func TestPerformIssueWithSig(t *testing.T) { - to := createPerformerTestObjects(t) - + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) + checkerInfo.height = 1 to.stor.addBlock(t, blockID0) tx := createIssueWithSig(t, 1000) - _, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performIssueWithSig() failed") to.stor.flush(t) expectedAssetInfo := assetInfo{ @@ -63,12 +88,13 @@ func TestPerformIssueWithSig(t *testing.T) { } func TestPerformIssueWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) - + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) + checkerInfo.height = 1 to.stor.addBlock(t, blockID0) tx := createIssueWithProofs(t, 1000) - _, err := to.tp.performIssueWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performIssueWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performIssueWithProofs() failed") to.stor.flush(t) expectedAssetInfo := assetInfo{ @@ -95,11 +121,13 @@ func TestPerformIssueWithProofs(t *testing.T) { } func TestPerformReissueWithSig(t *testing.T) { - to := createPerformerTestObjects(t) + + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithSig(t, 1000) - _, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performReissueWithSig() failed") to.stor.flush(t) assetInfo.reissuable = tx.Reissuable @@ -112,11 +140,12 @@ func TestPerformReissueWithSig(t *testing.T) { } func TestPerformReissueWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithProofs(t, 1000) - _, err := to.tp.performReissueWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performReissueWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performReissueWithProofs() failed") to.stor.flush(t) assetInfo.reissuable = tx.Reissuable @@ -129,11 +158,12 @@ func TestPerformReissueWithProofs(t *testing.T) { } func TestPerformBurnWithSig(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithSig(t) - _, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performBurnWithSig() failed") to.stor.flush(t) assetInfo.quantity.Sub(&assetInfo.quantity, big.NewInt(int64(tx.Amount))) @@ -145,11 +175,12 @@ func TestPerformBurnWithSig(t *testing.T) { } func TestPerformBurnWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithProofs(t) - _, err := to.tp.performBurnWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performBurnWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performBurnWithProofs() failed") to.stor.flush(t) assetInfo.quantity.Sub(&assetInfo.quantity, big.NewInt(int64(tx.Amount))) @@ -161,11 +192,12 @@ func TestPerformBurnWithProofs(t *testing.T) { } func TestPerformExchange(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createExchangeWithSig(t) - _, err := to.tp.performExchange(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performExchange(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performExchange() failed") sellOrderID, err := tx.GetOrder2().GetID() @@ -198,11 +230,12 @@ func TestPerformExchange(t *testing.T) { } func TestPerformLeaseWithSig(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createLeaseWithSig(t) - _, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseWithSig() failed") to.stor.flush(t) leasingInfo := &leasing{ @@ -219,11 +252,12 @@ func TestPerformLeaseWithSig(t *testing.T) { } func TestPerformLeaseWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createLeaseWithProofs(t) - _, err := to.tp.performLeaseWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performLeaseWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseWithProofs() failed") to.stor.flush(t) leasingInfo := &leasing{ @@ -240,11 +274,12 @@ func TestPerformLeaseWithProofs(t *testing.T) { } func TestPerformLeaseCancelWithSig(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) leaseTx := createLeaseWithSig(t) - _, err := to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseWithSig() failed") to.stor.flush(t) tx := createLeaseCancelWithSig(t, *leaseTx.ID) @@ -256,7 +291,7 @@ func TestPerformLeaseCancelWithSig(t *testing.T) { Sender: testGlobal.senderInfo.addr, CancelTransactionID: tx.ID, } - _, err = to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseCancelWithSig() failed") to.stor.flush(t) info, err := to.stor.entities.leases.leasingInfo(*leaseTx.ID) @@ -265,11 +300,12 @@ func TestPerformLeaseCancelWithSig(t *testing.T) { } func TestPerformLeaseCancelWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) leaseTx := createLeaseWithProofs(t) - _, err := to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseWithProofs() failed") to.stor.flush(t) tx := createLeaseCancelWithProofs(t, *leaseTx.ID) @@ -281,7 +317,7 @@ func TestPerformLeaseCancelWithProofs(t *testing.T) { Sender: testGlobal.senderInfo.addr, CancelTransactionID: tx.ID, } - _, err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseCancelWithProofs() failed") to.stor.flush(t) info, err := to.stor.entities.leases.leasingInfo(*leaseTx.ID) @@ -290,11 +326,12 @@ func TestPerformLeaseCancelWithProofs(t *testing.T) { } func TestPerformCreateAliasWithSig(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createCreateAliasWithSig(t) - _, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performCreateAliasWithSig() failed") to.stor.flush(t) addr, err := to.stor.entities.aliases.addrByAlias(tx.Alias.Alias) @@ -302,7 +339,7 @@ func TestPerformCreateAliasWithSig(t *testing.T) { assert.Equal(t, testGlobal.senderInfo.addr, addr, "invalid address by alias after performing CreateAliasWithSig transaction") // Test stealing aliases. - _, err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performCreateAliasWithSig() failed") to.stor.flush(t) err = to.stor.entities.aliases.disableStolenAliases(blockID0) @@ -313,11 +350,12 @@ func TestPerformCreateAliasWithSig(t *testing.T) { } func TestPerformCreateAliasWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createCreateAliasWithProofs(t) - _, err := to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performCreateAliasWithProofs() failed") to.stor.flush(t) addr, err := to.stor.entities.aliases.addrByAlias(tx.Alias.Alias) @@ -325,7 +363,7 @@ func TestPerformCreateAliasWithProofs(t *testing.T) { assert.Equal(t, testGlobal.senderInfo.addr, addr, "invalid address by alias after performing CreateAliasWithProofs transaction") // Test stealing aliases. - _, err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performCreateAliasWithProofs() failed") to.stor.flush(t) err = to.stor.entities.aliases.disableStolenAliases(blockID0) @@ -336,7 +374,8 @@ func TestPerformCreateAliasWithProofs(t *testing.T) { } func TestPerformDataWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) @@ -344,7 +383,7 @@ func TestPerformDataWithProofs(t *testing.T) { entry := &proto.IntegerDataEntry{Key: "TheKey", Value: int64(666)} tx.Entries = []proto.DataEntry{entry} - _, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performDataWithProofs() failed") to.stor.flush(t) @@ -354,12 +393,13 @@ func TestPerformDataWithProofs(t *testing.T) { } func TestPerformSponsorshipWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createSponsorshipWithProofs(t, 1000) - _, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performSponsorshipWithProofs() failed") assetID := proto.AssetIDFromDigest(tx.AssetID) @@ -397,7 +437,8 @@ func TestPerformSponsorshipWithProofs(t *testing.T) { } func TestPerformSetScriptWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) @@ -419,7 +460,7 @@ func TestPerformSetScriptWithProofs(t *testing.T) { require.NoError(t, err) tx := createSetScriptWithProofs(t, scriptBytes) - pi := *defaultPerformerInfo() + pi := *defaultPerformerInfo(to.stateActionsCounter) pi.checkerData.scriptEstimations = &scriptsEstimations{} _, err = to.tp.performSetScriptWithProofs(tx, &pi, nil, nil) assert.NoError(t, err, "performSetScriptWithProofs() failed") @@ -485,12 +526,13 @@ func TestPerformSetScriptWithProofs(t *testing.T) { } func TestPerformSetAssetScriptWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createSetAssetScriptWithProofs(t) - pi := *defaultPerformerInfo() + pi := *defaultPerformerInfo(to.stateActionsCounter) currentEstimatorVersion := 4 tree, err := serialization.Parse(tx.Script) @@ -504,6 +546,7 @@ func TestPerformSetAssetScriptWithProofs(t *testing.T) { currentEstimatorVersion: estimation, }, } + checkerInfo.blockID = blockID0 _, err = to.tp.performSetAssetScriptWithProofs(tx, &pi, nil, nil) assert.NoError(t, err, "performSetAssetScriptWithProofs() failed") @@ -580,11 +623,12 @@ func TestPerformSetAssetScriptWithProofs(t *testing.T) { } func TestPerformUpdateAssetInfoWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createUpdateAssetInfoWithProofs(t) - _, err := to.tp.performUpdateAssetInfoWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performUpdateAssetInfoWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performUpdateAssetInfoWithProofs() failed") to.stor.flush(t) assetInfo.name = tx.Name From 150fbfdd7816064c74f9e8a653a55f17c93c4439 Mon Sep 17 00:00:00 2001 From: esuwu Date: Tue, 18 Jul 2023 03:50:03 -0500 Subject: [PATCH 046/139] Fixed a comment --- pkg/state/appender.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index f90883d26..d36c905b2 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -352,8 +352,7 @@ func (a *txAppender) commitTxApplication( stateActionsCounter: params.stateActionsCounterInBlock, checkerData: applicationRes.checkerData, } - //snapshot, err = a.txHandler.performTx(tx, performerInfo, invocationRes, applicationRes.changes.diff) - snapshot, err = a.txHandler.performTx(tx, performerInfo, invocationRes, nil) + snapshot, err = a.txHandler.performTx(tx, performerInfo, invocationRes, applicationRes.changes.diff) if err != nil { return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to perform: %v", err)) } From 66c480b518f68d92d55e5546b96653a35a407c93 Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 19 Jul 2023 04:05:03 -0500 Subject: [PATCH 047/139] Removed the comment --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6590cfb03..4712bdbf7 100644 --- a/Makefile +++ b/Makefile @@ -71,7 +71,7 @@ vendor: vetcheck: go vet ./... golangci-lint run -c .golangci.yml - #golangci-lint run -c .golangci-strict.yml --new-from-rev=origin/master + golangci-lint run -c .golangci-strict.yml --new-from-rev=origin/master strict-vet-check: golangci-lint run -c .golangci-strict.yml From 651c160da6d4e56a6cc444be0bea3fa38f242e73 Mon Sep 17 00:00:00 2001 From: esuwu Date: Thu, 20 Jul 2023 17:01:08 -0500 Subject: [PATCH 048/139] Removed unnecessary code --- Makefile | 2 +- pkg/state/appender.go | 10 +- pkg/state/snapshot_generator.go | 19 ++- pkg/state/snapshot_generator_test.go | 194 +++++++++++---------------- pkg/state/snapshot_types.go | 94 ++++++------- 5 files changed, 131 insertions(+), 188 deletions(-) diff --git a/Makefile b/Makefile index 4712bdbf7..a96171d42 100644 --- a/Makefile +++ b/Makefile @@ -71,7 +71,7 @@ vendor: vetcheck: go vet ./... golangci-lint run -c .golangci.yml - golangci-lint run -c .golangci-strict.yml --new-from-rev=origin/master +# golangci-lint run -c .golangci-strict.yml --new-from-rev=origin/master strict-vet-check: golangci-lint run -c .golangci-strict.yml diff --git a/pkg/state/appender.go b/pkg/state/appender.go index d36c905b2..4cd7fb183 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -666,16 +666,14 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { return err } // create the initial snapshot - initialSnapshot, err := a.createInitialBlockSnapshot(minerAndRewardDiff) + _, err = a.createInitialBlockSnapshot(minerAndRewardDiff) if err != nil { return errors.Wrap(err, "failed to create initial snapshot") } - // apply miner diff snapshot - err = initialSnapshot.Apply(&snapshotApplier) - if err != nil { - return errors.Wrap(err, "failed to apply a snapshot with miner diff") - } + // TODO apply this snapshot when balances are refatored + //err = initialSnapshot.Apply(&snapshotApplier) + // Save miner diff first (for validation) if err := a.diffStor.saveTxDiff(minerAndRewardDiff); err != nil { return err diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index 7f459a049..ea6d0ecc8 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -51,10 +51,9 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t delete(addrAssetBalanceDiff, key) specialAssetSnapshot = &AssetBalanceSnapshot{ - Address: key.address, - AssetID: assetID, - Balance: uint64(diffAmount), - isGeneratedByTxDiff: true, + Address: key.address, + AssetID: assetID, + Balance: uint64(diffAmount), } } } @@ -677,9 +676,8 @@ func (sg *snapshotGenerator) constructWavesBalanceSnapshotFromDiff(diff addressW return nil, errors.Wrap(err, "failed to receive sender's waves balance") } newBalance := WavesBalanceSnapshot{ - Address: wavesAddress, - Balance: uint64(int64(fullBalance.balance) + diffAmount.balance), - isGeneratedByTxDiff: true, + Address: wavesAddress, + Balance: uint64(int64(fullBalance.balance) + diffAmount.balance), } wavesBalances = append(wavesBalances, newBalance) } @@ -701,10 +699,9 @@ func (sg *snapshotGenerator) constructAssetBalanceSnapshotFromDiff(diff addressA } newBalance := AssetBalanceSnapshot{ - Address: key.address, - AssetID: key.asset.Digest(assetInfo.tail), - Balance: uint64(int64(balance) + diffAmount), - isGeneratedByTxDiff: true, + Address: key.address, + AssetID: key.asset.Digest(assetInfo.tail), + Balance: uint64(int64(balance) + diffAmount), } assetBalances = append(assetBalances, newBalance) } diff --git a/pkg/state/snapshot_generator_test.go b/pkg/state/snapshot_generator_test.go index 23a7d2a5b..104e9de65 100644 --- a/pkg/state/snapshot_generator_test.go +++ b/pkg/state/snapshot_generator_test.go @@ -74,19 +74,16 @@ func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { assert.NoError(t, err, "failed to perform transfer tx") expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - isGeneratedByTxDiff: true, + Address: testGlobal.minerInfo.addr, + Balance: 40000, }, &WavesBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - Balance: 299700000, - isGeneratedByTxDiff: true, + Address: testGlobal.issuerInfo.addr, + Balance: 299700000, }, &WavesBalanceSnapshot{ - Address: testGlobal.recipientInfo.addr, - Balance: 200000, - isGeneratedByTxDiff: true, + Address: testGlobal.recipientInfo.addr, + Balance: 200000, }, } @@ -148,20 +145,17 @@ func TestDefaultIssueTransactionSnapshot(t *testing.T) { IsReissuable: true, }, &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - isGeneratedByTxDiff: true, + Address: testGlobal.minerInfo.addr, + Balance: 40000, }, &WavesBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - Balance: 299900000, - isGeneratedByTxDiff: true, + Address: testGlobal.issuerInfo.addr, + Balance: 299900000, }, &AssetBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - AssetID: *tx.ID, - Balance: 1000, - isGeneratedByTxDiff: true, + Address: testGlobal.issuerInfo.addr, + AssetID: *tx.ID, + Balance: 1000, }, } sort.Slice(expectedSnapshot, func(i, j int) bool { @@ -209,20 +203,17 @@ func TestDefaultReissueSnapshot(t *testing.T) { expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - isGeneratedByTxDiff: true, + Address: testGlobal.minerInfo.addr, + Balance: 40000, }, &WavesBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - Balance: 299900000, - isGeneratedByTxDiff: true, + Address: testGlobal.issuerInfo.addr, + Balance: 299900000, }, &AssetBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - AssetID: testGlobal.asset0.assetID, - Balance: 1050, - isGeneratedByTxDiff: true, + Address: testGlobal.issuerInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 1050, }, &AssetVolumeSnapshot{ AssetID: testGlobal.asset0.assetID, @@ -276,20 +267,17 @@ func TestDefaultBurnSnapshot(t *testing.T) { expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - isGeneratedByTxDiff: true, + Address: testGlobal.minerInfo.addr, + Balance: 40000, }, &WavesBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - Balance: 299900000, - isGeneratedByTxDiff: true, + Address: testGlobal.issuerInfo.addr, + Balance: 299900000, }, &AssetBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - AssetID: testGlobal.asset0.assetID, - Balance: 950, - isGeneratedByTxDiff: true, + Address: testGlobal.issuerInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 950, }, &AssetVolumeSnapshot{ AssetID: testGlobal.asset0.assetID, @@ -364,48 +352,40 @@ func TestDefaultExchangeTransaction(t *testing.T) { expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299999999, - isGeneratedByTxDiff: true, + Address: testGlobal.senderInfo.addr, + Balance: 299999999, }, &WavesBalanceSnapshot{ - Address: testGlobal.recipientInfo.addr, - Balance: 599999998, - isGeneratedByTxDiff: true, + Address: testGlobal.recipientInfo.addr, + Balance: 599999998, }, &WavesBalanceSnapshot{ - Address: testGlobal.matcherInfo.addr, - Balance: 899900003, - isGeneratedByTxDiff: true, + Address: testGlobal.matcherInfo.addr, + Balance: 899900003, }, &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - isGeneratedByTxDiff: true, + Address: testGlobal.minerInfo.addr, + Balance: 40000, }, &AssetBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - AssetID: testGlobal.asset0.assetID, - Balance: 10, - isGeneratedByTxDiff: true, + Address: testGlobal.senderInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 10, }, &AssetBalanceSnapshot{ - Address: testGlobal.recipientInfo.addr, - AssetID: testGlobal.asset0.assetID, - Balance: 590, - isGeneratedByTxDiff: true, + Address: testGlobal.recipientInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 590, }, &AssetBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - AssetID: testGlobal.asset1.assetID, - Balance: 400, - isGeneratedByTxDiff: true, + Address: testGlobal.senderInfo.addr, + AssetID: testGlobal.asset1.assetID, + Balance: 400, }, &AssetBalanceSnapshot{ - Address: testGlobal.recipientInfo.addr, - AssetID: testGlobal.asset1.assetID, - Balance: 100, - isGeneratedByTxDiff: true, + Address: testGlobal.recipientInfo.addr, + AssetID: testGlobal.asset1.assetID, + Balance: 100, }, &FilledVolumeFeeSnapshot{ OrderID: *bo.ID, @@ -460,14 +440,12 @@ func TestDefaultLeaseSnapshot(t *testing.T) { expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - isGeneratedByTxDiff: true, + Address: testGlobal.minerInfo.addr, + Balance: 40000, }, &WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, - isGeneratedByTxDiff: true, + Address: testGlobal.senderInfo.addr, + Balance: 299900000, }, &LeaseStateSnapshot{ LeaseID: *tx.ID, @@ -547,14 +525,12 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - isGeneratedByTxDiff: true, + Address: testGlobal.minerInfo.addr, + Balance: 40000, }, &WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, - isGeneratedByTxDiff: true, + Address: testGlobal.senderInfo.addr, + Balance: 299900000, }, &LeaseStateSnapshot{ LeaseID: leaseID, @@ -621,14 +597,12 @@ func TestDefaultCreateAliasSnapshot(t *testing.T) { expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - isGeneratedByTxDiff: true, + Address: testGlobal.minerInfo.addr, + Balance: 40000, }, &WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, - isGeneratedByTxDiff: true, + Address: testGlobal.senderInfo.addr, + Balance: 299900000, }, &AliasSnapshot{ Address: testGlobal.senderInfo.addr, @@ -683,14 +657,12 @@ func TestDefaultDataSnapshot(t *testing.T) { expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - isGeneratedByTxDiff: true, + Address: testGlobal.minerInfo.addr, + Balance: 40000, }, &WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, - isGeneratedByTxDiff: true, + Address: testGlobal.senderInfo.addr, + Balance: 299900000, }, &DataEntriesSnapshot{ Address: testGlobal.senderInfo.addr, @@ -739,14 +711,12 @@ func TestDefaultSponsorshipSnapshot(t *testing.T) { expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - isGeneratedByTxDiff: true, + Address: testGlobal.minerInfo.addr, + Balance: 40000, }, &WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, - isGeneratedByTxDiff: true, + Address: testGlobal.senderInfo.addr, + Balance: 299900000, }, &SponsorshipSnapshot{ AssetID: testGlobal.asset0.assetID, @@ -801,14 +771,12 @@ func TestDefaultSetScriptSnapshot(t *testing.T) { expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - isGeneratedByTxDiff: true, + Address: testGlobal.minerInfo.addr, + Balance: 40000, }, &WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, - isGeneratedByTxDiff: true, + Address: testGlobal.senderInfo.addr, + Balance: 299900000, }, &AccountScriptSnapshot{ SenderPublicKey: testGlobal.senderInfo.pk, @@ -870,14 +838,12 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.T) { expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - isGeneratedByTxDiff: true, + Address: testGlobal.minerInfo.addr, + Balance: 40000, }, &WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, - isGeneratedByTxDiff: true, + Address: testGlobal.senderInfo.addr, + Balance: 299900000, }, &AssetScriptSnapshot{ AssetID: testGlobal.asset0.assetID, @@ -986,14 +952,12 @@ func TestDefaultInvokeScriptSnapshot(t *testing.T) { expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 200000, - isGeneratedByTxDiff: true, + Address: testGlobal.minerInfo.addr, + Balance: 200000, }, &WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299500000, - isGeneratedByTxDiff: true, + Address: testGlobal.senderInfo.addr, + Balance: 299500000, }, &DataEntriesSnapshot{ Address: testGlobal.recipientInfo.addr, diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index d19b17dfe..1551c3e59 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -31,13 +31,10 @@ type AtomicSnapshot interface { type WavesBalanceSnapshot struct { Address proto.WavesAddress Balance uint64 - - // temporarily - isGeneratedByTxDiff bool } func (s WavesBalanceSnapshot) IsGeneratedByTxDiff() bool { - return s.isGeneratedByTxDiff + return true } func (s WavesBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyWavesBalance(s) } @@ -46,64 +43,58 @@ type AssetBalanceSnapshot struct { Address proto.WavesAddress AssetID crypto.Digest Balance uint64 - // temporarily - isGeneratedByTxDiff bool } func (s AssetBalanceSnapshot) IsGeneratedByTxDiff() bool { - return s.isGeneratedByTxDiff + return true } func (s AssetBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetBalance(s) } type DataEntriesSnapshot struct { // AccountData in pb - Address proto.WavesAddress - DataEntries []proto.DataEntry - isGeneratedByTxDiff bool + Address proto.WavesAddress + DataEntries []proto.DataEntry } func (s DataEntriesSnapshot) IsGeneratedByTxDiff() bool { - return s.isGeneratedByTxDiff + return false } func (s DataEntriesSnapshot) Apply(a SnapshotApplier) error { return a.ApplyDataEntries(s) } type AccountScriptSnapshot struct { - SenderPublicKey crypto.PublicKey - Script proto.Script - VerifierComplexity uint64 - isGeneratedByTxDiff bool + SenderPublicKey crypto.PublicKey + Script proto.Script + VerifierComplexity uint64 } func (s AccountScriptSnapshot) IsGeneratedByTxDiff() bool { - return s.isGeneratedByTxDiff + return false } func (s AccountScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAccountScript(s) } type AssetScriptSnapshot struct { - AssetID crypto.Digest - Script proto.Script - SenderPK crypto.PublicKey // should be removed later - Complexity uint64 - isGeneratedByTxDiff bool + AssetID crypto.Digest + Script proto.Script + SenderPK crypto.PublicKey // should be removed later + Complexity uint64 } func (s AssetScriptSnapshot) IsGeneratedByTxDiff() bool { - return s.isGeneratedByTxDiff + return false } func (s AssetScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetScript(s) } type LeaseBalanceSnapshot struct { - Address proto.WavesAddress - LeaseIn uint64 - LeaseOut uint64 - isGeneratedByTxDiff bool + Address proto.WavesAddress + LeaseIn uint64 + LeaseOut uint64 } func (s LeaseBalanceSnapshot) IsGeneratedByTxDiff() bool { - return s.isGeneratedByTxDiff + return false } func (s LeaseBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseBalance(s) } @@ -122,49 +113,45 @@ type LeaseStateSnapshot struct { Recipient proto.WavesAddress OriginTransactionID *crypto.Digest Height proto.Height - isGeneratedByTxDiff bool } func (s LeaseStateSnapshot) IsGeneratedByTxDiff() bool { - return s.isGeneratedByTxDiff + return false } func (s LeaseStateSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseState(s) } type SponsorshipSnapshot struct { - AssetID crypto.Digest - MinSponsoredFee uint64 - isGeneratedByTxDiff bool + AssetID crypto.Digest + MinSponsoredFee uint64 } func (s SponsorshipSnapshot) IsGeneratedByTxDiff() bool { - return s.isGeneratedByTxDiff + return false } func (s SponsorshipSnapshot) Apply(a SnapshotApplier) error { return a.ApplySponsorship(s) } type AliasSnapshot struct { - Address proto.WavesAddress - Alias proto.Alias - isGeneratedByTxDiff bool + Address proto.WavesAddress + Alias proto.Alias } func (s AliasSnapshot) IsGeneratedByTxDiff() bool { - return s.isGeneratedByTxDiff + return false } func (s AliasSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAlias(s) } // FilledVolumeFeeSnapshot Filled Volume and Fee. type FilledVolumeFeeSnapshot struct { // OrderFill - OrderID crypto.Digest - FilledVolume uint64 - FilledFee uint64 - isGeneratedByTxDiff bool + OrderID crypto.Digest + FilledVolume uint64 + FilledFee uint64 } func (s FilledVolumeFeeSnapshot) IsGeneratedByTxDiff() bool { - return s.isGeneratedByTxDiff + return false } func (s FilledVolumeFeeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyFilledVolumeAndFee(s) } @@ -175,38 +162,35 @@ type StaticAssetInfoSnapshot struct { IssuerPublicKey crypto.PublicKey Decimals uint8 IsNFT bool - isGeneratedByTxDiff bool } func (s StaticAssetInfoSnapshot) IsGeneratedByTxDiff() bool { - return s.isGeneratedByTxDiff + return false } func (s StaticAssetInfoSnapshot) Apply(a SnapshotApplier) error { return a.ApplyStaticAssetInfo(s) } type AssetVolumeSnapshot struct { // AssetVolume in pb - AssetID crypto.Digest - TotalQuantity big.Int // volume in protobuf - IsReissuable bool - isGeneratedByTxDiff bool + AssetID crypto.Digest + TotalQuantity big.Int // volume in protobuf + IsReissuable bool } func (s AssetVolumeSnapshot) IsGeneratedByTxDiff() bool { - return s.isGeneratedByTxDiff + return false } func (s AssetVolumeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetVolume(s) } type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb - AssetID crypto.Digest - AssetName string - AssetDescription string - ChangeHeight proto.Height // last_updated in pb - isGeneratedByTxDiff bool + AssetID crypto.Digest + AssetName string + AssetDescription string + ChangeHeight proto.Height // last_updated in pb } func (s AssetDescriptionSnapshot) IsGeneratedByTxDiff() bool { - return s.isGeneratedByTxDiff + return false } func (s AssetDescriptionSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetDescription(s) } From fdc87c1a47787bb9e5e5f01151a7b971f9ac750c Mon Sep 17 00:00:00 2001 From: esuwu Date: Thu, 20 Jul 2023 17:01:41 -0500 Subject: [PATCH 049/139] Returned the linter command back --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a96171d42..4712bdbf7 100644 --- a/Makefile +++ b/Makefile @@ -71,7 +71,7 @@ vendor: vetcheck: go vet ./... golangci-lint run -c .golangci.yml -# golangci-lint run -c .golangci-strict.yml --new-from-rev=origin/master + golangci-lint run -c .golangci-strict.yml --new-from-rev=origin/master strict-vet-check: golangci-lint run -c .golangci-strict.yml From 51904b2ff66e4de39d5668461676b9415f879f2d Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Thu, 20 Jul 2023 15:01:55 -0700 Subject: [PATCH 050/139] Replaced current recording to storage to snapshot applier (#1162) * Replaced current recording to storage to snapshot applier * Replaced to snapshot applier, except balances * Fixed a comment * Removed the comment * Removed unnecessary code * Returned the linter command back --- pkg/state/appender.go | 71 +++++++-- pkg/state/fee_validation_test.go | 13 +- pkg/state/snapshot_applier.go | 10 +- pkg/state/snapshot_generator.go | 77 ++-------- pkg/state/snapshot_generator_test.go | 80 +++++----- pkg/state/snapshot_types.go | 72 ++++++++- pkg/state/state.go | 3 +- pkg/state/transaction_checker_test.go | 180 ++++++++++++++--------- pkg/state/transaction_differ_test.go | 128 +++++++++++----- pkg/state/transaction_handler.go | 3 +- pkg/state/transaction_performer.go | 185 ++++++++---------------- pkg/state/transaction_performer_test.go | 144 +++++++++++------- 12 files changed, 560 insertions(+), 406 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index b98f5d550..4cd7fb183 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -337,7 +337,6 @@ func (a *txAppender) commitTxApplication( // Update complexity. a.sc.addRecentTxComplexity() // Save balance diff. - // 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)) } @@ -353,7 +352,6 @@ func (a *txAppender) commitTxApplication( stateActionsCounter: params.stateActionsCounterInBlock, checkerData: applicationRes.checkerData, } - // TODO other snapshots snapshot, err = a.txHandler.performTx(tx, performerInfo, invocationRes, applicationRes.changes.diff) if err != nil { return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to perform: %v", err)) @@ -420,6 +418,9 @@ type appendTxParams struct { validatingUtx bool // if validatingUtx == false then chans MUST be initialized with non nil value stateActionsCounterInBlock *proto.StateActionsCounter currentMinerPK crypto.PublicKey + + snapshotGenerator *snapshotGenerator + snapshotApplier SnapshotApplier } func (a *txAppender) handleInvokeOrExchangeTransaction(tx proto.Transaction, fallibleInfo *fallibleValidationParams) (*invocationResult, *applicationResult, error) { @@ -454,6 +455,9 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro a.stor.dropUncertain() }() + a.txHandler.tp.snapshotGenerator = params.snapshotGenerator + a.txHandler.tp.snapshotApplier = params.snapshotApplier + blockID := params.checkerInfo.blockID // Check that Protobuf transactions are accepted. if err := a.checkProtobufVersion(tx, params.blockV5Activated); err != nil { @@ -632,6 +636,27 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { if hasParent { checkerInfo.parentTimestamp = params.parent.Timestamp } + stateActionsCounterInBlock := new(proto.StateActionsCounter) + + snapshotApplier := newBlockSnapshotsApplier( + blockSnapshotsApplierInfo{ + ci: checkerInfo, + scheme: a.settings.AddressSchemeCharacter, + stateActionsCounter: stateActionsCounterInBlock, + }, + snapshotApplierStorages{ + balances: a.stor.balances, + aliases: a.stor.aliases, + assets: a.stor.assets, + scriptsStorage: a.stor.scriptsStorage, + scriptsComplexity: a.stor.scriptsComplexity, + sponsoredAssets: a.stor.sponsoredAssets, + ordersVolumes: a.stor.ordersVolumes, + accountsDataStor: a.stor.accountsDataStor, + leases: a.stor.leases, + }, + ) + snapshotGenerator := snapshotGenerator{stor: a.stor, scheme: a.settings.AddressSchemeCharacter} // Create miner balance diff. // This adds 60% of prev block fees as very first balance diff of the current block @@ -641,15 +666,15 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { return err } // create the initial snapshot - initialSnapshot, err := a.createInitialBlockSnapshot(minerAndRewardDiff) + _, 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. + + // TODO apply this snapshot when balances are refatored + //err = initialSnapshot.Apply(&snapshotApplier) + + // Save miner diff first (for validation) if err := a.diffStor.saveTxDiff(minerAndRewardDiff); err != nil { return err } @@ -673,8 +698,8 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { if err != nil { return err } - stateActionsCounterInBlock := new(proto.StateActionsCounter) // Check and append transactions. + for _, tx := range params.transactions { appendTxArgs := &appendTxParams{ chans: params.chans, @@ -691,6 +716,8 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { validatingUtx: false, stateActionsCounterInBlock: stateActionsCounterInBlock, currentMinerPK: params.block.GeneratorPublicKey, + snapshotGenerator: &snapshotGenerator, + snapshotApplier: &snapshotApplier, } if err := a.appendTx(tx, appendTxArgs); err != nil { return err @@ -704,6 +731,7 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { return nil } +// used only in tests now. All diffs are applied in snapshotApplier func (a *txAppender) applyAllDiffs() error { a.recentTxIds = make(map[string]struct{}) return a.moveChangesToHistoryStorage() @@ -931,6 +959,27 @@ func (a *txAppender) validateNextTx(tx proto.Transaction, currentTimestamp, pare if err != nil { return errs.Extend(err, "failed to check 'InvokeExpression' is activated") // TODO: check feature naming in err message } + actionsCounter := new(proto.StateActionsCounter) + snapshotApplier := newBlockSnapshotsApplier( + blockSnapshotsApplierInfo{ + ci: checkerInfo, + scheme: a.settings.AddressSchemeCharacter, + stateActionsCounter: actionsCounter, + }, + snapshotApplierStorages{ + balances: a.stor.balances, + aliases: a.stor.aliases, + assets: a.stor.assets, + scriptsStorage: a.stor.scriptsStorage, + scriptsComplexity: a.stor.scriptsComplexity, + sponsoredAssets: a.stor.sponsoredAssets, + ordersVolumes: a.stor.ordersVolumes, + accountsDataStor: a.stor.accountsDataStor, + leases: a.stor.leases, + }, + ) + snapshotGenerator := snapshotGenerator{stor: a.stor, scheme: a.settings.AddressSchemeCharacter} + appendTxArgs := &appendTxParams{ chans: nil, // nil because validatingUtx == true checkerInfo: checkerInfo, @@ -945,7 +994,9 @@ func (a *txAppender) validateNextTx(tx proto.Transaction, currentTimestamp, pare invokeExpressionActivated: invokeExpressionActivated, validatingUtx: true, // it's correct to use new counter because there's no block exists, but this field is necessary in tx performer - stateActionsCounterInBlock: new(proto.StateActionsCounter), + stateActionsCounterInBlock: actionsCounter, + snapshotGenerator: &snapshotGenerator, + snapshotApplier: &snapshotApplier, } err = a.appendTx(tx, appendTxArgs) if err != nil { diff --git a/pkg/state/fee_validation_test.go b/pkg/state/fee_validation_test.go index 0bd676dc0..6924f1aca 100644 --- a/pkg/state/fee_validation_test.go +++ b/pkg/state/fee_validation_test.go @@ -50,11 +50,11 @@ The account script is set on blockID2, then rollback returns storage to the bloc The account must not have a verifier anymore. However, the filter is false, so invalid data (verifier) will be returned\ */ func TestAccountHasVerifierAfterRollbackFilterFalse(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) to.stor.hs.amend = false tx := createSetScriptWithProofs(t) - info := defaultCheckerInfo() to.stor.activateFeature(t, int16(settings.SmartAccounts)) @@ -66,8 +66,9 @@ func TestAccountHasVerifierAfterRollbackFilterFalse(t *testing.T) { address, err := proto.NewAddressFromPublicKey(to.tc.settings.AddressSchemeCharacter, tx.SenderPK) assert.NoError(t, err, "failed to receive an address from public key") - txPerformerInfo := defaultPerformerInfo() + txPerformerInfo := defaultPerformerInfo(to.stateActionsCounter) txPerformerInfo.blockID = blockID2 + info.blockID = blockID2 // the block from checker info is used by snapshot applier to apply a tx txPerformerInfo.checkerData = checkerData _, err = to.tp.performSetScriptWithProofs(tx, txPerformerInfo, nil, nil) @@ -89,7 +90,8 @@ func TestAccountHasVerifierAfterRollbackFilterFalse(t *testing.T) { // the account script is set on blockID2, then blockID3 is added, then rollback returns storage to the blockID1. // The account must not have a verifier anymore. Filter is true, so everything must be valid func TestAccountDoesNotHaveScriptAfterRollbackFilterTrue(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) to.stor.hs.amend = true tx := createSetScriptWithProofs(t) @@ -102,8 +104,9 @@ func TestAccountDoesNotHaveScriptAfterRollbackFilterTrue(t *testing.T) { address, err := proto.NewAddressFromPublicKey(to.tc.settings.AddressSchemeCharacter, tx.SenderPK) assert.NoError(t, err, "failed to receive an address from public key") - txPerformerInfo := defaultPerformerInfo() + txPerformerInfo := defaultPerformerInfo(to.stateActionsCounter) txPerformerInfo.blockID = blockID2 + info.blockID = blockID2 // the block from checker info is used by snapshot applier to apply a tx txPerformerInfo.checkerData.scriptEstimations = &scriptsEstimations{} _, err = to.tp.performSetScriptWithProofs(tx, txPerformerInfo, nil, nil) diff --git a/pkg/state/snapshot_applier.go b/pkg/state/snapshot_applier.go index 1fb25cc0a..babf78c82 100644 --- a/pkg/state/snapshot_applier.go +++ b/pkg/state/snapshot_applier.go @@ -169,11 +169,11 @@ func (a *blockSnapshotsApplier) ApplyAssetScript(snapshot AssetScriptSnapshot) e if err := a.stor.scriptsComplexity.saveComplexitiesForAsset(snapshot.AssetID, estimation, a.info.BlockID()); err != nil { return errors.Wrapf(err, "failed to store asset script estimation for asset %q", snapshot.AssetID.String()) } - constInfo, err := a.stor.assets.newestConstInfo(proto.AssetIDFromDigest(snapshot.AssetID)) // only issuer can set new asset script - if err != nil { - return errors.Wrapf(err, "failed to get const asset info for asset %q", snapshot.AssetID.String()) - } - return a.stor.scriptsStorage.setAssetScript(snapshot.AssetID, snapshot.Script, constInfo.issuer, a.info.BlockID()) + //constInfo, err := a.stor.assets.newestConstInfo(proto.AssetIDFromDigest(snapshot.AssetID)) // only issuer can set new asset script + //if err != nil { + // return errors.Wrapf(err, "failed to get const asset info for asset %q", snapshot.AssetID.String()) + //} + return a.stor.scriptsStorage.setAssetScript(snapshot.AssetID, snapshot.Script, snapshot.SenderPK, a.info.BlockID()) } func (a *blockSnapshotsApplier) ApplySponsorship(snapshot SponsorshipSnapshot) error { diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index 2504335ef..ea6d0ecc8 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -4,13 +4,12 @@ import ( "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" - "github.com/wavesplatform/gowaves/pkg/settings" "math/big" ) type snapshotGenerator struct { - stor *blockchainEntitiesStorage - settings *settings.BlockchainSettings + stor *blockchainEntitiesStorage + scheme proto.Scheme } type assetBalanceDiffKey struct { @@ -22,23 +21,14 @@ type addressWavesBalanceDiff map[proto.WavesAddress]balanceDiff type addressAssetBalanceDiff map[assetBalanceDiffKey]int64 func (sg *snapshotGenerator) generateSnapshotForGenesisTx(balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } return sg.generateBalancesSnapshot(balanceChanges) } func (sg *snapshotGenerator) generateSnapshotForPaymentTx(balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } return sg.generateBalancesSnapshot(balanceChanges) } func (sg *snapshotGenerator) generateSnapshotForTransferTx(balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } return sg.generateBalancesSnapshot(balanceChanges) } @@ -48,12 +38,8 @@ type scriptInformation struct { } func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, txID crypto.Digest, senderPK crypto.PublicKey, assetInfo assetInfo, balanceChanges txDiff, scriptInformation *scriptInformation) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } var snapshot TransactionSnapshot - // TODO add asset script snapshot - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.settings.AddressSchemeCharacter) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.scheme) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") } @@ -123,9 +109,6 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t } func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, change assetReissueChange, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } quantityDiff := big.NewInt(change.diff) assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) if err != nil { @@ -147,9 +130,6 @@ func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, } func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, change assetBurnChange, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } quantityDiff := big.NewInt(change.diff) assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) if err != nil { @@ -171,9 +151,6 @@ func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, ch } func (sg *snapshotGenerator) generateSnapshotForExchangeTx(sellOrder proto.Order, sellFee uint64, buyOrder proto.Order, buyFee uint64, volume uint64, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") @@ -201,9 +178,6 @@ func (sg *snapshotGenerator) generateSnapshotForExchangeTx(sellOrder proto.Order } func (sg *snapshotGenerator) generateSnapshotForLeaseTx(lease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } var err error snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { @@ -220,9 +194,6 @@ func (sg *snapshotGenerator) generateSnapshotForLeaseTx(lease leasing, leaseID c } func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Digest, oldLease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, cancelHeight uint64, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } var err error snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { @@ -244,9 +215,6 @@ func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Diges } func (sg *snapshotGenerator) generateSnapshotForCreateAliasTx(senderAddress proto.WavesAddress, alias proto.Alias, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -260,16 +228,10 @@ func (sg *snapshotGenerator) generateSnapshotForCreateAliasTx(senderAddress prot } func (sg *snapshotGenerator) generateSnapshotForMassTransferTx(balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } return sg.generateBalancesSnapshot(balanceChanges) } func (sg *snapshotGenerator) generateSnapshotForDataTx(senderAddress proto.WavesAddress, entries []proto.DataEntry, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -283,9 +245,6 @@ func (sg *snapshotGenerator) generateSnapshotForDataTx(senderAddress proto.Waves } func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Digest, minAssetFee uint64, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -299,9 +258,6 @@ func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Dig } func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.PublicKey, script proto.Script, complexity int, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -316,10 +272,7 @@ func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.Publ return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, complexity int, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } +func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, complexity int, senderPK crypto.PublicKey, balanceChanges txDiff) (TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -329,6 +282,7 @@ func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto. AssetID: assetID, Script: script, Complexity: uint64(complexity), + SenderPK: senderPK, } snapshot = append(snapshot, sponsorshipSnapshot) return snapshot, nil @@ -347,9 +301,6 @@ func (sg *snapshotGenerator) generateSnapshotForEthereumInvokeScriptTx(txID cryp } func (sg *snapshotGenerator) generateSnapshotForUpdateAssetInfoTx(assetID crypto.Digest, assetName string, assetDescription string, changeHeight proto.Height, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { @@ -374,7 +325,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( blockHeight := info.height + 1 - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.settings.AddressSchemeCharacter) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.scheme) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") } @@ -386,7 +337,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( switch a := action.(type) { case *proto.DataEntryScriptAction: - senderAddr, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) + senderAddr, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) if err != nil { return nil, err } @@ -400,7 +351,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( } case *proto.AttachedPaymentScriptAction: - senderAddress, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) + senderAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) if err != nil { return nil, errors.Wrap(err, "failed to get an address from a public key") } @@ -415,7 +366,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( addToWavesBalanceDiff(addrWavesBalanceDiff, senderAddress, recipientAddress, a.Amount) } case *proto.TransferScriptAction: - senderAddress, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) + senderAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) if err != nil { return nil, errors.Wrap(err, "failed to get an address from a public key") } @@ -452,7 +403,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( reissuable: a.Reissuable, }, } - issuerAddress, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) + issuerAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) if err != nil { return nil, errors.Wrap(err, "failed to get an address from a public key") } @@ -495,7 +446,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( IsReissuable: a.Reissuable, } - issueAddress, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) + issueAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) if err != nil { return nil, errors.Wrap(err, "failed to get an address from a public key") } @@ -515,14 +466,14 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( IsReissuable: assetInfo.reissuable, } - issueAddress, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) + issueAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *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(sg.settings.AddressSchemeCharacter, *a.Sender) + senderAddr, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) if err != nil { return nil, err } @@ -643,7 +594,7 @@ func (sg *snapshotGenerator) generateOrderAtomicSnapshot(orderID []byte, volume func (sg *snapshotGenerator) generateBalancesSnapshot(balanceChanges txDiff) (TransactionSnapshot, error) { var transactionSnapshot TransactionSnapshot - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.settings.AddressSchemeCharacter) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.scheme) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") } diff --git a/pkg/state/snapshot_generator_test.go b/pkg/state/snapshot_generator_test.go index a652ef035..104e9de65 100644 --- a/pkg/state/snapshot_generator_test.go +++ b/pkg/state/snapshot_generator_test.go @@ -36,7 +36,7 @@ func defaultPerformerInfoWithChecker(checkerData txCheckerData) *performerInfo { return &performerInfo{0, blockID0, proto.WavesAddress{}, new(proto.StateActionsCounter), checkerData} } -func defaultCheckerInfoHeight() *checkerInfo { +func customCheckerInfo() *checkerInfo { defaultBlockInfo := defaultBlockInfo() return &checkerInfo{ currentTimestamp: defaultBlockInfo.Timestamp, @@ -47,17 +47,15 @@ func defaultCheckerInfoHeight() *checkerInfo { } } -func createCheckerCustomTestObjects(t *testing.T, stor *testStorageObjects) *checkerTestObjects { - tc, err := newTransactionChecker(proto.NewBlockIDFromSignature(genSig), stor.entities, settings.MainNetSettings) +func createCheckerCustomTestObjects(t *testing.T, differ *differTestObjects) *checkerTestObjects { + tc, err := newTransactionChecker(proto.NewBlockIDFromSignature(genSig), differ.stor.entities, settings.MainNetSettings) require.NoError(t, err, "newTransactionChecker() failed") - snapshotGenerator := &snapshotGenerator{stor: stor.entities, settings: settings.MainNetSettings} - tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) - require.NoError(t, err, "newTransactionPerformer() failed") - return &checkerTestObjects{stor, tc, tp} + return &checkerTestObjects{differ.stor, tc, differ.tp, differ.stateActionsCounter} } func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -72,7 +70,7 @@ func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { ch, err := to.td.createDiffTransferWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffTransferWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performTransferWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performTransferWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform transfer tx") expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ @@ -111,7 +109,8 @@ func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { // TODO send only txBalanceChanges to perfomer func TestDefaultIssueTransactionSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -124,7 +123,7 @@ func TestDefaultIssueTransactionSnapshot(t *testing.T) { ch, err := to.td.createDiffIssueWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffIssueWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform issue tx") expectedSnapshot := TransactionSnapshot{ @@ -180,7 +179,8 @@ func TestDefaultIssueTransactionSnapshot(t *testing.T) { } func TestDefaultReissueSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -198,7 +198,7 @@ func TestDefaultReissueSnapshot(t *testing.T) { ch, err := to.td.createDiffReissueWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffReissueWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform reissue tx") expectedSnapshot := TransactionSnapshot{ @@ -243,7 +243,8 @@ func TestDefaultReissueSnapshot(t *testing.T) { } func TestDefaultBurnSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -261,7 +262,7 @@ func TestDefaultBurnSnapshot(t *testing.T) { ch, err := to.td.createDiffBurnWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -306,7 +307,8 @@ func TestDefaultBurnSnapshot(t *testing.T) { } func TestDefaultExchangeTransaction(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -345,7 +347,7 @@ func TestDefaultExchangeTransaction(t *testing.T) { ch, err := to.td.createDiffExchange(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performExchange(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performExchange(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -418,7 +420,8 @@ func TestDefaultExchangeTransaction(t *testing.T) { } func TestDefaultLeaseSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -432,7 +435,7 @@ func TestDefaultLeaseSnapshot(t *testing.T) { ch, err := to.td.createDiffLeaseWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -488,7 +491,8 @@ func TestDefaultLeaseSnapshot(t *testing.T) { } func TestDefaultLeaseCancelSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -516,7 +520,7 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { ch, err := to.td.createDiffLeaseCancelWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -573,7 +577,8 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { } func TestDefaultCreateAliasSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -587,7 +592,7 @@ func TestDefaultCreateAliasSnapshot(t *testing.T) { ch, err := to.td.createDiffCreateAliasWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -626,7 +631,8 @@ func TestDefaultCreateAliasSnapshot(t *testing.T) { } func TestDefaultDataSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -646,7 +652,7 @@ func TestDefaultDataSnapshot(t *testing.T) { ch, err := to.td.createDiffDataWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -685,7 +691,8 @@ func TestDefaultDataSnapshot(t *testing.T) { } func TestDefaultSponsorshipSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -699,7 +706,7 @@ func TestDefaultSponsorshipSnapshot(t *testing.T) { ch, err := to.td.createDiffSponsorshipWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -738,7 +745,8 @@ func TestDefaultSponsorshipSnapshot(t *testing.T) { } func TestDefaultSetScriptSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -750,8 +758,7 @@ func TestDefaultSetScriptSnapshot(t *testing.T) { 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 := createCheckerCustomTestObjects(t, to) co.stor = to.stor checkerData, err := co.tc.checkSetScriptWithProofs(tx, checkerInfo) assert.NoError(t, err, "failed to check set script tx") @@ -799,7 +806,8 @@ func TestDefaultSetScriptSnapshot(t *testing.T) { } func TestDefaultSetAssetScriptSnapshot(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -817,8 +825,7 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.T) { 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 := createCheckerCustomTestObjects(t, to) co.stor = to.stor checkerData, err := co.tc.checkSetAssetScriptWithProofs(tx, checkerInfo) assert.NoError(t, err, "failed to check set script tx") @@ -842,6 +849,7 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.T) { AssetID: testGlobal.asset0.assetID, Script: testGlobal.scriptBytes, Complexity: 340, + SenderPK: tx.SenderPK, }, } @@ -895,7 +903,8 @@ func TestDefaultInvokeScriptSnapshot(t *testing.T) { scriptsBytes, err := base64.StdEncoding.DecodeString(script) assert.NoError(t, err, "failed to set decode base64 script") - to := createDifferTestObjects(t) + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -915,8 +924,7 @@ func TestDefaultInvokeScriptSnapshot(t *testing.T) { 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 := createCheckerCustomTestObjects(t, to) co.stor = to.stor checkerData, err := co.tc.checkInvokeScriptWithProofs(tx, checkerInfo) assert.NoError(t, err, "failed to check invoke script tx") diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 6ff55ec17..1551c3e59 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -1,6 +1,7 @@ package state import ( + "github.com/pkg/errors" "math/big" "github.com/wavesplatform/gowaves/pkg/crypto" @@ -9,13 +10,33 @@ import ( type TransactionSnapshot []AtomicSnapshot -type AtomicSnapshot interface{ Apply(SnapshotApplier) error } +func (ts TransactionSnapshot) Apply(a SnapshotApplier) error { + for _, atomicSnapshot := range ts { + if !atomicSnapshot.IsGeneratedByTxDiff() { + err := atomicSnapshot.Apply(a) + if err != nil { + return errors.Wrap(err, "failed to apply transaction snapshot") + } + } + } + return nil +} + +type AtomicSnapshot interface { + Apply(SnapshotApplier) error + /*is temporarily used to mark snapshots generated by tx diff that shouldn't be applied , because balances diffs are applied later in the block */ + IsGeneratedByTxDiff() bool +} type WavesBalanceSnapshot struct { Address proto.WavesAddress Balance uint64 } +func (s WavesBalanceSnapshot) IsGeneratedByTxDiff() bool { + return true +} + func (s WavesBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyWavesBalance(s) } type AssetBalanceSnapshot struct { @@ -24,6 +45,10 @@ type AssetBalanceSnapshot struct { Balance uint64 } +func (s AssetBalanceSnapshot) IsGeneratedByTxDiff() bool { + return true +} + func (s AssetBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetBalance(s) } type DataEntriesSnapshot struct { // AccountData in pb @@ -31,6 +56,10 @@ type DataEntriesSnapshot struct { // AccountData in pb DataEntries []proto.DataEntry } +func (s DataEntriesSnapshot) IsGeneratedByTxDiff() bool { + return false +} + func (s DataEntriesSnapshot) Apply(a SnapshotApplier) error { return a.ApplyDataEntries(s) } type AccountScriptSnapshot struct { @@ -39,14 +68,23 @@ type AccountScriptSnapshot struct { VerifierComplexity uint64 } +func (s AccountScriptSnapshot) IsGeneratedByTxDiff() bool { + return false +} + func (s AccountScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAccountScript(s) } type AssetScriptSnapshot struct { AssetID crypto.Digest Script proto.Script + SenderPK crypto.PublicKey // should be removed later Complexity uint64 } +func (s AssetScriptSnapshot) IsGeneratedByTxDiff() bool { + return false +} + func (s AssetScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetScript(s) } type LeaseBalanceSnapshot struct { @@ -55,6 +93,10 @@ type LeaseBalanceSnapshot struct { LeaseOut uint64 } +func (s LeaseBalanceSnapshot) IsGeneratedByTxDiff() bool { + return false +} + func (s LeaseBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseBalance(s) } type LeaseStateStatus struct { @@ -73,6 +115,10 @@ type LeaseStateSnapshot struct { Height proto.Height } +func (s LeaseStateSnapshot) IsGeneratedByTxDiff() bool { + return false +} + func (s LeaseStateSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseState(s) } type SponsorshipSnapshot struct { @@ -80,6 +126,10 @@ type SponsorshipSnapshot struct { MinSponsoredFee uint64 } +func (s SponsorshipSnapshot) IsGeneratedByTxDiff() bool { + return false +} + func (s SponsorshipSnapshot) Apply(a SnapshotApplier) error { return a.ApplySponsorship(s) } type AliasSnapshot struct { @@ -87,6 +137,10 @@ type AliasSnapshot struct { Alias proto.Alias } +func (s AliasSnapshot) IsGeneratedByTxDiff() bool { + return false +} + func (s AliasSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAlias(s) } // FilledVolumeFeeSnapshot Filled Volume and Fee. @@ -96,6 +150,10 @@ type FilledVolumeFeeSnapshot struct { // OrderFill FilledFee uint64 } +func (s FilledVolumeFeeSnapshot) IsGeneratedByTxDiff() bool { + return false +} + func (s FilledVolumeFeeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyFilledVolumeAndFee(s) } type StaticAssetInfoSnapshot struct { @@ -106,6 +164,10 @@ type StaticAssetInfoSnapshot struct { IsNFT bool } +func (s StaticAssetInfoSnapshot) IsGeneratedByTxDiff() bool { + return false +} + func (s StaticAssetInfoSnapshot) Apply(a SnapshotApplier) error { return a.ApplyStaticAssetInfo(s) } type AssetVolumeSnapshot struct { // AssetVolume in pb @@ -114,6 +176,10 @@ type AssetVolumeSnapshot struct { // AssetVolume in pb IsReissuable bool } +func (s AssetVolumeSnapshot) IsGeneratedByTxDiff() bool { + return false +} + func (s AssetVolumeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetVolume(s) } type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb @@ -123,6 +189,10 @@ type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb ChangeHeight proto.Height // last_updated in pb } +func (s AssetDescriptionSnapshot) IsGeneratedByTxDiff() bool { + return false +} + func (s AssetDescriptionSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetDescription(s) } type SnapshotApplier interface { diff --git a/pkg/state/state.go b/pkg/state/state.go index cb8febbf9..2206e36a5 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -1272,7 +1272,7 @@ func (s *stateManager) needToCancelLeases(blockchainHeight uint64) (bool, error) } } -// TODO generate snapshots here too +// TODO what to do with stolen aliases in snapshots? func (s *stateManager) blockchainHeightAction(blockchainHeight uint64, lastBlock, nextBlock proto.BlockID) error { cancelLeases, err := s.needToCancelLeases(blockchainHeight) if err != nil { @@ -1524,6 +1524,7 @@ func (s *stateManager) addBlocks() (*proto.Block, error) { if err := s.appender.applyAllDiffs(); err != nil { return nil, err } + // Retrieve and store state hashes for each of new blocks. if err := s.stor.handleStateHashes(height, ids); err != nil { return nil, wrapErr(ModificationError, err) diff --git a/pkg/state/transaction_checker_test.go b/pkg/state/transaction_checker_test.go index 101ac9b97..ff7f81942 100644 --- a/pkg/state/transaction_checker_test.go +++ b/pkg/state/transaction_checker_test.go @@ -21,19 +21,43 @@ var ( ) type checkerTestObjects struct { - stor *testStorageObjects - tc *transactionChecker - tp *transactionPerformer + stor *testStorageObjects + tc *transactionChecker + tp *transactionPerformer + stateActionsCounter *proto.StateActionsCounter } -func createCheckerTestObjects(t *testing.T) *checkerTestObjects { +func createCheckerTestObjects(t *testing.T, checkerInfo *checkerInfo) *checkerTestObjects { stor := createStorageObjects(t, true) tc, err := newTransactionChecker(proto.NewBlockIDFromSignature(genSig), stor.entities, settings.MainNetSettings) require.NoError(t, err, "newTransactionChecker() failed") - snapshotGenerator := &snapshotGenerator{stor: stor.entities, settings: settings.MainNetSettings} - tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) + + actionsCounter := new(proto.StateActionsCounter) + snapshotApplier := newBlockSnapshotsApplier( + blockSnapshotsApplierInfo{ + ci: checkerInfo, + scheme: settings.MainNetSettings.AddressSchemeCharacter, + stateActionsCounter: actionsCounter, + }, + snapshotApplierStorages{ + balances: stor.entities.balances, + aliases: stor.entities.aliases, + assets: stor.entities.assets, + scriptsStorage: stor.entities.scriptsStorage, + scriptsComplexity: stor.entities.scriptsComplexity, + sponsoredAssets: stor.entities.sponsoredAssets, + ordersVolumes: stor.entities.ordersVolumes, + accountsDataStor: stor.entities.accountsDataStor, + leases: stor.entities.leases, + }, + ) + snapshotGenerator := snapshotGenerator{stor: stor.entities, scheme: settings.MainNetSettings.AddressSchemeCharacter} + + tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings) + tp.snapshotApplier = &snapshotApplier + tp.snapshotGenerator = &snapshotGenerator require.NoError(t, err, "newTransactionPerformer() failed") - return &checkerTestObjects{stor, tc, tp} + return &checkerTestObjects{stor, tc, tp, actionsCounter} } func defaultCheckerInfo() *checkerInfo { @@ -47,10 +71,11 @@ func defaultCheckerInfo() *checkerInfo { } func TestCheckGenesis(t *testing.T) { - to := createCheckerTestObjects(t) - tx := createGenesis() info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) + + tx := createGenesis() _, err := to.tc.checkGenesis(tx, info) assert.EqualError(t, err, "genesis transaction inside of non-genesis block") @@ -69,10 +94,11 @@ func TestCheckGenesis(t *testing.T) { } func TestCheckPayment(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createPayment(t) - info := defaultCheckerInfo() + info.height = settings.MainNetSettings.BlockVersion3AfterHeight _, err := to.tc.checkPayment(tx, info) assert.Error(t, err, "checkPayment accepted payment tx after Block v3 height") @@ -86,10 +112,10 @@ func TestCheckPayment(t *testing.T) { } func TestCheckTransferWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createTransferWithSig(t) - info := defaultCheckerInfo() assetId := tx.FeeAsset.ID @@ -124,10 +150,10 @@ func TestCheckTransferWithSig(t *testing.T) { } func TestCheckTransferWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createTransferWithProofs(t) - info := defaultCheckerInfo() assetId := tx.FeeAsset.ID @@ -169,7 +195,8 @@ func TestCheckTransferWithProofs(t *testing.T) { } func TestCheckIsValidUtf8(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) err := to.tc.isValidUtf8("just a normal string") assert.NoError(t, err) @@ -187,10 +214,11 @@ func TestCheckIsValidUtf8(t *testing.T) { } func TestCheckIssueWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createIssueWithSig(t, 1000) - info := defaultCheckerInfo() + _, err := to.tc.checkIssueWithSig(tx, info) assert.NoError(t, err, "checkIssueWithSig failed with valid issue tx") @@ -200,10 +228,11 @@ func TestCheckIssueWithSig(t *testing.T) { } func TestCheckIssueWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createIssueWithProofs(t, 1000) - info := defaultCheckerInfo() + to.stor.addBlock(t, blockID0) _, err := to.tc.checkIssueWithProofs(tx, info) @@ -215,13 +244,14 @@ func TestCheckIssueWithProofs(t *testing.T) { } func TestCheckReissueWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithSig(t, 1000) tx.SenderPK = assetInfo.issuer - info := defaultCheckerInfo() + info.currentTimestamp = settings.MainNetSettings.ReissueBugWindowTimeEnd + 1 _, err := to.tc.checkReissueWithSig(tx, info) assert.NoError(t, err, "checkReissueWithSig failed with valid reissue tx") @@ -246,7 +276,7 @@ func TestCheckReissueWithSig(t *testing.T) { tx.SenderPK = assetInfo.issuer tx.Reissuable = false - _, err = to.tp.performReissueWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performReissueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performReissueWithSig failed") to.stor.addBlock(t, blockID0) to.stor.flush(t) @@ -257,13 +287,14 @@ func TestCheckReissueWithSig(t *testing.T) { } func TestCheckReissueWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithProofs(t, 1000) tx.SenderPK = assetInfo.issuer - info := defaultCheckerInfo() + info.currentTimestamp = settings.MainNetSettings.ReissueBugWindowTimeEnd + 1 _, err := to.tc.checkReissueWithProofs(tx, info) @@ -294,7 +325,7 @@ func TestCheckReissueWithProofs(t *testing.T) { tx.SenderPK = assetInfo.issuer tx.Reissuable = false - _, err = to.tp.performReissueWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performReissueWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performReissueWithProofs failed") to.stor.addBlock(t, blockID0) to.stor.flush(t) @@ -305,12 +336,12 @@ func TestCheckReissueWithProofs(t *testing.T) { } func TestCheckBurnWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithSig(t) tx.SenderPK = assetInfo.issuer - info := defaultCheckerInfo() _, err := to.tc.checkBurnWithSig(tx, info) assert.NoError(t, err, "checkBurnWithSig failed with valid burn tx") @@ -339,12 +370,12 @@ func TestCheckBurnWithSig(t *testing.T) { } func TestCheckBurnWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithProofs(t) tx.SenderPK = assetInfo.issuer - info := defaultCheckerInfo() _, err := to.tc.checkBurnWithProofs(tx, info) assert.Error(t, err, "checkBurnWithProofs did not fail prior to SmartAccounts activation") @@ -378,10 +409,11 @@ func TestCheckBurnWithProofs(t *testing.T) { } func TestCheckExchangeWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createExchangeWithSig(t) - info := defaultCheckerInfo() + _, err := to.tc.checkExchangeWithSig(tx, info) assert.Error(t, err, "checkExchangeWithSig did not fail with exchange with unknown assets") @@ -444,10 +476,11 @@ func TestCheckExchangeWithSig(t *testing.T) { } func TestCheckExchangeWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) txOV2 := createExchangeWithProofs(t) - info := defaultCheckerInfo() + _, err := to.tc.checkExchangeWithProofs(txOV2, info) assert.Error(t, err, "checkExchangeWithProofs did not fail with exchange with unknown assets") @@ -539,10 +572,10 @@ func TestCheckExchangeWithProofs(t *testing.T) { } func TestCheckUnorderedExchangeV2WithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createUnorderedExchangeWithProofs(t, 2) - info := defaultCheckerInfo() to.stor.createAsset(t, testGlobal.asset0.asset.ID) to.stor.createAsset(t, testGlobal.asset1.asset.ID) @@ -558,10 +591,10 @@ func TestCheckUnorderedExchangeV2WithProofs(t *testing.T) { } func TestCheckUnorderedExchangeV3WithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createUnorderedExchangeWithProofs(t, 3) - info := defaultCheckerInfo() to.stor.createAsset(t, testGlobal.asset0.asset.ID) to.stor.createAsset(t, testGlobal.asset1.asset.ID) @@ -577,10 +610,11 @@ func TestCheckUnorderedExchangeV3WithProofs(t *testing.T) { } func TestCheckLeaseWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createLeaseWithSig(t) - info := defaultCheckerInfo() + tx.Recipient = proto.NewRecipientFromAddress(testGlobal.senderInfo.addr) _, err := to.tc.checkLeaseWithSig(tx, info) assert.Error(t, err, "checkLeaseWithSig did not fail when leasing to self") @@ -591,10 +625,11 @@ func TestCheckLeaseWithSig(t *testing.T) { } func TestCheckLeaseWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createLeaseWithProofs(t) - info := defaultCheckerInfo() + tx.Recipient = proto.NewRecipientFromAddress(testGlobal.senderInfo.addr) _, err := to.tc.checkLeaseWithProofs(tx, info) assert.Error(t, err, "checkLeaseWithProofs did not fail when leasing to self") @@ -611,10 +646,11 @@ func TestCheckLeaseWithProofs(t *testing.T) { } func TestCheckLeaseCancelWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) leaseTx := createLeaseWithSig(t) - info := defaultCheckerInfo() + info.currentTimestamp = settings.MainNetSettings.AllowMultipleLeaseCancelUntilTime + 1 tx := createLeaseCancelWithSig(t, *leaseTx.ID) @@ -622,7 +658,7 @@ func TestCheckLeaseCancelWithSig(t *testing.T) { assert.Error(t, err, "checkLeaseCancelWithSig did not fail when cancelling nonexistent lease") to.stor.addBlock(t, blockID0) - _, err = to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseWithSig failed") to.stor.flush(t) @@ -639,10 +675,11 @@ func TestCheckLeaseCancelWithSig(t *testing.T) { } func TestCheckLeaseCancelWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) leaseTx := createLeaseWithProofs(t) - info := defaultCheckerInfo() + info.currentTimestamp = settings.MainNetSettings.AllowMultipleLeaseCancelUntilTime + 1 tx := createLeaseCancelWithProofs(t, *leaseTx.ID) @@ -650,7 +687,7 @@ func TestCheckLeaseCancelWithProofs(t *testing.T) { assert.Error(t, err, "checkLeaseCancelWithProofs did not fail when cancelling nonexistent lease") to.stor.addBlock(t, blockID0) - _, err = to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseWithProofs failed") to.stor.flush(t) @@ -666,7 +703,7 @@ func TestCheckLeaseCancelWithProofs(t *testing.T) { _, err = to.tc.checkLeaseCancelWithProofs(tx, info) assert.NoError(t, err, "checkLeaseCancelWithProofs failed with valid leaseCancel tx") - _, err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseCancelWithProofs() failed") _, err = to.tc.checkLeaseCancelWithProofs(tx, info) @@ -674,16 +711,16 @@ func TestCheckLeaseCancelWithProofs(t *testing.T) { } func TestCheckCreateAliasWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createCreateAliasWithSig(t) - info := defaultCheckerInfo() _, err := to.tc.checkCreateAliasWithSig(tx, info) assert.NoError(t, err, "checkCreateAliasWithSig failed with valid createAlias tx") to.stor.addBlock(t, blockID0) - _, err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performCreateAliasWithSig failed") to.stor.flush(t) @@ -697,10 +734,10 @@ func TestCheckCreateAliasWithSig(t *testing.T) { } func TestCheckCreateAliasWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createCreateAliasWithProofs(t) - info := defaultCheckerInfo() _, err := to.tc.checkCreateAliasWithProofs(tx, info) assert.Error(t, err, "checkCreateAliasWithProofs did not fail prior to SmartAccounts activation") @@ -711,7 +748,7 @@ func TestCheckCreateAliasWithProofs(t *testing.T) { assert.NoError(t, err, "checkCreateAliasWithProofs failed with valid createAlias tx") to.stor.addBlock(t, blockID0) - _, err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performCreateAliasWithProofs failed") to.stor.flush(t) @@ -725,12 +762,12 @@ func TestCheckCreateAliasWithProofs(t *testing.T) { } func TestCheckMassTransferWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) entriesNum := 50 entries := generateMassTransferEntries(t, entriesNum) tx := createMassTransferWithProofs(t, entries) - info := defaultCheckerInfo() _, err := to.tc.checkMassTransferWithProofs(tx, info) assert.Error(t, err, "checkMassTransferWithProofs did not fail prior to feature activation") @@ -756,10 +793,10 @@ func TestCheckMassTransferWithProofs(t *testing.T) { } func TestCheckDataWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createDataWithProofs(t, 1) - info := defaultCheckerInfo() _, err := to.tc.checkDataWithProofs(tx, info) assert.Error(t, err, "checkDataWithProofs did not fail prior to feature activation") @@ -802,12 +839,12 @@ func TestCheckDataWithProofs(t *testing.T) { } func TestCheckSponsorshipWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createSponsorshipWithProofs(t, 1000) assetInfo := to.stor.createAsset(t, tx.AssetID) tx.SenderPK = assetInfo.issuer - info := defaultCheckerInfo() _, err := to.tc.checkSponsorshipWithProofs(tx, info) assert.Error(t, err, "checkSponsorshipWithProofs did not fail prior to feature activation") @@ -845,10 +882,10 @@ func TestCheckSponsorshipWithProofs(t *testing.T) { } func TestCheckSetScriptWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createSetScriptWithProofs(t) - info := defaultCheckerInfo() // Activate sponsorship. to.stor.activateSponsorship(t) @@ -1343,10 +1380,10 @@ func TestCheckSetScriptWithProofsCheckDAppCallables(t *testing.T) { } func TestCheckSetAssetScriptWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createSetAssetScriptWithProofs(t) - info := defaultCheckerInfo() assetInfo := defaultAssetInfo(proto.DigestTail(tx.AssetID), true) assetInfo.issuer = tx.SenderPK @@ -1379,13 +1416,14 @@ func TestCheckSetAssetScriptWithProofs(t *testing.T) { } func TestCheckInvokeScriptWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) payments := []proto.ScriptPayment{ {Amount: 1, Asset: *testGlobal.asset0.asset}, } tx := createInvokeScriptWithProofs(t, payments, proto.FunctionCall{}, proto.OptionalAsset{}, 1) - info := defaultCheckerInfo() + to.stor.addBlock(t, blockID0) assetId := tx.Payments[0].Asset.ID to.stor.createAsset(t, assetId) @@ -1418,7 +1456,8 @@ func TestCheckInvokeScriptWithProofs(t *testing.T) { } func TestCheckUpdateAssetInfoWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createUpdateAssetInfoWithProofs(t) // We create asset using random block here on purpose, this way @@ -1427,7 +1466,6 @@ func TestCheckUpdateAssetInfoWithProofs(t *testing.T) { to.stor.createAsset(t, tx.FeeAsset.ID) tx.SenderPK = assetInfo.issuer - info := defaultCheckerInfo() info.height = 100001 // Check fail prior to activation. @@ -1460,10 +1498,10 @@ func TestCheckUpdateAssetInfoWithProofs(t *testing.T) { } func TestCheckInvokeExpressionWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createInvokeExpressionWithProofs(t, make([]byte, 1), proto.OptionalAsset{}, 1) - info := defaultCheckerInfo() // Check activation. _, err := to.tc.checkInvokeScriptWithProofs(tx, info) diff --git a/pkg/state/transaction_differ_test.go b/pkg/state/transaction_differ_test.go index 7f5e312d1..a20236f51 100644 --- a/pkg/state/transaction_differ_test.go +++ b/pkg/state/transaction_differ_test.go @@ -26,19 +26,43 @@ var ( ) type differTestObjects struct { - stor *testStorageObjects - td *transactionDiffer - tp *transactionPerformer + stor *testStorageObjects + td *transactionDiffer + tp *transactionPerformer + stateActionsCounter *proto.StateActionsCounter } -func createDifferTestObjects(t *testing.T) *differTestObjects { +func createDifferTestObjects(t *testing.T, checkerInfo *checkerInfo) *differTestObjects { stor := createStorageObjects(t, true) td, err := newTransactionDiffer(stor.entities, settings.MainNetSettings) require.NoError(t, err, "newTransactionDiffer() failed") - snapshotGenerator := &snapshotGenerator{stor: stor.entities, settings: settings.MainNetSettings} - tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) + + actionsCounter := new(proto.StateActionsCounter) + + snapshotApplier := newBlockSnapshotsApplier( + blockSnapshotsApplierInfo{ + ci: checkerInfo, + scheme: settings.MainNetSettings.AddressSchemeCharacter, + stateActionsCounter: actionsCounter, + }, + snapshotApplierStorages{ + balances: stor.entities.balances, + aliases: stor.entities.aliases, + assets: stor.entities.assets, + scriptsStorage: stor.entities.scriptsStorage, + scriptsComplexity: stor.entities.scriptsComplexity, + sponsoredAssets: stor.entities.sponsoredAssets, + ordersVolumes: stor.entities.ordersVolumes, + accountsDataStor: stor.entities.accountsDataStor, + leases: stor.entities.leases, + }, + ) + snapshotGenerator := snapshotGenerator{stor: stor.entities, scheme: settings.MainNetSettings.AddressSchemeCharacter} + tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings) + tp.snapshotApplier = &snapshotApplier + tp.snapshotGenerator = &snapshotGenerator require.NoError(t, err, "newTransactionPerformer() failed") - return &differTestObjects{stor, td, tp} + return &differTestObjects{stor, td, tp, actionsCounter} } func createGenesis() *proto.Genesis { @@ -46,7 +70,8 @@ func createGenesis() *proto.Genesis { } func TestCreateDiffGenesis(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createGenesis() ch, err := to.td.createDiffGenesis(tx, defaultDifferInfo()) @@ -67,7 +92,8 @@ func createPayment(t *testing.T) *proto.Payment { } func TestCreateDiffPayment(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createPayment(t) ch, err := to.td.createDiffPayment(tx, defaultDifferInfo()) @@ -94,7 +120,8 @@ func createTransferWithSig(t *testing.T) *proto.TransferWithSig { } func TestCreateDiffTransferWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createTransferWithSig(t) feeFullAssetID := tx.FeeAsset.ID @@ -151,7 +178,8 @@ func createTransferWithProofs(t *testing.T) *proto.TransferWithProofs { } func TestCreateDiffTransferWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createTransferWithProofs(t) feeFullAssetID := tx.FeeAsset.ID @@ -215,7 +243,8 @@ func createNFTIssueWithSig(t *testing.T) *proto.IssueWithSig { } func TestCreateDiffIssueWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createIssueWithSig(t, 1000) ch, err := to.td.createDiffIssueWithSig(tx, defaultDifferInfo()) @@ -249,7 +278,8 @@ func createNFTIssueWithProofs(t *testing.T) *proto.IssueWithProofs { } func TestCreateDiffIssueWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createIssueWithProofs(t, 1000) ch, err := to.td.createDiffIssueWithProofs(tx, defaultDifferInfo()) @@ -276,7 +306,8 @@ func createReissueWithSig(t *testing.T, feeUnits int) *proto.ReissueWithSig { } func TestCreateDiffReissueWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createReissueWithSig(t, 1000) ch, err := to.td.createDiffReissueWithSig(tx, defaultDifferInfo()) @@ -302,7 +333,8 @@ func createReissueWithProofs(t *testing.T, feeUnits int) *proto.ReissueWithProof } func TestCreateDiffReissueWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createReissueWithProofs(t, 1000) ch, err := to.td.createDiffReissueWithProofs(tx, defaultDifferInfo()) @@ -328,7 +360,8 @@ func createBurnWithSig(t *testing.T) *proto.BurnWithSig { } func TestCreateDiffBurnWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createBurnWithSig(t) ch, err := to.td.createDiffBurnWithSig(tx, defaultDifferInfo()) @@ -354,7 +387,8 @@ func createBurnWithProofs(t *testing.T) *proto.BurnWithProofs { } func TestCreateDiffBurnWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createBurnWithProofs(t) ch, err := to.td.createDiffBurnWithProofs(tx, defaultDifferInfo()) @@ -400,7 +434,8 @@ func createExchangeWithSig(t *testing.T) *proto.ExchangeWithSig { //} func TestCreateDiffExchangeWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createExchangeWithSig(t) ch, err := to.td.createDiffExchange(tx, defaultDifferInfo()) @@ -453,7 +488,8 @@ func createUnorderedExchangeWithProofs(t *testing.T, v int) *proto.ExchangeWithP } func TestCreateDiffExchangeWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createExchangeWithProofs(t) ch, err := to.td.createDiffExchange(tx, defaultDifferInfo()) @@ -562,7 +598,8 @@ func createExchangeV2WithProofsWithOrdersV3(t *testing.T, info orderBuildInfo) * } func TestCreateDiffExchangeV2WithProofsWithOrdersV3(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createExchangeV2WithProofsWithOrdersV3(t, orderBuildInfo{ price: 10e8, @@ -593,7 +630,8 @@ func TestCreateDiffExchangeV2WithProofsWithOrdersV3(t *testing.T) { } func TestCreateDiffExchangeV3WithProofsWithMixedOrders(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) const ( asset0Decimals = 5 @@ -700,7 +738,7 @@ func TestCreateDiffExchangeV3WithProofsWithMixedOrders(t *testing.T) { // and produces an incorrect or unexpected diff, should be fixes some how // // func TestCreateDiffExchangeWithSignature(t *testing.T) { -// to, path := createDifferTestObjects(t) +// to, path := createDifferTestObjects(t, checkerInfo // // to.stor.createAssetWithDecimals(t, testGlobal.asset0.asset.ID, 8) // to.stor.createAssetWithDecimals(t, testGlobal.asset1.asset.ID, 8) @@ -734,7 +772,8 @@ func TestCreateDiffExchangeV3WithProofsWithMixedOrders(t *testing.T) { // assert.Equal(t, correctAddrs, ch.addrs) // } func TestCreateDiffExchangeV3WithProofsWithOrdersV4(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.createAssetWithDecimals(t, testGlobal.asset0.asset.ID, 0) to.stor.createAssetWithDecimals(t, testGlobal.asset1.asset.ID, 8) @@ -807,7 +846,8 @@ func createLeaseWithSig(t *testing.T) *proto.LeaseWithSig { } func TestCreateDiffLeaseWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createLeaseWithSig(t) ch, err := to.td.createDiffLeaseWithSig(tx, defaultDifferInfo()) @@ -834,7 +874,8 @@ func createLeaseWithProofs(t *testing.T) *proto.LeaseWithProofs { } func TestCreateDiffLeaseWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createLeaseWithProofs(t) ch, err := to.td.createDiffLeaseWithProofs(tx, defaultDifferInfo()) @@ -861,10 +902,11 @@ func createLeaseCancelWithSig(t *testing.T, leaseID crypto.Digest) *proto.LeaseC } func TestCreateDiffLeaseCancelWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) leaseTx := createLeaseWithSig(t) - info := defaultPerformerInfo() + info := defaultPerformerInfo(to.stateActionsCounter) to.stor.addBlock(t, blockID0) _, err := to.tp.performLeaseWithSig(leaseTx, info, nil, nil) assert.NoError(t, err, "performLeaseWithSig failed") @@ -894,10 +936,11 @@ func createLeaseCancelWithProofs(t *testing.T, leaseID crypto.Digest) *proto.Lea } func TestCreateDiffLeaseCancelWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) leaseTx := createLeaseWithProofs(t) - info := defaultPerformerInfo() + info := defaultPerformerInfo(to.stateActionsCounter) to.stor.addBlock(t, blockID0) _, err := to.tp.performLeaseWithProofs(leaseTx, info, nil, nil) assert.NoError(t, err, "performLeaseWithProofs failed") @@ -931,7 +974,8 @@ func createCreateAliasWithSig(t *testing.T) *proto.CreateAliasWithSig { } func TestCreateDiffCreateAliasWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createCreateAliasWithSig(t) ch, err := to.td.createDiffCreateAliasWithSig(tx, defaultDifferInfo()) @@ -960,7 +1004,8 @@ func createCreateAliasWithProofs(t *testing.T) *proto.CreateAliasWithProofs { } func TestCreateDiffCreateAliasWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createCreateAliasWithProofs(t) ch, err := to.td.createDiffCreateAliasWithProofs(tx, defaultDifferInfo()) @@ -996,7 +1041,8 @@ func createMassTransferWithProofs(t *testing.T, transfers []proto.MassTransferEn } func TestCreateDiffMassTransferWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) entriesNum := 66 entries := generateMassTransferEntries(t, entriesNum) @@ -1036,7 +1082,8 @@ func createDataWithProofs(t *testing.T, entriesNum int) *proto.DataWithProofs { } func TestCreateDiffDataWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createDataWithProofs(t, 1) ch, err := to.td.createDiffDataWithProofs(tx, defaultDifferInfo()) @@ -1061,7 +1108,8 @@ func createSponsorshipWithProofs(t *testing.T, fee uint64) *proto.SponsorshipWit } func TestCreateDiffSponsorshipWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createSponsorshipWithProofs(t, 1000) ch, err := to.td.createDiffSponsorshipWithProofs(tx, defaultDifferInfo()) @@ -1093,7 +1141,8 @@ func createSetScriptWithProofs(t *testing.T, customScriptBytes ...[]byte) *proto } func TestCreateDiffSetScriptWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createSetScriptWithProofs(t) ch, err := to.td.createDiffSetScriptWithProofs(tx, defaultDifferInfo()) @@ -1120,7 +1169,8 @@ func createSetAssetScriptWithProofs(t *testing.T) *proto.SetAssetScriptWithProof } func TestCreateDiffSetAssetScriptWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createSetAssetScriptWithProofs(t) ch, err := to.td.createDiffSetAssetScriptWithProofs(tx, defaultDifferInfo()) @@ -1145,7 +1195,8 @@ func createInvokeScriptWithProofs(t *testing.T, pmts proto.ScriptPayments, fc pr } func TestCreateDiffInvokeScriptWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) feeConst, ok := feeConstants[proto.InvokeScriptTransaction] assert.Equal(t, ok, true) @@ -1207,7 +1258,8 @@ func createUpdateAssetInfoWithProofs(t *testing.T) *proto.UpdateAssetInfoWithPro } func TestCreateDiffUpdateAssetInfoWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createUpdateAssetInfoWithProofs(t) ch, err := to.td.createDiffUpdateAssetInfoWithProofs(tx, defaultDifferInfo()) diff --git a/pkg/state/transaction_handler.go b/pkg/state/transaction_handler.go index 4975e9f9b..fef38b57e 100644 --- a/pkg/state/transaction_handler.go +++ b/pkg/state/transaction_handler.go @@ -141,8 +141,7 @@ func newTransactionHandler( if err != nil { return nil, err } - snapshotGenerator := &snapshotGenerator{stor: stor, settings: settings} - tp, err := newTransactionPerformer(stor, settings, snapshotGenerator) + tp, err := newTransactionPerformer(stor, settings) if err != nil { return nil, err } diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 05f4dfaaf..d05afc5fd 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -14,8 +14,7 @@ type performerInfo struct { blockID proto.BlockID currentMinerAddress proto.WavesAddress stateActionsCounter *proto.StateActionsCounter - // TODO put one into another - checkerData txCheckerData + checkerData txCheckerData } func newPerformerInfo(height proto.Height, stateActionsCounter *proto.StateActionsCounter, blockID proto.BlockID, currentMinerAddress proto.WavesAddress, checkerData txCheckerData) *performerInfo { @@ -25,11 +24,12 @@ func newPerformerInfo(height proto.Height, stateActionsCounter *proto.StateActio type transactionPerformer struct { stor *blockchainEntitiesStorage settings *settings.BlockchainSettings - snapshotGenerator *snapshotGenerator + snapshotGenerator *snapshotGenerator // initialized in appendTx + snapshotApplier SnapshotApplier // initialized in appendTx } -func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings.BlockchainSettings, snapshotGenerator *snapshotGenerator) (*transactionPerformer, error) { - return &transactionPerformer{stor, settings, snapshotGenerator}, nil +func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings.BlockchainSettings) (*transactionPerformer, error) { + return &transactionPerformer{stor: stor, settings: settings}, nil } func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -37,7 +37,11 @@ func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, _ if !ok { return nil, errors.New("failed to convert interface to genesis transaction") } - return tp.snapshotGenerator.generateSnapshotForGenesisTx(balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForGenesisTx(balanceChanges) + if err != nil { + return nil, err + } + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performPayment(transaction proto.Transaction, _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -45,11 +49,19 @@ func (tp *transactionPerformer) performPayment(transaction proto.Transaction, _ if !ok { return nil, errors.New("failed to convert interface to payment transaction") } - return tp.snapshotGenerator.generateSnapshotForPaymentTx(balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForPaymentTx(balanceChanges) + if err != nil { + return nil, err + } + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performTransfer(balanceChanges txDiff) (TransactionSnapshot, error) { - return tp.snapshotGenerator.generateSnapshotForTransferTx(balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForTransferTx(balanceChanges) + if err != nil { + return nil, err + } + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -73,11 +85,10 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest // Create new asset. assetInfo := &assetInfo{ assetConstInfo: assetConstInfo{ - tail: proto.DigestTail(assetID), - issuer: tx.SenderPK, - decimals: tx.Decimals, - issueHeight: blockHeight, - issueSequenceInBlock: info.stateActionsCounter.NextIssueActionNumber(), + tail: proto.DigestTail(assetID), + issuer: tx.SenderPK, + decimals: tx.Decimals, + issueHeight: blockHeight, }, assetChangeableInfo: assetChangeableInfo{ quantity: *big.NewInt(int64(tx.Quantity)), @@ -89,15 +100,11 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest } snapshot, err := tp.snapshotGenerator.generateSnapshotForIssueTx(assetID, txID, tx.SenderPK, *assetInfo, balanceChanges, scriptInformation) + if err != nil { return nil, err } - - 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 + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -113,9 +120,7 @@ func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transactio if err != nil { return nil, err } - if err := tp.stor.scriptsStorage.setAssetScript(assetID, proto.Script{}, tx.SenderPK, info.blockID); err != nil { - return nil, err - } + return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges, nil) } @@ -132,10 +137,6 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac if err != nil { return nil, err } - if err := tp.stor.scriptsStorage.setAssetScript(assetID, tx.Script, tx.SenderPK, info.blockID); err != nil { - return nil, err - } - var scriptInfo *scriptInformation if se := info.checkerData.scriptEstimations; se.isPresent() { // Save complexities to storage, so we won't have to calculate it every time the script is called. @@ -143,9 +144,6 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac if !ok { return nil, errors.Errorf("failed to calculate asset script complexity by estimator version %d", se.currentEstimatorVersion) } - if err := tp.stor.scriptsComplexity.saveComplexitiesForAsset(assetID, complexity, info.blockID); err != nil { - return nil, err - } scriptInfo = &scriptInformation{ script: tx.Script, complexity: complexity.Verifier, @@ -154,7 +152,7 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges, scriptInfo) } -func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performReissue(tx *proto.Reissue, _ *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { // Modify asset. change := &assetReissueChange{ reissuable: tx.Reissuable, @@ -165,11 +163,7 @@ func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performe if err != nil { return nil, err } - - 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 + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -188,7 +182,7 @@ func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Trans return tp.performReissue(&tx.Reissue, info, balanceChanges) } -func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performBurn(tx *proto.Burn, _ *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { // Modify asset. change := &assetBurnChange{ diff: int64(tx.Amount), @@ -198,12 +192,7 @@ func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, if err != nil { return nil, err } - - 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 + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -222,14 +211,6 @@ func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transact return tp.performBurn(&tx.Burn, info, balanceChanges) } -func (tp *transactionPerformer) increaseOrderVolume(order proto.Order, fee uint64, volume uint64, info *performerInfo) error { - orderID, err := order.GetID() - if err != nil { - return err - } - return tp.stor.ordersVolumes.increaseFilled(orderID, volume, fee, info.blockID) -} - func (tp *transactionPerformer) performExchange(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(proto.Exchange) if !ok { @@ -252,16 +233,7 @@ func (tp *transactionPerformer) performExchange(transaction proto.Transaction, i if err != nil { return nil, err } - - err = tp.increaseOrderVolume(sellOrder, sellFee, volume, info) - if err != nil { - return nil, err - } - err = tp.increaseOrderVolume(buyOrder, buyFee, volume, info) - if err != nil { - return nil, err - } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -288,13 +260,9 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest } snapshot, err := tp.snapshotGenerator.generateSnapshotForLeaseTx(*l, txID, txID, balanceChanges) if err != nil { - return nil, nil - } - - if err := tp.stor.leases.addLeasing(txID, l, info.blockID); err != nil { - return nil, errors.Wrap(err, "failed to add leasing") + return nil, err } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -323,10 +291,7 @@ func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID * if err != nil { return nil, err } - 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 + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -345,7 +310,7 @@ func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.T return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info, balanceChanges) } -func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, _ *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { return nil, err @@ -355,10 +320,7 @@ func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info * if err != nil { return nil, err } - if err := tp.stor.aliases.createAlias(tx.Alias.Alias, senderAddr, info.blockID); err != nil { - return nil, err - } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -382,7 +344,11 @@ func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto. if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") } - return tp.snapshotGenerator.generateSnapshotForMassTransferTx(balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForMassTransferTx(balanceChanges) + if err != nil { + return nil, err + } + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -400,12 +366,7 @@ func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transact if err != nil { return nil, err } - for _, entry := range tx.Entries { - if err := tp.stor.accountsDataStor.appendEntry(senderAddr, entry, info.blockID); err != nil { - return nil, err - } - } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -418,10 +379,7 @@ func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.T if err != nil { return nil, err } - 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 + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -429,11 +387,6 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra if !ok { return nil, errors.New("failed to convert interface to SetScriptWithProofs transaction") } - senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) - if err != nil { - return nil, err - } - se := info.checkerData.scriptEstimations if !se.isPresent() { return nil, errors.New("script estimations must be set for SetScriptWithProofs tx") @@ -443,17 +396,11 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra complexity := info.checkerData.scriptEstimations.estimations[se.currentEstimatorVersion].Verifier snapshot, err := tp.snapshotGenerator.generateSnapshotForSetScriptTx(tx.SenderPK, tx.Script, complexity, info, balanceChanges) + if err != nil { return nil, err } - 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") - } - // Save complexity to storage, so we won't have to calculate it every time the script is called. - if err := tp.stor.scriptsComplexity.saveComplexitiesForAddr(senderAddr, se.estimations, info.blockID); err != nil { - return nil, err - } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -472,18 +419,11 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot } complexity := estimation.Verifier - snapshot, err := tp.snapshotGenerator.generateSnapshotForSetAssetScriptTx(tx.AssetID, tx.Script, complexity, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForSetAssetScriptTx(tx.AssetID, tx.Script, complexity, tx.SenderPK, balanceChanges) if err != nil { return nil, err } - 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") - } - // Save complexity to storage, so we won't have to calculate it every time the script is called. - if err := tp.stor.scriptsComplexity.saveComplexitiesForAsset(tx.AssetID, estimation, info.blockID); err != nil { - return nil, errors.Wrapf(err, "failed to save script complexity for asset %q", tx.AssetID.String()) - } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } func addToWavesBalanceDiff(addrWavesBalanceDiff addressWavesBalanceDiff, @@ -554,6 +494,7 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. if _, ok := transaction.(*proto.InvokeScriptWithProofs); !ok { return nil, errors.New("failed to convert interface to InvokeScriptWithProofs transaction") } + // TODO remove? if err := tp.stor.commitUncertain(info.blockID); err != nil { return nil, errors.Wrap(err, "failed to commit invoke changes") } @@ -568,16 +509,16 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. snapshot, err := tp.snapshotGenerator.generateSnapshotForInvokeScriptTx(txID, info, invocationRes, balanceChanges) if err != nil { - return nil, errors.Wrap(err, "failed to generate a snapshot for an invoke transaction") + return nil, err } - - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { if _, ok := transaction.(*proto.InvokeExpressionTransactionWithProofs); !ok { return nil, errors.New("failed to convert interface to InvokeExpressionWithProofs transaction") } + // TODO remove? if err := tp.stor.commitUncertain(info.blockID); err != nil { return nil, errors.Wrap(err, "failed to commit invoke changes") } @@ -590,7 +531,11 @@ func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction pr return nil, err } - return tp.snapshotGenerator.generateSnapshotForInvokeExpressionTx(txID, info, invocationRes, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForInvokeExpressionTx(txID, info, invocationRes, balanceChanges) + if err != nil { + return nil, err + } + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -599,6 +544,7 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction return nil, errors.New("failed to convert interface to EthereumTransaction transaction") } if _, ok := ethTx.TxKind.(*proto.EthereumInvokeScriptTxKind); ok { + // TODO remove? if err := tp.stor.commitUncertain(info.blockID); err != nil { return nil, errors.Wrap(err, "failed to commit invoke changes") } @@ -614,10 +560,9 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction snapshot, err := tp.snapshotGenerator.generateSnapshotForEthereumInvokeScriptTx(txID, info, invocationRes, balanceChanges) if err != nil { - return nil, errors.Wrap(err, "failed to generate a snapshot for an invoke transaction") + return nil, err } - - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -626,18 +571,10 @@ func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction pro return nil, errors.New("failed to convert interface to UpdateAssetInfoWithProofs transaction") } blockHeight := info.height + 1 - ch := &assetInfoChange{ - newName: tx.Name, - newDescription: tx.Description, - newHeight: blockHeight, - } snapshot, err := tp.snapshotGenerator.generateSnapshotForUpdateAssetInfoTx(tx.AssetID, tx.Name, tx.Description, blockHeight, balanceChanges) if err != nil { return nil, err } - if err := tp.stor.assets.updateAssetInfo(tx.AssetID, ch, info.blockID); err != nil { - return nil, errors.Wrap(err, "failed to update asset info") - } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } diff --git a/pkg/state/transaction_performer_test.go b/pkg/state/transaction_performer_test.go index 0f84dae1e..96400f168 100644 --- a/pkg/state/transaction_performer_test.go +++ b/pkg/state/transaction_performer_test.go @@ -15,28 +15,53 @@ import ( ) type performerTestObjects struct { - stor *testStorageObjects - tp *transactionPerformer + stor *testStorageObjects + tp *transactionPerformer + stateActionsCounter *proto.StateActionsCounter } -func createPerformerTestObjects(t *testing.T) *performerTestObjects { +func createPerformerTestObjects(t *testing.T, checkerInfo *checkerInfo) *performerTestObjects { stor := createStorageObjects(t, true) - snapshotGenerator := &snapshotGenerator{stor.entities, settings.MainNetSettings} - tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) + tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings) + + actionsCounter := new(proto.StateActionsCounter) + + snapshotApplier := newBlockSnapshotsApplier( + blockSnapshotsApplierInfo{ + ci: checkerInfo, + scheme: settings.MainNetSettings.AddressSchemeCharacter, + stateActionsCounter: actionsCounter, + }, + snapshotApplierStorages{ + balances: stor.entities.balances, + aliases: stor.entities.aliases, + assets: stor.entities.assets, + scriptsStorage: stor.entities.scriptsStorage, + scriptsComplexity: stor.entities.scriptsComplexity, + sponsoredAssets: stor.entities.sponsoredAssets, + ordersVolumes: stor.entities.ordersVolumes, + accountsDataStor: stor.entities.accountsDataStor, + leases: stor.entities.leases, + }, + ) + snapshotGenerator := snapshotGenerator{stor: stor.entities, scheme: settings.MainNetSettings.AddressSchemeCharacter} + tp.snapshotApplier = &snapshotApplier + tp.snapshotGenerator = &snapshotGenerator require.NoError(t, err, "newTransactionPerformer() failed") - return &performerTestObjects{stor, tp} + return &performerTestObjects{stor, tp, actionsCounter} } -func defaultPerformerInfo() *performerInfo { - return newPerformerInfo(0, new(proto.StateActionsCounter), blockID0, proto.WavesAddress{}, txCheckerData{}) +func defaultPerformerInfo(stateActionsCounter *proto.StateActionsCounter) *performerInfo { + return newPerformerInfo(0, stateActionsCounter, blockID0, proto.WavesAddress{}, txCheckerData{}) } func TestPerformIssueWithSig(t *testing.T) { - to := createPerformerTestObjects(t) - + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) + checkerInfo.height = 1 to.stor.addBlock(t, blockID0) tx := createIssueWithSig(t, 1000) - _, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performIssueWithSig() failed") to.stor.flush(t) expectedAssetInfo := assetInfo{ @@ -63,12 +88,13 @@ func TestPerformIssueWithSig(t *testing.T) { } func TestPerformIssueWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) - + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) + checkerInfo.height = 1 to.stor.addBlock(t, blockID0) tx := createIssueWithProofs(t, 1000) - _, err := to.tp.performIssueWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performIssueWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performIssueWithProofs() failed") to.stor.flush(t) expectedAssetInfo := assetInfo{ @@ -95,11 +121,13 @@ func TestPerformIssueWithProofs(t *testing.T) { } func TestPerformReissueWithSig(t *testing.T) { - to := createPerformerTestObjects(t) + + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithSig(t, 1000) - _, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performReissueWithSig() failed") to.stor.flush(t) assetInfo.reissuable = tx.Reissuable @@ -112,11 +140,12 @@ func TestPerformReissueWithSig(t *testing.T) { } func TestPerformReissueWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithProofs(t, 1000) - _, err := to.tp.performReissueWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performReissueWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performReissueWithProofs() failed") to.stor.flush(t) assetInfo.reissuable = tx.Reissuable @@ -129,11 +158,12 @@ func TestPerformReissueWithProofs(t *testing.T) { } func TestPerformBurnWithSig(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithSig(t) - _, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performBurnWithSig() failed") to.stor.flush(t) assetInfo.quantity.Sub(&assetInfo.quantity, big.NewInt(int64(tx.Amount))) @@ -145,11 +175,12 @@ func TestPerformBurnWithSig(t *testing.T) { } func TestPerformBurnWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithProofs(t) - _, err := to.tp.performBurnWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performBurnWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performBurnWithProofs() failed") to.stor.flush(t) assetInfo.quantity.Sub(&assetInfo.quantity, big.NewInt(int64(tx.Amount))) @@ -161,11 +192,12 @@ func TestPerformBurnWithProofs(t *testing.T) { } func TestPerformExchange(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createExchangeWithSig(t) - _, err := to.tp.performExchange(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performExchange(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performExchange() failed") sellOrderID, err := tx.GetOrder2().GetID() @@ -198,11 +230,12 @@ func TestPerformExchange(t *testing.T) { } func TestPerformLeaseWithSig(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createLeaseWithSig(t) - _, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseWithSig() failed") to.stor.flush(t) leasingInfo := &leasing{ @@ -219,11 +252,12 @@ func TestPerformLeaseWithSig(t *testing.T) { } func TestPerformLeaseWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createLeaseWithProofs(t) - _, err := to.tp.performLeaseWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performLeaseWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseWithProofs() failed") to.stor.flush(t) leasingInfo := &leasing{ @@ -240,11 +274,12 @@ func TestPerformLeaseWithProofs(t *testing.T) { } func TestPerformLeaseCancelWithSig(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) leaseTx := createLeaseWithSig(t) - _, err := to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseWithSig() failed") to.stor.flush(t) tx := createLeaseCancelWithSig(t, *leaseTx.ID) @@ -256,7 +291,7 @@ func TestPerformLeaseCancelWithSig(t *testing.T) { Sender: testGlobal.senderInfo.addr, CancelTransactionID: tx.ID, } - _, err = to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseCancelWithSig() failed") to.stor.flush(t) info, err := to.stor.entities.leases.leasingInfo(*leaseTx.ID) @@ -265,11 +300,12 @@ func TestPerformLeaseCancelWithSig(t *testing.T) { } func TestPerformLeaseCancelWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) leaseTx := createLeaseWithProofs(t) - _, err := to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseWithProofs() failed") to.stor.flush(t) tx := createLeaseCancelWithProofs(t, *leaseTx.ID) @@ -281,7 +317,7 @@ func TestPerformLeaseCancelWithProofs(t *testing.T) { Sender: testGlobal.senderInfo.addr, CancelTransactionID: tx.ID, } - _, err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseCancelWithProofs() failed") to.stor.flush(t) info, err := to.stor.entities.leases.leasingInfo(*leaseTx.ID) @@ -290,11 +326,12 @@ func TestPerformLeaseCancelWithProofs(t *testing.T) { } func TestPerformCreateAliasWithSig(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createCreateAliasWithSig(t) - _, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performCreateAliasWithSig() failed") to.stor.flush(t) addr, err := to.stor.entities.aliases.addrByAlias(tx.Alias.Alias) @@ -302,7 +339,7 @@ func TestPerformCreateAliasWithSig(t *testing.T) { assert.Equal(t, testGlobal.senderInfo.addr, addr, "invalid address by alias after performing CreateAliasWithSig transaction") // Test stealing aliases. - _, err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performCreateAliasWithSig() failed") to.stor.flush(t) err = to.stor.entities.aliases.disableStolenAliases(blockID0) @@ -313,11 +350,12 @@ func TestPerformCreateAliasWithSig(t *testing.T) { } func TestPerformCreateAliasWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createCreateAliasWithProofs(t) - _, err := to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performCreateAliasWithProofs() failed") to.stor.flush(t) addr, err := to.stor.entities.aliases.addrByAlias(tx.Alias.Alias) @@ -325,7 +363,7 @@ func TestPerformCreateAliasWithProofs(t *testing.T) { assert.Equal(t, testGlobal.senderInfo.addr, addr, "invalid address by alias after performing CreateAliasWithProofs transaction") // Test stealing aliases. - _, err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performCreateAliasWithProofs() failed") to.stor.flush(t) err = to.stor.entities.aliases.disableStolenAliases(blockID0) @@ -336,7 +374,8 @@ func TestPerformCreateAliasWithProofs(t *testing.T) { } func TestPerformDataWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) @@ -344,7 +383,7 @@ func TestPerformDataWithProofs(t *testing.T) { entry := &proto.IntegerDataEntry{Key: "TheKey", Value: int64(666)} tx.Entries = []proto.DataEntry{entry} - _, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performDataWithProofs() failed") to.stor.flush(t) @@ -354,12 +393,13 @@ func TestPerformDataWithProofs(t *testing.T) { } func TestPerformSponsorshipWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createSponsorshipWithProofs(t, 1000) - _, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performSponsorshipWithProofs() failed") assetID := proto.AssetIDFromDigest(tx.AssetID) @@ -397,7 +437,8 @@ func TestPerformSponsorshipWithProofs(t *testing.T) { } func TestPerformSetScriptWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) @@ -419,7 +460,7 @@ func TestPerformSetScriptWithProofs(t *testing.T) { require.NoError(t, err) tx := createSetScriptWithProofs(t, scriptBytes) - pi := *defaultPerformerInfo() + pi := *defaultPerformerInfo(to.stateActionsCounter) pi.checkerData.scriptEstimations = &scriptsEstimations{} _, err = to.tp.performSetScriptWithProofs(tx, &pi, nil, nil) assert.NoError(t, err, "performSetScriptWithProofs() failed") @@ -485,12 +526,13 @@ func TestPerformSetScriptWithProofs(t *testing.T) { } func TestPerformSetAssetScriptWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createSetAssetScriptWithProofs(t) - pi := *defaultPerformerInfo() + pi := *defaultPerformerInfo(to.stateActionsCounter) currentEstimatorVersion := 4 tree, err := serialization.Parse(tx.Script) @@ -504,6 +546,7 @@ func TestPerformSetAssetScriptWithProofs(t *testing.T) { currentEstimatorVersion: estimation, }, } + checkerInfo.blockID = blockID0 _, err = to.tp.performSetAssetScriptWithProofs(tx, &pi, nil, nil) assert.NoError(t, err, "performSetAssetScriptWithProofs() failed") @@ -580,11 +623,12 @@ func TestPerformSetAssetScriptWithProofs(t *testing.T) { } func TestPerformUpdateAssetInfoWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createUpdateAssetInfoWithProofs(t) - _, err := to.tp.performUpdateAssetInfoWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performUpdateAssetInfoWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performUpdateAssetInfoWithProofs() failed") to.stor.flush(t) assetInfo.name = tx.Name From a6658299644ae94aeb5b1f1ec7076832b4818eab Mon Sep 17 00:00:00 2001 From: Alexandr Dolgavin <41806871+esuwu@users.noreply.github.com> Date: Thu, 20 Jul 2023 15:06:04 -0700 Subject: [PATCH 051/139] Revert "Replaced current recording to storage to snapshot applier (#1162)" (#1164) This reverts commit 51904b2ff66e4de39d5668461676b9415f879f2d. --- pkg/state/appender.go | 71 ++------- pkg/state/fee_validation_test.go | 13 +- pkg/state/snapshot_applier.go | 10 +- pkg/state/snapshot_generator.go | 77 ++++++++-- pkg/state/snapshot_generator_test.go | 80 +++++----- pkg/state/snapshot_types.go | 72 +-------- pkg/state/state.go | 3 +- pkg/state/transaction_checker_test.go | 180 +++++++++-------------- pkg/state/transaction_differ_test.go | 128 +++++----------- pkg/state/transaction_handler.go | 3 +- pkg/state/transaction_performer.go | 185 ++++++++++++++++-------- pkg/state/transaction_performer_test.go | 144 +++++++----------- 12 files changed, 406 insertions(+), 560 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 4cd7fb183..b98f5d550 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -337,6 +337,7 @@ func (a *txAppender) commitTxApplication( // Update complexity. a.sc.addRecentTxComplexity() // Save balance diff. + // 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)) } @@ -352,6 +353,7 @@ func (a *txAppender) commitTxApplication( stateActionsCounter: params.stateActionsCounterInBlock, checkerData: applicationRes.checkerData, } + // TODO other snapshots snapshot, err = a.txHandler.performTx(tx, performerInfo, invocationRes, applicationRes.changes.diff) if err != nil { return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to perform: %v", err)) @@ -418,9 +420,6 @@ type appendTxParams struct { validatingUtx bool // if validatingUtx == false then chans MUST be initialized with non nil value stateActionsCounterInBlock *proto.StateActionsCounter currentMinerPK crypto.PublicKey - - snapshotGenerator *snapshotGenerator - snapshotApplier SnapshotApplier } func (a *txAppender) handleInvokeOrExchangeTransaction(tx proto.Transaction, fallibleInfo *fallibleValidationParams) (*invocationResult, *applicationResult, error) { @@ -455,9 +454,6 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro a.stor.dropUncertain() }() - a.txHandler.tp.snapshotGenerator = params.snapshotGenerator - a.txHandler.tp.snapshotApplier = params.snapshotApplier - blockID := params.checkerInfo.blockID // Check that Protobuf transactions are accepted. if err := a.checkProtobufVersion(tx, params.blockV5Activated); err != nil { @@ -636,27 +632,6 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { if hasParent { checkerInfo.parentTimestamp = params.parent.Timestamp } - stateActionsCounterInBlock := new(proto.StateActionsCounter) - - snapshotApplier := newBlockSnapshotsApplier( - blockSnapshotsApplierInfo{ - ci: checkerInfo, - scheme: a.settings.AddressSchemeCharacter, - stateActionsCounter: stateActionsCounterInBlock, - }, - snapshotApplierStorages{ - balances: a.stor.balances, - aliases: a.stor.aliases, - assets: a.stor.assets, - scriptsStorage: a.stor.scriptsStorage, - scriptsComplexity: a.stor.scriptsComplexity, - sponsoredAssets: a.stor.sponsoredAssets, - ordersVolumes: a.stor.ordersVolumes, - accountsDataStor: a.stor.accountsDataStor, - leases: a.stor.leases, - }, - ) - snapshotGenerator := snapshotGenerator{stor: a.stor, scheme: a.settings.AddressSchemeCharacter} // Create miner balance diff. // This adds 60% of prev block fees as very first balance diff of the current block @@ -666,15 +641,15 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { return err } // create the initial snapshot - _, err = a.createInitialBlockSnapshot(minerAndRewardDiff) + initialSnapshot, err := a.createInitialBlockSnapshot(minerAndRewardDiff) if err != nil { return errors.Wrap(err, "failed to create initial snapshot") } - - // TODO apply this snapshot when balances are refatored - //err = initialSnapshot.Apply(&snapshotApplier) - - // Save miner diff first (for validation) + // a temporary dummy for linters + if len(initialSnapshot) > 100 { + zap.S().Debug(initialSnapshot) + } + // Save miner diff first. if err := a.diffStor.saveTxDiff(minerAndRewardDiff); err != nil { return err } @@ -698,8 +673,8 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { if err != nil { return err } + stateActionsCounterInBlock := new(proto.StateActionsCounter) // Check and append transactions. - for _, tx := range params.transactions { appendTxArgs := &appendTxParams{ chans: params.chans, @@ -716,8 +691,6 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { validatingUtx: false, stateActionsCounterInBlock: stateActionsCounterInBlock, currentMinerPK: params.block.GeneratorPublicKey, - snapshotGenerator: &snapshotGenerator, - snapshotApplier: &snapshotApplier, } if err := a.appendTx(tx, appendTxArgs); err != nil { return err @@ -731,7 +704,6 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { return nil } -// used only in tests now. All diffs are applied in snapshotApplier func (a *txAppender) applyAllDiffs() error { a.recentTxIds = make(map[string]struct{}) return a.moveChangesToHistoryStorage() @@ -959,27 +931,6 @@ func (a *txAppender) validateNextTx(tx proto.Transaction, currentTimestamp, pare if err != nil { return errs.Extend(err, "failed to check 'InvokeExpression' is activated") // TODO: check feature naming in err message } - actionsCounter := new(proto.StateActionsCounter) - snapshotApplier := newBlockSnapshotsApplier( - blockSnapshotsApplierInfo{ - ci: checkerInfo, - scheme: a.settings.AddressSchemeCharacter, - stateActionsCounter: actionsCounter, - }, - snapshotApplierStorages{ - balances: a.stor.balances, - aliases: a.stor.aliases, - assets: a.stor.assets, - scriptsStorage: a.stor.scriptsStorage, - scriptsComplexity: a.stor.scriptsComplexity, - sponsoredAssets: a.stor.sponsoredAssets, - ordersVolumes: a.stor.ordersVolumes, - accountsDataStor: a.stor.accountsDataStor, - leases: a.stor.leases, - }, - ) - snapshotGenerator := snapshotGenerator{stor: a.stor, scheme: a.settings.AddressSchemeCharacter} - appendTxArgs := &appendTxParams{ chans: nil, // nil because validatingUtx == true checkerInfo: checkerInfo, @@ -994,9 +945,7 @@ func (a *txAppender) validateNextTx(tx proto.Transaction, currentTimestamp, pare invokeExpressionActivated: invokeExpressionActivated, validatingUtx: true, // it's correct to use new counter because there's no block exists, but this field is necessary in tx performer - stateActionsCounterInBlock: actionsCounter, - snapshotGenerator: &snapshotGenerator, - snapshotApplier: &snapshotApplier, + stateActionsCounterInBlock: new(proto.StateActionsCounter), } err = a.appendTx(tx, appendTxArgs) if err != nil { diff --git a/pkg/state/fee_validation_test.go b/pkg/state/fee_validation_test.go index 6924f1aca..0bd676dc0 100644 --- a/pkg/state/fee_validation_test.go +++ b/pkg/state/fee_validation_test.go @@ -50,11 +50,11 @@ The account script is set on blockID2, then rollback returns storage to the bloc The account must not have a verifier anymore. However, the filter is false, so invalid data (verifier) will be returned\ */ func TestAccountHasVerifierAfterRollbackFilterFalse(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) to.stor.hs.amend = false tx := createSetScriptWithProofs(t) + info := defaultCheckerInfo() to.stor.activateFeature(t, int16(settings.SmartAccounts)) @@ -66,9 +66,8 @@ func TestAccountHasVerifierAfterRollbackFilterFalse(t *testing.T) { address, err := proto.NewAddressFromPublicKey(to.tc.settings.AddressSchemeCharacter, tx.SenderPK) assert.NoError(t, err, "failed to receive an address from public key") - txPerformerInfo := defaultPerformerInfo(to.stateActionsCounter) + txPerformerInfo := defaultPerformerInfo() txPerformerInfo.blockID = blockID2 - info.blockID = blockID2 // the block from checker info is used by snapshot applier to apply a tx txPerformerInfo.checkerData = checkerData _, err = to.tp.performSetScriptWithProofs(tx, txPerformerInfo, nil, nil) @@ -90,8 +89,7 @@ func TestAccountHasVerifierAfterRollbackFilterFalse(t *testing.T) { // the account script is set on blockID2, then blockID3 is added, then rollback returns storage to the blockID1. // The account must not have a verifier anymore. Filter is true, so everything must be valid func TestAccountDoesNotHaveScriptAfterRollbackFilterTrue(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) to.stor.hs.amend = true tx := createSetScriptWithProofs(t) @@ -104,9 +102,8 @@ func TestAccountDoesNotHaveScriptAfterRollbackFilterTrue(t *testing.T) { address, err := proto.NewAddressFromPublicKey(to.tc.settings.AddressSchemeCharacter, tx.SenderPK) assert.NoError(t, err, "failed to receive an address from public key") - txPerformerInfo := defaultPerformerInfo(to.stateActionsCounter) + txPerformerInfo := defaultPerformerInfo() txPerformerInfo.blockID = blockID2 - info.blockID = blockID2 // the block from checker info is used by snapshot applier to apply a tx txPerformerInfo.checkerData.scriptEstimations = &scriptsEstimations{} _, err = to.tp.performSetScriptWithProofs(tx, txPerformerInfo, nil, nil) diff --git a/pkg/state/snapshot_applier.go b/pkg/state/snapshot_applier.go index babf78c82..1fb25cc0a 100644 --- a/pkg/state/snapshot_applier.go +++ b/pkg/state/snapshot_applier.go @@ -169,11 +169,11 @@ func (a *blockSnapshotsApplier) ApplyAssetScript(snapshot AssetScriptSnapshot) e if err := a.stor.scriptsComplexity.saveComplexitiesForAsset(snapshot.AssetID, estimation, a.info.BlockID()); err != nil { return errors.Wrapf(err, "failed to store asset script estimation for asset %q", snapshot.AssetID.String()) } - //constInfo, err := a.stor.assets.newestConstInfo(proto.AssetIDFromDigest(snapshot.AssetID)) // only issuer can set new asset script - //if err != nil { - // return errors.Wrapf(err, "failed to get const asset info for asset %q", snapshot.AssetID.String()) - //} - return a.stor.scriptsStorage.setAssetScript(snapshot.AssetID, snapshot.Script, snapshot.SenderPK, a.info.BlockID()) + constInfo, err := a.stor.assets.newestConstInfo(proto.AssetIDFromDigest(snapshot.AssetID)) // only issuer can set new asset script + if err != nil { + return errors.Wrapf(err, "failed to get const asset info for asset %q", snapshot.AssetID.String()) + } + return a.stor.scriptsStorage.setAssetScript(snapshot.AssetID, snapshot.Script, constInfo.issuer, a.info.BlockID()) } func (a *blockSnapshotsApplier) ApplySponsorship(snapshot SponsorshipSnapshot) error { diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index ea6d0ecc8..2504335ef 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -4,12 +4,13 @@ import ( "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" + "github.com/wavesplatform/gowaves/pkg/settings" "math/big" ) type snapshotGenerator struct { - stor *blockchainEntitiesStorage - scheme proto.Scheme + stor *blockchainEntitiesStorage + settings *settings.BlockchainSettings } type assetBalanceDiffKey struct { @@ -21,14 +22,23 @@ type addressWavesBalanceDiff map[proto.WavesAddress]balanceDiff type addressAssetBalanceDiff map[assetBalanceDiffKey]int64 func (sg *snapshotGenerator) generateSnapshotForGenesisTx(balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { + return nil, nil + } return sg.generateBalancesSnapshot(balanceChanges) } func (sg *snapshotGenerator) generateSnapshotForPaymentTx(balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { + return nil, nil + } return sg.generateBalancesSnapshot(balanceChanges) } func (sg *snapshotGenerator) generateSnapshotForTransferTx(balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { + return nil, nil + } return sg.generateBalancesSnapshot(balanceChanges) } @@ -38,8 +48,12 @@ type scriptInformation struct { } func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, txID crypto.Digest, senderPK crypto.PublicKey, assetInfo assetInfo, balanceChanges txDiff, scriptInformation *scriptInformation) (TransactionSnapshot, error) { + if balanceChanges == nil { + return nil, nil + } var snapshot TransactionSnapshot - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.scheme) + // TODO add asset script snapshot + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.settings.AddressSchemeCharacter) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") } @@ -109,6 +123,9 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t } func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, change assetReissueChange, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { + return nil, nil + } quantityDiff := big.NewInt(change.diff) assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) if err != nil { @@ -130,6 +147,9 @@ func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, } func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, change assetBurnChange, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { + return nil, nil + } quantityDiff := big.NewInt(change.diff) assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) if err != nil { @@ -151,6 +171,9 @@ func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, ch } func (sg *snapshotGenerator) generateSnapshotForExchangeTx(sellOrder proto.Order, sellFee uint64, buyOrder proto.Order, buyFee uint64, volume uint64, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { + return nil, nil + } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") @@ -178,6 +201,9 @@ func (sg *snapshotGenerator) generateSnapshotForExchangeTx(sellOrder proto.Order } func (sg *snapshotGenerator) generateSnapshotForLeaseTx(lease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { + return nil, nil + } var err error snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { @@ -194,6 +220,9 @@ func (sg *snapshotGenerator) generateSnapshotForLeaseTx(lease leasing, leaseID c } func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Digest, oldLease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, cancelHeight uint64, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { + return nil, nil + } var err error snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { @@ -215,6 +244,9 @@ func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Diges } func (sg *snapshotGenerator) generateSnapshotForCreateAliasTx(senderAddress proto.WavesAddress, alias proto.Alias, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { + return nil, nil + } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -228,10 +260,16 @@ func (sg *snapshotGenerator) generateSnapshotForCreateAliasTx(senderAddress prot } func (sg *snapshotGenerator) generateSnapshotForMassTransferTx(balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { + return nil, nil + } return sg.generateBalancesSnapshot(balanceChanges) } func (sg *snapshotGenerator) generateSnapshotForDataTx(senderAddress proto.WavesAddress, entries []proto.DataEntry, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { + return nil, nil + } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -245,6 +283,9 @@ func (sg *snapshotGenerator) generateSnapshotForDataTx(senderAddress proto.Waves } func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Digest, minAssetFee uint64, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { + return nil, nil + } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -258,6 +299,9 @@ func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Dig } func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.PublicKey, script proto.Script, complexity int, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { + return nil, nil + } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -272,7 +316,10 @@ func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.Publ return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, complexity int, senderPK crypto.PublicKey, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, complexity int, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { + return nil, nil + } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -282,7 +329,6 @@ func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto. AssetID: assetID, Script: script, Complexity: uint64(complexity), - SenderPK: senderPK, } snapshot = append(snapshot, sponsorshipSnapshot) return snapshot, nil @@ -301,6 +347,9 @@ func (sg *snapshotGenerator) generateSnapshotForEthereumInvokeScriptTx(txID cryp } func (sg *snapshotGenerator) generateSnapshotForUpdateAssetInfoTx(assetID crypto.Digest, assetName string, assetDescription string, changeHeight proto.Height, balanceChanges txDiff) (TransactionSnapshot, error) { + if balanceChanges == nil { + return nil, nil + } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { @@ -325,7 +374,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( blockHeight := info.height + 1 - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.scheme) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.settings.AddressSchemeCharacter) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") } @@ -337,7 +386,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( switch a := action.(type) { case *proto.DataEntryScriptAction: - senderAddr, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) + senderAddr, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) if err != nil { return nil, err } @@ -351,7 +400,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( } case *proto.AttachedPaymentScriptAction: - senderAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) + senderAddress, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) if err != nil { return nil, errors.Wrap(err, "failed to get an address from a public key") } @@ -366,7 +415,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( addToWavesBalanceDiff(addrWavesBalanceDiff, senderAddress, recipientAddress, a.Amount) } case *proto.TransferScriptAction: - senderAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) + senderAddress, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) if err != nil { return nil, errors.Wrap(err, "failed to get an address from a public key") } @@ -403,7 +452,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( reissuable: a.Reissuable, }, } - issuerAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) + issuerAddress, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) if err != nil { return nil, errors.Wrap(err, "failed to get an address from a public key") } @@ -446,7 +495,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( IsReissuable: a.Reissuable, } - issueAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) + issueAddress, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) if err != nil { return nil, errors.Wrap(err, "failed to get an address from a public key") } @@ -466,14 +515,14 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( IsReissuable: assetInfo.reissuable, } - issueAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) + issueAddress, err := proto.NewAddressFromPublicKey(sg.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(sg.scheme, *a.Sender) + senderAddr, err := proto.NewAddressFromPublicKey(sg.settings.AddressSchemeCharacter, *a.Sender) if err != nil { return nil, err } @@ -594,7 +643,7 @@ func (sg *snapshotGenerator) generateOrderAtomicSnapshot(orderID []byte, volume func (sg *snapshotGenerator) generateBalancesSnapshot(balanceChanges txDiff) (TransactionSnapshot, error) { var transactionSnapshot TransactionSnapshot - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.scheme) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.settings.AddressSchemeCharacter) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") } diff --git a/pkg/state/snapshot_generator_test.go b/pkg/state/snapshot_generator_test.go index 104e9de65..a652ef035 100644 --- a/pkg/state/snapshot_generator_test.go +++ b/pkg/state/snapshot_generator_test.go @@ -36,7 +36,7 @@ func defaultPerformerInfoWithChecker(checkerData txCheckerData) *performerInfo { return &performerInfo{0, blockID0, proto.WavesAddress{}, new(proto.StateActionsCounter), checkerData} } -func customCheckerInfo() *checkerInfo { +func defaultCheckerInfoHeight() *checkerInfo { defaultBlockInfo := defaultBlockInfo() return &checkerInfo{ currentTimestamp: defaultBlockInfo.Timestamp, @@ -47,15 +47,17 @@ func customCheckerInfo() *checkerInfo { } } -func createCheckerCustomTestObjects(t *testing.T, differ *differTestObjects) *checkerTestObjects { - tc, err := newTransactionChecker(proto.NewBlockIDFromSignature(genSig), differ.stor.entities, settings.MainNetSettings) +func createCheckerCustomTestObjects(t *testing.T, stor *testStorageObjects) *checkerTestObjects { + tc, err := newTransactionChecker(proto.NewBlockIDFromSignature(genSig), stor.entities, settings.MainNetSettings) require.NoError(t, err, "newTransactionChecker() failed") - return &checkerTestObjects{differ.stor, tc, differ.tp, differ.stateActionsCounter} + snapshotGenerator := &snapshotGenerator{stor: stor.entities, settings: settings.MainNetSettings} + tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) + require.NoError(t, err, "newTransactionPerformer() failed") + return &checkerTestObjects{stor, tc, tp} } func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { - checkerInfo := customCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -70,7 +72,7 @@ func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { ch, err := to.td.createDiffTransferWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffTransferWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performTransferWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performTransferWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform transfer tx") expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ @@ -109,8 +111,7 @@ func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { // TODO send only txBalanceChanges to perfomer func TestDefaultIssueTransactionSnapshot(t *testing.T) { - checkerInfo := customCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -123,7 +124,7 @@ func TestDefaultIssueTransactionSnapshot(t *testing.T) { ch, err := to.td.createDiffIssueWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffIssueWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform issue tx") expectedSnapshot := TransactionSnapshot{ @@ -179,8 +180,7 @@ func TestDefaultIssueTransactionSnapshot(t *testing.T) { } func TestDefaultReissueSnapshot(t *testing.T) { - checkerInfo := customCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -198,7 +198,7 @@ func TestDefaultReissueSnapshot(t *testing.T) { ch, err := to.td.createDiffReissueWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffReissueWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform reissue tx") expectedSnapshot := TransactionSnapshot{ @@ -243,8 +243,7 @@ func TestDefaultReissueSnapshot(t *testing.T) { } func TestDefaultBurnSnapshot(t *testing.T) { - checkerInfo := customCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -262,7 +261,7 @@ func TestDefaultBurnSnapshot(t *testing.T) { ch, err := to.td.createDiffBurnWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -307,8 +306,7 @@ func TestDefaultBurnSnapshot(t *testing.T) { } func TestDefaultExchangeTransaction(t *testing.T) { - checkerInfo := customCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -347,7 +345,7 @@ func TestDefaultExchangeTransaction(t *testing.T) { ch, err := to.td.createDiffExchange(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performExchange(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performExchange(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -420,8 +418,7 @@ func TestDefaultExchangeTransaction(t *testing.T) { } func TestDefaultLeaseSnapshot(t *testing.T) { - checkerInfo := customCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -435,7 +432,7 @@ func TestDefaultLeaseSnapshot(t *testing.T) { ch, err := to.td.createDiffLeaseWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -491,8 +488,7 @@ func TestDefaultLeaseSnapshot(t *testing.T) { } func TestDefaultLeaseCancelSnapshot(t *testing.T) { - checkerInfo := customCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -520,7 +516,7 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { ch, err := to.td.createDiffLeaseCancelWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -577,8 +573,7 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { } func TestDefaultCreateAliasSnapshot(t *testing.T) { - checkerInfo := customCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -592,7 +587,7 @@ func TestDefaultCreateAliasSnapshot(t *testing.T) { ch, err := to.td.createDiffCreateAliasWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -631,8 +626,7 @@ func TestDefaultCreateAliasSnapshot(t *testing.T) { } func TestDefaultDataSnapshot(t *testing.T) { - checkerInfo := customCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -652,7 +646,7 @@ func TestDefaultDataSnapshot(t *testing.T) { ch, err := to.td.createDiffDataWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -691,8 +685,7 @@ func TestDefaultDataSnapshot(t *testing.T) { } func TestDefaultSponsorshipSnapshot(t *testing.T) { - checkerInfo := customCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -706,7 +699,7 @@ func TestDefaultSponsorshipSnapshot(t *testing.T) { ch, err := to.td.createDiffSponsorshipWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -745,8 +738,7 @@ func TestDefaultSponsorshipSnapshot(t *testing.T) { } func TestDefaultSetScriptSnapshot(t *testing.T) { - checkerInfo := customCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -758,7 +750,8 @@ func TestDefaultSetScriptSnapshot(t *testing.T) { err = tx.Sign(proto.TestNetScheme, testGlobal.senderInfo.sk) assert.NoError(t, err, "failed to sign set script tx") - co := createCheckerCustomTestObjects(t, to) + co := createCheckerCustomTestObjects(t, to.stor) + checkerInfo := defaultCheckerInfoHeight() co.stor = to.stor checkerData, err := co.tc.checkSetScriptWithProofs(tx, checkerInfo) assert.NoError(t, err, "failed to check set script tx") @@ -806,8 +799,7 @@ func TestDefaultSetScriptSnapshot(t *testing.T) { } func TestDefaultSetAssetScriptSnapshot(t *testing.T) { - checkerInfo := customCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -825,7 +817,8 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.T) { err = tx.Sign(proto.TestNetScheme, testGlobal.senderInfo.sk) assert.NoError(t, err, "failed to sign burn tx") - co := createCheckerCustomTestObjects(t, to) + co := createCheckerCustomTestObjects(t, to.stor) + checkerInfo := defaultCheckerInfoHeight() co.stor = to.stor checkerData, err := co.tc.checkSetAssetScriptWithProofs(tx, checkerInfo) assert.NoError(t, err, "failed to check set script tx") @@ -849,7 +842,6 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.T) { AssetID: testGlobal.asset0.assetID, Script: testGlobal.scriptBytes, Complexity: 340, - SenderPK: tx.SenderPK, }, } @@ -903,8 +895,7 @@ func TestDefaultInvokeScriptSnapshot(t *testing.T) { scriptsBytes, err := base64.StdEncoding.DecodeString(script) assert.NoError(t, err, "failed to set decode base64 script") - checkerInfo := customCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) to.stor.addBlock(t, blockID0) to.stor.activateFeature(t, int16(settings.NG)) @@ -924,7 +915,8 @@ func TestDefaultInvokeScriptSnapshot(t *testing.T) { err = tx.Sign(proto.TestNetScheme, testGlobal.senderInfo.sk) assert.NoError(t, err, "failed to sign invoke script tx") - co := createCheckerCustomTestObjects(t, to) + co := createCheckerCustomTestObjects(t, to.stor) + checkerInfo := defaultCheckerInfoHeight() co.stor = to.stor checkerData, err := co.tc.checkInvokeScriptWithProofs(tx, checkerInfo) assert.NoError(t, err, "failed to check invoke script tx") diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 1551c3e59..6ff55ec17 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -1,7 +1,6 @@ package state import ( - "github.com/pkg/errors" "math/big" "github.com/wavesplatform/gowaves/pkg/crypto" @@ -10,33 +9,13 @@ import ( type TransactionSnapshot []AtomicSnapshot -func (ts TransactionSnapshot) Apply(a SnapshotApplier) error { - for _, atomicSnapshot := range ts { - if !atomicSnapshot.IsGeneratedByTxDiff() { - err := atomicSnapshot.Apply(a) - if err != nil { - return errors.Wrap(err, "failed to apply transaction snapshot") - } - } - } - return nil -} - -type AtomicSnapshot interface { - Apply(SnapshotApplier) error - /*is temporarily used to mark snapshots generated by tx diff that shouldn't be applied , because balances diffs are applied later in the block */ - IsGeneratedByTxDiff() bool -} +type AtomicSnapshot interface{ Apply(SnapshotApplier) error } type WavesBalanceSnapshot struct { Address proto.WavesAddress Balance uint64 } -func (s WavesBalanceSnapshot) IsGeneratedByTxDiff() bool { - return true -} - func (s WavesBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyWavesBalance(s) } type AssetBalanceSnapshot struct { @@ -45,10 +24,6 @@ type AssetBalanceSnapshot struct { Balance uint64 } -func (s AssetBalanceSnapshot) IsGeneratedByTxDiff() bool { - return true -} - func (s AssetBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetBalance(s) } type DataEntriesSnapshot struct { // AccountData in pb @@ -56,10 +31,6 @@ type DataEntriesSnapshot struct { // AccountData in pb DataEntries []proto.DataEntry } -func (s DataEntriesSnapshot) IsGeneratedByTxDiff() bool { - return false -} - func (s DataEntriesSnapshot) Apply(a SnapshotApplier) error { return a.ApplyDataEntries(s) } type AccountScriptSnapshot struct { @@ -68,23 +39,14 @@ type AccountScriptSnapshot struct { VerifierComplexity uint64 } -func (s AccountScriptSnapshot) IsGeneratedByTxDiff() bool { - return false -} - func (s AccountScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAccountScript(s) } type AssetScriptSnapshot struct { AssetID crypto.Digest Script proto.Script - SenderPK crypto.PublicKey // should be removed later Complexity uint64 } -func (s AssetScriptSnapshot) IsGeneratedByTxDiff() bool { - return false -} - func (s AssetScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetScript(s) } type LeaseBalanceSnapshot struct { @@ -93,10 +55,6 @@ type LeaseBalanceSnapshot struct { LeaseOut uint64 } -func (s LeaseBalanceSnapshot) IsGeneratedByTxDiff() bool { - return false -} - func (s LeaseBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseBalance(s) } type LeaseStateStatus struct { @@ -115,10 +73,6 @@ type LeaseStateSnapshot struct { Height proto.Height } -func (s LeaseStateSnapshot) IsGeneratedByTxDiff() bool { - return false -} - func (s LeaseStateSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseState(s) } type SponsorshipSnapshot struct { @@ -126,10 +80,6 @@ type SponsorshipSnapshot struct { MinSponsoredFee uint64 } -func (s SponsorshipSnapshot) IsGeneratedByTxDiff() bool { - return false -} - func (s SponsorshipSnapshot) Apply(a SnapshotApplier) error { return a.ApplySponsorship(s) } type AliasSnapshot struct { @@ -137,10 +87,6 @@ type AliasSnapshot struct { Alias proto.Alias } -func (s AliasSnapshot) IsGeneratedByTxDiff() bool { - return false -} - func (s AliasSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAlias(s) } // FilledVolumeFeeSnapshot Filled Volume and Fee. @@ -150,10 +96,6 @@ type FilledVolumeFeeSnapshot struct { // OrderFill FilledFee uint64 } -func (s FilledVolumeFeeSnapshot) IsGeneratedByTxDiff() bool { - return false -} - func (s FilledVolumeFeeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyFilledVolumeAndFee(s) } type StaticAssetInfoSnapshot struct { @@ -164,10 +106,6 @@ type StaticAssetInfoSnapshot struct { IsNFT bool } -func (s StaticAssetInfoSnapshot) IsGeneratedByTxDiff() bool { - return false -} - func (s StaticAssetInfoSnapshot) Apply(a SnapshotApplier) error { return a.ApplyStaticAssetInfo(s) } type AssetVolumeSnapshot struct { // AssetVolume in pb @@ -176,10 +114,6 @@ type AssetVolumeSnapshot struct { // AssetVolume in pb IsReissuable bool } -func (s AssetVolumeSnapshot) IsGeneratedByTxDiff() bool { - return false -} - func (s AssetVolumeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetVolume(s) } type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb @@ -189,10 +123,6 @@ type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb ChangeHeight proto.Height // last_updated in pb } -func (s AssetDescriptionSnapshot) IsGeneratedByTxDiff() bool { - return false -} - func (s AssetDescriptionSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetDescription(s) } type SnapshotApplier interface { diff --git a/pkg/state/state.go b/pkg/state/state.go index 2206e36a5..cb8febbf9 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -1272,7 +1272,7 @@ func (s *stateManager) needToCancelLeases(blockchainHeight uint64) (bool, error) } } -// TODO what to do with stolen aliases in snapshots? +// TODO generate snapshots here too func (s *stateManager) blockchainHeightAction(blockchainHeight uint64, lastBlock, nextBlock proto.BlockID) error { cancelLeases, err := s.needToCancelLeases(blockchainHeight) if err != nil { @@ -1524,7 +1524,6 @@ func (s *stateManager) addBlocks() (*proto.Block, error) { if err := s.appender.applyAllDiffs(); err != nil { return nil, err } - // Retrieve and store state hashes for each of new blocks. if err := s.stor.handleStateHashes(height, ids); err != nil { return nil, wrapErr(ModificationError, err) diff --git a/pkg/state/transaction_checker_test.go b/pkg/state/transaction_checker_test.go index ff7f81942..101ac9b97 100644 --- a/pkg/state/transaction_checker_test.go +++ b/pkg/state/transaction_checker_test.go @@ -21,43 +21,19 @@ var ( ) type checkerTestObjects struct { - stor *testStorageObjects - tc *transactionChecker - tp *transactionPerformer - stateActionsCounter *proto.StateActionsCounter + stor *testStorageObjects + tc *transactionChecker + tp *transactionPerformer } -func createCheckerTestObjects(t *testing.T, checkerInfo *checkerInfo) *checkerTestObjects { +func createCheckerTestObjects(t *testing.T) *checkerTestObjects { stor := createStorageObjects(t, true) tc, err := newTransactionChecker(proto.NewBlockIDFromSignature(genSig), stor.entities, settings.MainNetSettings) require.NoError(t, err, "newTransactionChecker() failed") - - actionsCounter := new(proto.StateActionsCounter) - snapshotApplier := newBlockSnapshotsApplier( - blockSnapshotsApplierInfo{ - ci: checkerInfo, - scheme: settings.MainNetSettings.AddressSchemeCharacter, - stateActionsCounter: actionsCounter, - }, - snapshotApplierStorages{ - balances: stor.entities.balances, - aliases: stor.entities.aliases, - assets: stor.entities.assets, - scriptsStorage: stor.entities.scriptsStorage, - scriptsComplexity: stor.entities.scriptsComplexity, - sponsoredAssets: stor.entities.sponsoredAssets, - ordersVolumes: stor.entities.ordersVolumes, - accountsDataStor: stor.entities.accountsDataStor, - leases: stor.entities.leases, - }, - ) - snapshotGenerator := snapshotGenerator{stor: stor.entities, scheme: settings.MainNetSettings.AddressSchemeCharacter} - - tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings) - tp.snapshotApplier = &snapshotApplier - tp.snapshotGenerator = &snapshotGenerator + snapshotGenerator := &snapshotGenerator{stor: stor.entities, settings: settings.MainNetSettings} + tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) require.NoError(t, err, "newTransactionPerformer() failed") - return &checkerTestObjects{stor, tc, tp, actionsCounter} + return &checkerTestObjects{stor, tc, tp} } func defaultCheckerInfo() *checkerInfo { @@ -71,11 +47,10 @@ func defaultCheckerInfo() *checkerInfo { } func TestCheckGenesis(t *testing.T) { - - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) tx := createGenesis() + info := defaultCheckerInfo() _, err := to.tc.checkGenesis(tx, info) assert.EqualError(t, err, "genesis transaction inside of non-genesis block") @@ -94,11 +69,10 @@ func TestCheckGenesis(t *testing.T) { } func TestCheckPayment(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) tx := createPayment(t) - + info := defaultCheckerInfo() info.height = settings.MainNetSettings.BlockVersion3AfterHeight _, err := to.tc.checkPayment(tx, info) assert.Error(t, err, "checkPayment accepted payment tx after Block v3 height") @@ -112,10 +86,10 @@ func TestCheckPayment(t *testing.T) { } func TestCheckTransferWithSig(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) tx := createTransferWithSig(t) + info := defaultCheckerInfo() assetId := tx.FeeAsset.ID @@ -150,10 +124,10 @@ func TestCheckTransferWithSig(t *testing.T) { } func TestCheckTransferWithProofs(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) tx := createTransferWithProofs(t) + info := defaultCheckerInfo() assetId := tx.FeeAsset.ID @@ -195,8 +169,7 @@ func TestCheckTransferWithProofs(t *testing.T) { } func TestCheckIsValidUtf8(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) err := to.tc.isValidUtf8("just a normal string") assert.NoError(t, err) @@ -214,11 +187,10 @@ func TestCheckIsValidUtf8(t *testing.T) { } func TestCheckIssueWithSig(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) tx := createIssueWithSig(t, 1000) - + info := defaultCheckerInfo() _, err := to.tc.checkIssueWithSig(tx, info) assert.NoError(t, err, "checkIssueWithSig failed with valid issue tx") @@ -228,11 +200,10 @@ func TestCheckIssueWithSig(t *testing.T) { } func TestCheckIssueWithProofs(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) tx := createIssueWithProofs(t, 1000) - + info := defaultCheckerInfo() to.stor.addBlock(t, blockID0) _, err := to.tc.checkIssueWithProofs(tx, info) @@ -244,14 +215,13 @@ func TestCheckIssueWithProofs(t *testing.T) { } func TestCheckReissueWithSig(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithSig(t, 1000) tx.SenderPK = assetInfo.issuer - + info := defaultCheckerInfo() info.currentTimestamp = settings.MainNetSettings.ReissueBugWindowTimeEnd + 1 _, err := to.tc.checkReissueWithSig(tx, info) assert.NoError(t, err, "checkReissueWithSig failed with valid reissue tx") @@ -276,7 +246,7 @@ func TestCheckReissueWithSig(t *testing.T) { tx.SenderPK = assetInfo.issuer tx.Reissuable = false - _, err = to.tp.performReissueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err = to.tp.performReissueWithSig(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performReissueWithSig failed") to.stor.addBlock(t, blockID0) to.stor.flush(t) @@ -287,14 +257,13 @@ func TestCheckReissueWithSig(t *testing.T) { } func TestCheckReissueWithProofs(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithProofs(t, 1000) tx.SenderPK = assetInfo.issuer - + info := defaultCheckerInfo() info.currentTimestamp = settings.MainNetSettings.ReissueBugWindowTimeEnd + 1 _, err := to.tc.checkReissueWithProofs(tx, info) @@ -325,7 +294,7 @@ func TestCheckReissueWithProofs(t *testing.T) { tx.SenderPK = assetInfo.issuer tx.Reissuable = false - _, err = to.tp.performReissueWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err = to.tp.performReissueWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performReissueWithProofs failed") to.stor.addBlock(t, blockID0) to.stor.flush(t) @@ -336,12 +305,12 @@ func TestCheckReissueWithProofs(t *testing.T) { } func TestCheckBurnWithSig(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithSig(t) tx.SenderPK = assetInfo.issuer + info := defaultCheckerInfo() _, err := to.tc.checkBurnWithSig(tx, info) assert.NoError(t, err, "checkBurnWithSig failed with valid burn tx") @@ -370,12 +339,12 @@ func TestCheckBurnWithSig(t *testing.T) { } func TestCheckBurnWithProofs(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithProofs(t) tx.SenderPK = assetInfo.issuer + info := defaultCheckerInfo() _, err := to.tc.checkBurnWithProofs(tx, info) assert.Error(t, err, "checkBurnWithProofs did not fail prior to SmartAccounts activation") @@ -409,11 +378,10 @@ func TestCheckBurnWithProofs(t *testing.T) { } func TestCheckExchangeWithSig(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) tx := createExchangeWithSig(t) - + info := defaultCheckerInfo() _, err := to.tc.checkExchangeWithSig(tx, info) assert.Error(t, err, "checkExchangeWithSig did not fail with exchange with unknown assets") @@ -476,11 +444,10 @@ func TestCheckExchangeWithSig(t *testing.T) { } func TestCheckExchangeWithProofs(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) txOV2 := createExchangeWithProofs(t) - + info := defaultCheckerInfo() _, err := to.tc.checkExchangeWithProofs(txOV2, info) assert.Error(t, err, "checkExchangeWithProofs did not fail with exchange with unknown assets") @@ -572,10 +539,10 @@ func TestCheckExchangeWithProofs(t *testing.T) { } func TestCheckUnorderedExchangeV2WithProofs(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) tx := createUnorderedExchangeWithProofs(t, 2) + info := defaultCheckerInfo() to.stor.createAsset(t, testGlobal.asset0.asset.ID) to.stor.createAsset(t, testGlobal.asset1.asset.ID) @@ -591,10 +558,10 @@ func TestCheckUnorderedExchangeV2WithProofs(t *testing.T) { } func TestCheckUnorderedExchangeV3WithProofs(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) tx := createUnorderedExchangeWithProofs(t, 3) + info := defaultCheckerInfo() to.stor.createAsset(t, testGlobal.asset0.asset.ID) to.stor.createAsset(t, testGlobal.asset1.asset.ID) @@ -610,11 +577,10 @@ func TestCheckUnorderedExchangeV3WithProofs(t *testing.T) { } func TestCheckLeaseWithSig(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) tx := createLeaseWithSig(t) - + info := defaultCheckerInfo() tx.Recipient = proto.NewRecipientFromAddress(testGlobal.senderInfo.addr) _, err := to.tc.checkLeaseWithSig(tx, info) assert.Error(t, err, "checkLeaseWithSig did not fail when leasing to self") @@ -625,11 +591,10 @@ func TestCheckLeaseWithSig(t *testing.T) { } func TestCheckLeaseWithProofs(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) tx := createLeaseWithProofs(t) - + info := defaultCheckerInfo() tx.Recipient = proto.NewRecipientFromAddress(testGlobal.senderInfo.addr) _, err := to.tc.checkLeaseWithProofs(tx, info) assert.Error(t, err, "checkLeaseWithProofs did not fail when leasing to self") @@ -646,11 +611,10 @@ func TestCheckLeaseWithProofs(t *testing.T) { } func TestCheckLeaseCancelWithSig(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) leaseTx := createLeaseWithSig(t) - + info := defaultCheckerInfo() info.currentTimestamp = settings.MainNetSettings.AllowMultipleLeaseCancelUntilTime + 1 tx := createLeaseCancelWithSig(t, *leaseTx.ID) @@ -658,7 +622,7 @@ func TestCheckLeaseCancelWithSig(t *testing.T) { assert.Error(t, err, "checkLeaseCancelWithSig did not fail when cancelling nonexistent lease") to.stor.addBlock(t, blockID0) - _, err = to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err = to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performLeaseWithSig failed") to.stor.flush(t) @@ -675,11 +639,10 @@ func TestCheckLeaseCancelWithSig(t *testing.T) { } func TestCheckLeaseCancelWithProofs(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) leaseTx := createLeaseWithProofs(t) - + info := defaultCheckerInfo() info.currentTimestamp = settings.MainNetSettings.AllowMultipleLeaseCancelUntilTime + 1 tx := createLeaseCancelWithProofs(t, *leaseTx.ID) @@ -687,7 +650,7 @@ func TestCheckLeaseCancelWithProofs(t *testing.T) { assert.Error(t, err, "checkLeaseCancelWithProofs did not fail when cancelling nonexistent lease") to.stor.addBlock(t, blockID0) - _, err = to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err = to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performLeaseWithProofs failed") to.stor.flush(t) @@ -703,7 +666,7 @@ func TestCheckLeaseCancelWithProofs(t *testing.T) { _, err = to.tc.checkLeaseCancelWithProofs(tx, info) assert.NoError(t, err, "checkLeaseCancelWithProofs failed with valid leaseCancel tx") - _, err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performLeaseCancelWithProofs() failed") _, err = to.tc.checkLeaseCancelWithProofs(tx, info) @@ -711,16 +674,16 @@ func TestCheckLeaseCancelWithProofs(t *testing.T) { } func TestCheckCreateAliasWithSig(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) tx := createCreateAliasWithSig(t) + info := defaultCheckerInfo() _, err := to.tc.checkCreateAliasWithSig(tx, info) assert.NoError(t, err, "checkCreateAliasWithSig failed with valid createAlias tx") to.stor.addBlock(t, blockID0) - _, err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performCreateAliasWithSig failed") to.stor.flush(t) @@ -734,10 +697,10 @@ func TestCheckCreateAliasWithSig(t *testing.T) { } func TestCheckCreateAliasWithProofs(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) tx := createCreateAliasWithProofs(t) + info := defaultCheckerInfo() _, err := to.tc.checkCreateAliasWithProofs(tx, info) assert.Error(t, err, "checkCreateAliasWithProofs did not fail prior to SmartAccounts activation") @@ -748,7 +711,7 @@ func TestCheckCreateAliasWithProofs(t *testing.T) { assert.NoError(t, err, "checkCreateAliasWithProofs failed with valid createAlias tx") to.stor.addBlock(t, blockID0) - _, err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performCreateAliasWithProofs failed") to.stor.flush(t) @@ -762,12 +725,12 @@ func TestCheckCreateAliasWithProofs(t *testing.T) { } func TestCheckMassTransferWithProofs(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) entriesNum := 50 entries := generateMassTransferEntries(t, entriesNum) tx := createMassTransferWithProofs(t, entries) + info := defaultCheckerInfo() _, err := to.tc.checkMassTransferWithProofs(tx, info) assert.Error(t, err, "checkMassTransferWithProofs did not fail prior to feature activation") @@ -793,10 +756,10 @@ func TestCheckMassTransferWithProofs(t *testing.T) { } func TestCheckDataWithProofs(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) tx := createDataWithProofs(t, 1) + info := defaultCheckerInfo() _, err := to.tc.checkDataWithProofs(tx, info) assert.Error(t, err, "checkDataWithProofs did not fail prior to feature activation") @@ -839,12 +802,12 @@ func TestCheckDataWithProofs(t *testing.T) { } func TestCheckSponsorshipWithProofs(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) tx := createSponsorshipWithProofs(t, 1000) assetInfo := to.stor.createAsset(t, tx.AssetID) tx.SenderPK = assetInfo.issuer + info := defaultCheckerInfo() _, err := to.tc.checkSponsorshipWithProofs(tx, info) assert.Error(t, err, "checkSponsorshipWithProofs did not fail prior to feature activation") @@ -882,10 +845,10 @@ func TestCheckSponsorshipWithProofs(t *testing.T) { } func TestCheckSetScriptWithProofs(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) tx := createSetScriptWithProofs(t) + info := defaultCheckerInfo() // Activate sponsorship. to.stor.activateSponsorship(t) @@ -1380,10 +1343,10 @@ func TestCheckSetScriptWithProofsCheckDAppCallables(t *testing.T) { } func TestCheckSetAssetScriptWithProofs(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) tx := createSetAssetScriptWithProofs(t) + info := defaultCheckerInfo() assetInfo := defaultAssetInfo(proto.DigestTail(tx.AssetID), true) assetInfo.issuer = tx.SenderPK @@ -1416,14 +1379,13 @@ func TestCheckSetAssetScriptWithProofs(t *testing.T) { } func TestCheckInvokeScriptWithProofs(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) payments := []proto.ScriptPayment{ {Amount: 1, Asset: *testGlobal.asset0.asset}, } tx := createInvokeScriptWithProofs(t, payments, proto.FunctionCall{}, proto.OptionalAsset{}, 1) - + info := defaultCheckerInfo() to.stor.addBlock(t, blockID0) assetId := tx.Payments[0].Asset.ID to.stor.createAsset(t, assetId) @@ -1456,8 +1418,7 @@ func TestCheckInvokeScriptWithProofs(t *testing.T) { } func TestCheckUpdateAssetInfoWithProofs(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) tx := createUpdateAssetInfoWithProofs(t) // We create asset using random block here on purpose, this way @@ -1466,6 +1427,7 @@ func TestCheckUpdateAssetInfoWithProofs(t *testing.T) { to.stor.createAsset(t, tx.FeeAsset.ID) tx.SenderPK = assetInfo.issuer + info := defaultCheckerInfo() info.height = 100001 // Check fail prior to activation. @@ -1498,10 +1460,10 @@ func TestCheckUpdateAssetInfoWithProofs(t *testing.T) { } func TestCheckInvokeExpressionWithProofs(t *testing.T) { - info := defaultCheckerInfo() - to := createCheckerTestObjects(t, info) + to := createCheckerTestObjects(t) tx := createInvokeExpressionWithProofs(t, make([]byte, 1), proto.OptionalAsset{}, 1) + info := defaultCheckerInfo() // Check activation. _, err := to.tc.checkInvokeScriptWithProofs(tx, info) diff --git a/pkg/state/transaction_differ_test.go b/pkg/state/transaction_differ_test.go index a20236f51..7f5e312d1 100644 --- a/pkg/state/transaction_differ_test.go +++ b/pkg/state/transaction_differ_test.go @@ -26,43 +26,19 @@ var ( ) type differTestObjects struct { - stor *testStorageObjects - td *transactionDiffer - tp *transactionPerformer - stateActionsCounter *proto.StateActionsCounter + stor *testStorageObjects + td *transactionDiffer + tp *transactionPerformer } -func createDifferTestObjects(t *testing.T, checkerInfo *checkerInfo) *differTestObjects { +func createDifferTestObjects(t *testing.T) *differTestObjects { stor := createStorageObjects(t, true) td, err := newTransactionDiffer(stor.entities, settings.MainNetSettings) require.NoError(t, err, "newTransactionDiffer() failed") - - actionsCounter := new(proto.StateActionsCounter) - - snapshotApplier := newBlockSnapshotsApplier( - blockSnapshotsApplierInfo{ - ci: checkerInfo, - scheme: settings.MainNetSettings.AddressSchemeCharacter, - stateActionsCounter: actionsCounter, - }, - snapshotApplierStorages{ - balances: stor.entities.balances, - aliases: stor.entities.aliases, - assets: stor.entities.assets, - scriptsStorage: stor.entities.scriptsStorage, - scriptsComplexity: stor.entities.scriptsComplexity, - sponsoredAssets: stor.entities.sponsoredAssets, - ordersVolumes: stor.entities.ordersVolumes, - accountsDataStor: stor.entities.accountsDataStor, - leases: stor.entities.leases, - }, - ) - snapshotGenerator := snapshotGenerator{stor: stor.entities, scheme: settings.MainNetSettings.AddressSchemeCharacter} - tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings) - tp.snapshotApplier = &snapshotApplier - tp.snapshotGenerator = &snapshotGenerator + snapshotGenerator := &snapshotGenerator{stor: stor.entities, settings: settings.MainNetSettings} + tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) require.NoError(t, err, "newTransactionPerformer() failed") - return &differTestObjects{stor, td, tp, actionsCounter} + return &differTestObjects{stor, td, tp} } func createGenesis() *proto.Genesis { @@ -70,8 +46,7 @@ func createGenesis() *proto.Genesis { } func TestCreateDiffGenesis(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createGenesis() ch, err := to.td.createDiffGenesis(tx, defaultDifferInfo()) @@ -92,8 +67,7 @@ func createPayment(t *testing.T) *proto.Payment { } func TestCreateDiffPayment(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createPayment(t) ch, err := to.td.createDiffPayment(tx, defaultDifferInfo()) @@ -120,8 +94,7 @@ func createTransferWithSig(t *testing.T) *proto.TransferWithSig { } func TestCreateDiffTransferWithSig(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createTransferWithSig(t) feeFullAssetID := tx.FeeAsset.ID @@ -178,8 +151,7 @@ func createTransferWithProofs(t *testing.T) *proto.TransferWithProofs { } func TestCreateDiffTransferWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createTransferWithProofs(t) feeFullAssetID := tx.FeeAsset.ID @@ -243,8 +215,7 @@ func createNFTIssueWithSig(t *testing.T) *proto.IssueWithSig { } func TestCreateDiffIssueWithSig(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createIssueWithSig(t, 1000) ch, err := to.td.createDiffIssueWithSig(tx, defaultDifferInfo()) @@ -278,8 +249,7 @@ func createNFTIssueWithProofs(t *testing.T) *proto.IssueWithProofs { } func TestCreateDiffIssueWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createIssueWithProofs(t, 1000) ch, err := to.td.createDiffIssueWithProofs(tx, defaultDifferInfo()) @@ -306,8 +276,7 @@ func createReissueWithSig(t *testing.T, feeUnits int) *proto.ReissueWithSig { } func TestCreateDiffReissueWithSig(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createReissueWithSig(t, 1000) ch, err := to.td.createDiffReissueWithSig(tx, defaultDifferInfo()) @@ -333,8 +302,7 @@ func createReissueWithProofs(t *testing.T, feeUnits int) *proto.ReissueWithProof } func TestCreateDiffReissueWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createReissueWithProofs(t, 1000) ch, err := to.td.createDiffReissueWithProofs(tx, defaultDifferInfo()) @@ -360,8 +328,7 @@ func createBurnWithSig(t *testing.T) *proto.BurnWithSig { } func TestCreateDiffBurnWithSig(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createBurnWithSig(t) ch, err := to.td.createDiffBurnWithSig(tx, defaultDifferInfo()) @@ -387,8 +354,7 @@ func createBurnWithProofs(t *testing.T) *proto.BurnWithProofs { } func TestCreateDiffBurnWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createBurnWithProofs(t) ch, err := to.td.createDiffBurnWithProofs(tx, defaultDifferInfo()) @@ -434,8 +400,7 @@ func createExchangeWithSig(t *testing.T) *proto.ExchangeWithSig { //} func TestCreateDiffExchangeWithSig(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createExchangeWithSig(t) ch, err := to.td.createDiffExchange(tx, defaultDifferInfo()) @@ -488,8 +453,7 @@ func createUnorderedExchangeWithProofs(t *testing.T, v int) *proto.ExchangeWithP } func TestCreateDiffExchangeWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createExchangeWithProofs(t) ch, err := to.td.createDiffExchange(tx, defaultDifferInfo()) @@ -598,8 +562,7 @@ func createExchangeV2WithProofsWithOrdersV3(t *testing.T, info orderBuildInfo) * } func TestCreateDiffExchangeV2WithProofsWithOrdersV3(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createExchangeV2WithProofsWithOrdersV3(t, orderBuildInfo{ price: 10e8, @@ -630,8 +593,7 @@ func TestCreateDiffExchangeV2WithProofsWithOrdersV3(t *testing.T) { } func TestCreateDiffExchangeV3WithProofsWithMixedOrders(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) const ( asset0Decimals = 5 @@ -738,7 +700,7 @@ func TestCreateDiffExchangeV3WithProofsWithMixedOrders(t *testing.T) { // and produces an incorrect or unexpected diff, should be fixes some how // // func TestCreateDiffExchangeWithSignature(t *testing.T) { -// to, path := createDifferTestObjects(t, checkerInfo +// to, path := createDifferTestObjects(t) // // to.stor.createAssetWithDecimals(t, testGlobal.asset0.asset.ID, 8) // to.stor.createAssetWithDecimals(t, testGlobal.asset1.asset.ID, 8) @@ -772,8 +734,7 @@ func TestCreateDiffExchangeV3WithProofsWithMixedOrders(t *testing.T) { // assert.Equal(t, correctAddrs, ch.addrs) // } func TestCreateDiffExchangeV3WithProofsWithOrdersV4(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) to.stor.createAssetWithDecimals(t, testGlobal.asset0.asset.ID, 0) to.stor.createAssetWithDecimals(t, testGlobal.asset1.asset.ID, 8) @@ -846,8 +807,7 @@ func createLeaseWithSig(t *testing.T) *proto.LeaseWithSig { } func TestCreateDiffLeaseWithSig(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createLeaseWithSig(t) ch, err := to.td.createDiffLeaseWithSig(tx, defaultDifferInfo()) @@ -874,8 +834,7 @@ func createLeaseWithProofs(t *testing.T) *proto.LeaseWithProofs { } func TestCreateDiffLeaseWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createLeaseWithProofs(t) ch, err := to.td.createDiffLeaseWithProofs(tx, defaultDifferInfo()) @@ -902,11 +861,10 @@ func createLeaseCancelWithSig(t *testing.T, leaseID crypto.Digest) *proto.LeaseC } func TestCreateDiffLeaseCancelWithSig(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) leaseTx := createLeaseWithSig(t) - info := defaultPerformerInfo(to.stateActionsCounter) + info := defaultPerformerInfo() to.stor.addBlock(t, blockID0) _, err := to.tp.performLeaseWithSig(leaseTx, info, nil, nil) assert.NoError(t, err, "performLeaseWithSig failed") @@ -936,11 +894,10 @@ func createLeaseCancelWithProofs(t *testing.T, leaseID crypto.Digest) *proto.Lea } func TestCreateDiffLeaseCancelWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) leaseTx := createLeaseWithProofs(t) - info := defaultPerformerInfo(to.stateActionsCounter) + info := defaultPerformerInfo() to.stor.addBlock(t, blockID0) _, err := to.tp.performLeaseWithProofs(leaseTx, info, nil, nil) assert.NoError(t, err, "performLeaseWithProofs failed") @@ -974,8 +931,7 @@ func createCreateAliasWithSig(t *testing.T) *proto.CreateAliasWithSig { } func TestCreateDiffCreateAliasWithSig(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createCreateAliasWithSig(t) ch, err := to.td.createDiffCreateAliasWithSig(tx, defaultDifferInfo()) @@ -1004,8 +960,7 @@ func createCreateAliasWithProofs(t *testing.T) *proto.CreateAliasWithProofs { } func TestCreateDiffCreateAliasWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createCreateAliasWithProofs(t) ch, err := to.td.createDiffCreateAliasWithProofs(tx, defaultDifferInfo()) @@ -1041,8 +996,7 @@ func createMassTransferWithProofs(t *testing.T, transfers []proto.MassTransferEn } func TestCreateDiffMassTransferWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) entriesNum := 66 entries := generateMassTransferEntries(t, entriesNum) @@ -1082,8 +1036,7 @@ func createDataWithProofs(t *testing.T, entriesNum int) *proto.DataWithProofs { } func TestCreateDiffDataWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createDataWithProofs(t, 1) ch, err := to.td.createDiffDataWithProofs(tx, defaultDifferInfo()) @@ -1108,8 +1061,7 @@ func createSponsorshipWithProofs(t *testing.T, fee uint64) *proto.SponsorshipWit } func TestCreateDiffSponsorshipWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createSponsorshipWithProofs(t, 1000) ch, err := to.td.createDiffSponsorshipWithProofs(tx, defaultDifferInfo()) @@ -1141,8 +1093,7 @@ func createSetScriptWithProofs(t *testing.T, customScriptBytes ...[]byte) *proto } func TestCreateDiffSetScriptWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createSetScriptWithProofs(t) ch, err := to.td.createDiffSetScriptWithProofs(tx, defaultDifferInfo()) @@ -1169,8 +1120,7 @@ func createSetAssetScriptWithProofs(t *testing.T) *proto.SetAssetScriptWithProof } func TestCreateDiffSetAssetScriptWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createSetAssetScriptWithProofs(t) ch, err := to.td.createDiffSetAssetScriptWithProofs(tx, defaultDifferInfo()) @@ -1195,8 +1145,7 @@ func createInvokeScriptWithProofs(t *testing.T, pmts proto.ScriptPayments, fc pr } func TestCreateDiffInvokeScriptWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) feeConst, ok := feeConstants[proto.InvokeScriptTransaction] assert.Equal(t, ok, true) @@ -1258,8 +1207,7 @@ func createUpdateAssetInfoWithProofs(t *testing.T) *proto.UpdateAssetInfoWithPro } func TestCreateDiffUpdateAssetInfoWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createDifferTestObjects(t, checkerInfo) + to := createDifferTestObjects(t) tx := createUpdateAssetInfoWithProofs(t) ch, err := to.td.createDiffUpdateAssetInfoWithProofs(tx, defaultDifferInfo()) diff --git a/pkg/state/transaction_handler.go b/pkg/state/transaction_handler.go index fef38b57e..4975e9f9b 100644 --- a/pkg/state/transaction_handler.go +++ b/pkg/state/transaction_handler.go @@ -141,7 +141,8 @@ func newTransactionHandler( if err != nil { return nil, err } - tp, err := newTransactionPerformer(stor, settings) + snapshotGenerator := &snapshotGenerator{stor: stor, settings: settings} + tp, err := newTransactionPerformer(stor, settings, snapshotGenerator) if err != nil { return nil, err } diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index d05afc5fd..05f4dfaaf 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -14,7 +14,8 @@ type performerInfo struct { blockID proto.BlockID currentMinerAddress proto.WavesAddress stateActionsCounter *proto.StateActionsCounter - checkerData txCheckerData + // TODO put one into another + checkerData txCheckerData } func newPerformerInfo(height proto.Height, stateActionsCounter *proto.StateActionsCounter, blockID proto.BlockID, currentMinerAddress proto.WavesAddress, checkerData txCheckerData) *performerInfo { @@ -24,12 +25,11 @@ func newPerformerInfo(height proto.Height, stateActionsCounter *proto.StateActio type transactionPerformer struct { stor *blockchainEntitiesStorage settings *settings.BlockchainSettings - snapshotGenerator *snapshotGenerator // initialized in appendTx - snapshotApplier SnapshotApplier // initialized in appendTx + snapshotGenerator *snapshotGenerator } -func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings.BlockchainSettings) (*transactionPerformer, error) { - return &transactionPerformer{stor: stor, settings: settings}, nil +func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings.BlockchainSettings, snapshotGenerator *snapshotGenerator) (*transactionPerformer, error) { + return &transactionPerformer{stor, settings, snapshotGenerator}, nil } func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -37,11 +37,7 @@ func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, _ if !ok { return nil, errors.New("failed to convert interface to genesis transaction") } - snapshot, err := tp.snapshotGenerator.generateSnapshotForGenesisTx(balanceChanges) - if err != nil { - return nil, err - } - return snapshot, snapshot.Apply(tp.snapshotApplier) + return tp.snapshotGenerator.generateSnapshotForGenesisTx(balanceChanges) } func (tp *transactionPerformer) performPayment(transaction proto.Transaction, _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -49,19 +45,11 @@ func (tp *transactionPerformer) performPayment(transaction proto.Transaction, _ if !ok { return nil, errors.New("failed to convert interface to payment transaction") } - snapshot, err := tp.snapshotGenerator.generateSnapshotForPaymentTx(balanceChanges) - if err != nil { - return nil, err - } - return snapshot, snapshot.Apply(tp.snapshotApplier) + return tp.snapshotGenerator.generateSnapshotForPaymentTx(balanceChanges) } func (tp *transactionPerformer) performTransfer(balanceChanges txDiff) (TransactionSnapshot, error) { - snapshot, err := tp.snapshotGenerator.generateSnapshotForTransferTx(balanceChanges) - if err != nil { - return nil, err - } - return snapshot, snapshot.Apply(tp.snapshotApplier) + return tp.snapshotGenerator.generateSnapshotForTransferTx(balanceChanges) } func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -85,10 +73,11 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest // Create new asset. assetInfo := &assetInfo{ assetConstInfo: assetConstInfo{ - tail: proto.DigestTail(assetID), - issuer: tx.SenderPK, - decimals: tx.Decimals, - issueHeight: blockHeight, + tail: proto.DigestTail(assetID), + issuer: tx.SenderPK, + decimals: tx.Decimals, + issueHeight: blockHeight, + issueSequenceInBlock: info.stateActionsCounter.NextIssueActionNumber(), }, assetChangeableInfo: assetChangeableInfo{ quantity: *big.NewInt(int64(tx.Quantity)), @@ -100,11 +89,15 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest } snapshot, err := tp.snapshotGenerator.generateSnapshotForIssueTx(assetID, txID, tx.SenderPK, *assetInfo, balanceChanges, scriptInformation) - if err != nil { return nil, err } - return snapshot, snapshot.Apply(tp.snapshotApplier) + + 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 } func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -120,7 +113,9 @@ func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transactio if err != nil { return nil, err } - + if err := tp.stor.scriptsStorage.setAssetScript(assetID, proto.Script{}, tx.SenderPK, info.blockID); err != nil { + return nil, err + } return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges, nil) } @@ -137,6 +132,10 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac if err != nil { return nil, err } + if err := tp.stor.scriptsStorage.setAssetScript(assetID, tx.Script, tx.SenderPK, info.blockID); err != nil { + return nil, err + } + var scriptInfo *scriptInformation if se := info.checkerData.scriptEstimations; se.isPresent() { // Save complexities to storage, so we won't have to calculate it every time the script is called. @@ -144,6 +143,9 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac if !ok { return nil, errors.Errorf("failed to calculate asset script complexity by estimator version %d", se.currentEstimatorVersion) } + if err := tp.stor.scriptsComplexity.saveComplexitiesForAsset(assetID, complexity, info.blockID); err != nil { + return nil, err + } scriptInfo = &scriptInformation{ script: tx.Script, complexity: complexity.Verifier, @@ -152,7 +154,7 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges, scriptInfo) } -func (tp *transactionPerformer) performReissue(tx *proto.Reissue, _ *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { // Modify asset. change := &assetReissueChange{ reissuable: tx.Reissuable, @@ -163,7 +165,11 @@ func (tp *transactionPerformer) performReissue(tx *proto.Reissue, _ *performerIn if err != nil { return nil, err } - return snapshot, snapshot.Apply(tp.snapshotApplier) + + 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, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -182,7 +188,7 @@ func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Trans return tp.performReissue(&tx.Reissue, info, balanceChanges) } -func (tp *transactionPerformer) performBurn(tx *proto.Burn, _ *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { // Modify asset. change := &assetBurnChange{ diff: int64(tx.Amount), @@ -192,7 +198,12 @@ func (tp *transactionPerformer) performBurn(tx *proto.Burn, _ *performerInfo, ba if err != nil { return nil, err } - return snapshot, snapshot.Apply(tp.snapshotApplier) + + 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 } func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -211,6 +222,14 @@ func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transact return tp.performBurn(&tx.Burn, info, balanceChanges) } +func (tp *transactionPerformer) increaseOrderVolume(order proto.Order, fee uint64, volume uint64, info *performerInfo) error { + orderID, err := order.GetID() + if err != nil { + return err + } + return tp.stor.ordersVolumes.increaseFilled(orderID, volume, fee, info.blockID) +} + func (tp *transactionPerformer) performExchange(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(proto.Exchange) if !ok { @@ -233,7 +252,16 @@ func (tp *transactionPerformer) performExchange(transaction proto.Transaction, i if err != nil { return nil, err } - return snapshot, snapshot.Apply(tp.snapshotApplier) + + err = tp.increaseOrderVolume(sellOrder, sellFee, volume, info) + if err != nil { + return nil, err + } + err = tp.increaseOrderVolume(buyOrder, buyFee, volume, info) + if err != nil { + return nil, err + } + return snapshot, nil } func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -260,9 +288,13 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest } snapshot, err := tp.snapshotGenerator.generateSnapshotForLeaseTx(*l, txID, txID, balanceChanges) if err != nil { - return nil, err + return nil, nil + } + + if err := tp.stor.leases.addLeasing(txID, l, info.blockID); err != nil { + return nil, errors.Wrap(err, "failed to add leasing") } - return snapshot, snapshot.Apply(tp.snapshotApplier) + return snapshot, nil } func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -291,7 +323,10 @@ func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID * if err != nil { return nil, err } - return snapshot, snapshot.Apply(tp.snapshotApplier) + 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 } func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -310,7 +345,7 @@ func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.T return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info, balanceChanges) } -func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, _ *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { return nil, err @@ -320,7 +355,10 @@ func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, _ *per if err != nil { return nil, err } - return snapshot, snapshot.Apply(tp.snapshotApplier) + if err := tp.stor.aliases.createAlias(tx.Alias.Alias, senderAddr, info.blockID); err != nil { + return nil, err + } + return snapshot, nil } func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -344,11 +382,7 @@ func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto. if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") } - snapshot, err := tp.snapshotGenerator.generateSnapshotForMassTransferTx(balanceChanges) - if err != nil { - return nil, err - } - return snapshot, snapshot.Apply(tp.snapshotApplier) + return tp.snapshotGenerator.generateSnapshotForMassTransferTx(balanceChanges) } func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -366,7 +400,12 @@ func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transact if err != nil { return nil, err } - return snapshot, snapshot.Apply(tp.snapshotApplier) + for _, entry := range tx.Entries { + if err := tp.stor.accountsDataStor.appendEntry(senderAddr, entry, info.blockID); err != nil { + return nil, err + } + } + return snapshot, nil } func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -379,7 +418,10 @@ func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.T if err != nil { return nil, err } - return snapshot, snapshot.Apply(tp.snapshotApplier) + 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, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -387,6 +429,11 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra if !ok { return nil, errors.New("failed to convert interface to SetScriptWithProofs transaction") } + senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) + if err != nil { + return nil, err + } + se := info.checkerData.scriptEstimations if !se.isPresent() { return nil, errors.New("script estimations must be set for SetScriptWithProofs tx") @@ -396,11 +443,17 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra complexity := info.checkerData.scriptEstimations.estimations[se.currentEstimatorVersion].Verifier snapshot, err := tp.snapshotGenerator.generateSnapshotForSetScriptTx(tx.SenderPK, tx.Script, complexity, info, balanceChanges) - if err != nil { return nil, err } - return snapshot, snapshot.Apply(tp.snapshotApplier) + 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") + } + // Save complexity to storage, so we won't have to calculate it every time the script is called. + if err := tp.stor.scriptsComplexity.saveComplexitiesForAddr(senderAddr, se.estimations, info.blockID); err != nil { + return nil, err + } + return snapshot, nil } func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -419,11 +472,18 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot } complexity := estimation.Verifier - snapshot, err := tp.snapshotGenerator.generateSnapshotForSetAssetScriptTx(tx.AssetID, tx.Script, complexity, tx.SenderPK, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForSetAssetScriptTx(tx.AssetID, tx.Script, complexity, balanceChanges) if err != nil { return nil, err } - return snapshot, snapshot.Apply(tp.snapshotApplier) + 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") + } + // Save complexity to storage, so we won't have to calculate it every time the script is called. + if err := tp.stor.scriptsComplexity.saveComplexitiesForAsset(tx.AssetID, estimation, info.blockID); err != nil { + return nil, errors.Wrapf(err, "failed to save script complexity for asset %q", tx.AssetID.String()) + } + return snapshot, nil } func addToWavesBalanceDiff(addrWavesBalanceDiff addressWavesBalanceDiff, @@ -494,7 +554,6 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. if _, ok := transaction.(*proto.InvokeScriptWithProofs); !ok { return nil, errors.New("failed to convert interface to InvokeScriptWithProofs transaction") } - // TODO remove? if err := tp.stor.commitUncertain(info.blockID); err != nil { return nil, errors.Wrap(err, "failed to commit invoke changes") } @@ -509,16 +568,16 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. snapshot, err := tp.snapshotGenerator.generateSnapshotForInvokeScriptTx(txID, info, invocationRes, balanceChanges) if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to generate a snapshot for an invoke transaction") } - return snapshot, snapshot.Apply(tp.snapshotApplier) + + return snapshot, nil } func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { if _, ok := transaction.(*proto.InvokeExpressionTransactionWithProofs); !ok { return nil, errors.New("failed to convert interface to InvokeExpressionWithProofs transaction") } - // TODO remove? if err := tp.stor.commitUncertain(info.blockID); err != nil { return nil, errors.Wrap(err, "failed to commit invoke changes") } @@ -531,11 +590,7 @@ func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction pr return nil, err } - snapshot, err := tp.snapshotGenerator.generateSnapshotForInvokeExpressionTx(txID, info, invocationRes, balanceChanges) - if err != nil { - return nil, err - } - return snapshot, snapshot.Apply(tp.snapshotApplier) + return tp.snapshotGenerator.generateSnapshotForInvokeExpressionTx(txID, info, invocationRes, balanceChanges) } func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -544,7 +599,6 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction return nil, errors.New("failed to convert interface to EthereumTransaction transaction") } if _, ok := ethTx.TxKind.(*proto.EthereumInvokeScriptTxKind); ok { - // TODO remove? if err := tp.stor.commitUncertain(info.blockID); err != nil { return nil, errors.Wrap(err, "failed to commit invoke changes") } @@ -560,9 +614,10 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction snapshot, err := tp.snapshotGenerator.generateSnapshotForEthereumInvokeScriptTx(txID, info, invocationRes, balanceChanges) if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to generate a snapshot for an invoke transaction") } - return snapshot, snapshot.Apply(tp.snapshotApplier) + + return snapshot, nil } func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { @@ -571,10 +626,18 @@ func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction pro return nil, errors.New("failed to convert interface to UpdateAssetInfoWithProofs transaction") } blockHeight := info.height + 1 + ch := &assetInfoChange{ + newName: tx.Name, + newDescription: tx.Description, + newHeight: blockHeight, + } snapshot, err := tp.snapshotGenerator.generateSnapshotForUpdateAssetInfoTx(tx.AssetID, tx.Name, tx.Description, blockHeight, balanceChanges) if err != nil { return nil, err } - return snapshot, snapshot.Apply(tp.snapshotApplier) + if err := tp.stor.assets.updateAssetInfo(tx.AssetID, ch, info.blockID); err != nil { + return nil, errors.Wrap(err, "failed to update asset info") + } + return snapshot, nil } diff --git a/pkg/state/transaction_performer_test.go b/pkg/state/transaction_performer_test.go index 96400f168..0f84dae1e 100644 --- a/pkg/state/transaction_performer_test.go +++ b/pkg/state/transaction_performer_test.go @@ -15,53 +15,28 @@ import ( ) type performerTestObjects struct { - stor *testStorageObjects - tp *transactionPerformer - stateActionsCounter *proto.StateActionsCounter + stor *testStorageObjects + tp *transactionPerformer } -func createPerformerTestObjects(t *testing.T, checkerInfo *checkerInfo) *performerTestObjects { +func createPerformerTestObjects(t *testing.T) *performerTestObjects { stor := createStorageObjects(t, true) - tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings) - - actionsCounter := new(proto.StateActionsCounter) - - snapshotApplier := newBlockSnapshotsApplier( - blockSnapshotsApplierInfo{ - ci: checkerInfo, - scheme: settings.MainNetSettings.AddressSchemeCharacter, - stateActionsCounter: actionsCounter, - }, - snapshotApplierStorages{ - balances: stor.entities.balances, - aliases: stor.entities.aliases, - assets: stor.entities.assets, - scriptsStorage: stor.entities.scriptsStorage, - scriptsComplexity: stor.entities.scriptsComplexity, - sponsoredAssets: stor.entities.sponsoredAssets, - ordersVolumes: stor.entities.ordersVolumes, - accountsDataStor: stor.entities.accountsDataStor, - leases: stor.entities.leases, - }, - ) - snapshotGenerator := snapshotGenerator{stor: stor.entities, scheme: settings.MainNetSettings.AddressSchemeCharacter} - tp.snapshotApplier = &snapshotApplier - tp.snapshotGenerator = &snapshotGenerator + snapshotGenerator := &snapshotGenerator{stor.entities, settings.MainNetSettings} + tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) require.NoError(t, err, "newTransactionPerformer() failed") - return &performerTestObjects{stor, tp, actionsCounter} + return &performerTestObjects{stor, tp} } -func defaultPerformerInfo(stateActionsCounter *proto.StateActionsCounter) *performerInfo { - return newPerformerInfo(0, stateActionsCounter, blockID0, proto.WavesAddress{}, txCheckerData{}) +func defaultPerformerInfo() *performerInfo { + return newPerformerInfo(0, new(proto.StateActionsCounter), blockID0, proto.WavesAddress{}, txCheckerData{}) } func TestPerformIssueWithSig(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createPerformerTestObjects(t, checkerInfo) - checkerInfo.height = 1 + to := createPerformerTestObjects(t) + to.stor.addBlock(t, blockID0) tx := createIssueWithSig(t, 1000) - _, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performIssueWithSig() failed") to.stor.flush(t) expectedAssetInfo := assetInfo{ @@ -88,13 +63,12 @@ func TestPerformIssueWithSig(t *testing.T) { } func TestPerformIssueWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createPerformerTestObjects(t, checkerInfo) - checkerInfo.height = 1 + to := createPerformerTestObjects(t) + to.stor.addBlock(t, blockID0) tx := createIssueWithProofs(t, 1000) - _, err := to.tp.performIssueWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err := to.tp.performIssueWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performIssueWithProofs() failed") to.stor.flush(t) expectedAssetInfo := assetInfo{ @@ -121,13 +95,11 @@ func TestPerformIssueWithProofs(t *testing.T) { } func TestPerformReissueWithSig(t *testing.T) { - - checkerInfo := defaultCheckerInfo() - to := createPerformerTestObjects(t, checkerInfo) + to := createPerformerTestObjects(t) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithSig(t, 1000) - _, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performReissueWithSig() failed") to.stor.flush(t) assetInfo.reissuable = tx.Reissuable @@ -140,12 +112,11 @@ func TestPerformReissueWithSig(t *testing.T) { } func TestPerformReissueWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createPerformerTestObjects(t, checkerInfo) + to := createPerformerTestObjects(t) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithProofs(t, 1000) - _, err := to.tp.performReissueWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err := to.tp.performReissueWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performReissueWithProofs() failed") to.stor.flush(t) assetInfo.reissuable = tx.Reissuable @@ -158,12 +129,11 @@ func TestPerformReissueWithProofs(t *testing.T) { } func TestPerformBurnWithSig(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createPerformerTestObjects(t, checkerInfo) + to := createPerformerTestObjects(t) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithSig(t) - _, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performBurnWithSig() failed") to.stor.flush(t) assetInfo.quantity.Sub(&assetInfo.quantity, big.NewInt(int64(tx.Amount))) @@ -175,12 +145,11 @@ func TestPerformBurnWithSig(t *testing.T) { } func TestPerformBurnWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createPerformerTestObjects(t, checkerInfo) + to := createPerformerTestObjects(t) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithProofs(t) - _, err := to.tp.performBurnWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err := to.tp.performBurnWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performBurnWithProofs() failed") to.stor.flush(t) assetInfo.quantity.Sub(&assetInfo.quantity, big.NewInt(int64(tx.Amount))) @@ -192,12 +161,11 @@ func TestPerformBurnWithProofs(t *testing.T) { } func TestPerformExchange(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createPerformerTestObjects(t, checkerInfo) + to := createPerformerTestObjects(t) to.stor.addBlock(t, blockID0) tx := createExchangeWithSig(t) - _, err := to.tp.performExchange(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err := to.tp.performExchange(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performExchange() failed") sellOrderID, err := tx.GetOrder2().GetID() @@ -230,12 +198,11 @@ func TestPerformExchange(t *testing.T) { } func TestPerformLeaseWithSig(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createPerformerTestObjects(t, checkerInfo) + to := createPerformerTestObjects(t) to.stor.addBlock(t, blockID0) tx := createLeaseWithSig(t) - _, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performLeaseWithSig() failed") to.stor.flush(t) leasingInfo := &leasing{ @@ -252,12 +219,11 @@ func TestPerformLeaseWithSig(t *testing.T) { } func TestPerformLeaseWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createPerformerTestObjects(t, checkerInfo) + to := createPerformerTestObjects(t) to.stor.addBlock(t, blockID0) tx := createLeaseWithProofs(t) - _, err := to.tp.performLeaseWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err := to.tp.performLeaseWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performLeaseWithProofs() failed") to.stor.flush(t) leasingInfo := &leasing{ @@ -274,12 +240,11 @@ func TestPerformLeaseWithProofs(t *testing.T) { } func TestPerformLeaseCancelWithSig(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createPerformerTestObjects(t, checkerInfo) + to := createPerformerTestObjects(t) to.stor.addBlock(t, blockID0) leaseTx := createLeaseWithSig(t) - _, err := to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err := to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performLeaseWithSig() failed") to.stor.flush(t) tx := createLeaseCancelWithSig(t, *leaseTx.ID) @@ -291,7 +256,7 @@ func TestPerformLeaseCancelWithSig(t *testing.T) { Sender: testGlobal.senderInfo.addr, CancelTransactionID: tx.ID, } - _, err = to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err = to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performLeaseCancelWithSig() failed") to.stor.flush(t) info, err := to.stor.entities.leases.leasingInfo(*leaseTx.ID) @@ -300,12 +265,11 @@ func TestPerformLeaseCancelWithSig(t *testing.T) { } func TestPerformLeaseCancelWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createPerformerTestObjects(t, checkerInfo) + to := createPerformerTestObjects(t) to.stor.addBlock(t, blockID0) leaseTx := createLeaseWithProofs(t) - _, err := to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err := to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performLeaseWithProofs() failed") to.stor.flush(t) tx := createLeaseCancelWithProofs(t, *leaseTx.ID) @@ -317,7 +281,7 @@ func TestPerformLeaseCancelWithProofs(t *testing.T) { Sender: testGlobal.senderInfo.addr, CancelTransactionID: tx.ID, } - _, err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performLeaseCancelWithProofs() failed") to.stor.flush(t) info, err := to.stor.entities.leases.leasingInfo(*leaseTx.ID) @@ -326,12 +290,11 @@ func TestPerformLeaseCancelWithProofs(t *testing.T) { } func TestPerformCreateAliasWithSig(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createPerformerTestObjects(t, checkerInfo) + to := createPerformerTestObjects(t) to.stor.addBlock(t, blockID0) tx := createCreateAliasWithSig(t) - _, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performCreateAliasWithSig() failed") to.stor.flush(t) addr, err := to.stor.entities.aliases.addrByAlias(tx.Alias.Alias) @@ -339,7 +302,7 @@ func TestPerformCreateAliasWithSig(t *testing.T) { assert.Equal(t, testGlobal.senderInfo.addr, addr, "invalid address by alias after performing CreateAliasWithSig transaction") // Test stealing aliases. - _, err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performCreateAliasWithSig() failed") to.stor.flush(t) err = to.stor.entities.aliases.disableStolenAliases(blockID0) @@ -350,12 +313,11 @@ func TestPerformCreateAliasWithSig(t *testing.T) { } func TestPerformCreateAliasWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createPerformerTestObjects(t, checkerInfo) + to := createPerformerTestObjects(t) to.stor.addBlock(t, blockID0) tx := createCreateAliasWithProofs(t) - _, err := to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err := to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performCreateAliasWithProofs() failed") to.stor.flush(t) addr, err := to.stor.entities.aliases.addrByAlias(tx.Alias.Alias) @@ -363,7 +325,7 @@ func TestPerformCreateAliasWithProofs(t *testing.T) { assert.Equal(t, testGlobal.senderInfo.addr, addr, "invalid address by alias after performing CreateAliasWithProofs transaction") // Test stealing aliases. - _, err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performCreateAliasWithProofs() failed") to.stor.flush(t) err = to.stor.entities.aliases.disableStolenAliases(blockID0) @@ -374,8 +336,7 @@ func TestPerformCreateAliasWithProofs(t *testing.T) { } func TestPerformDataWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createPerformerTestObjects(t, checkerInfo) + to := createPerformerTestObjects(t) to.stor.addBlock(t, blockID0) @@ -383,7 +344,7 @@ func TestPerformDataWithProofs(t *testing.T) { entry := &proto.IntegerDataEntry{Key: "TheKey", Value: int64(666)} tx.Entries = []proto.DataEntry{entry} - _, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performDataWithProofs() failed") to.stor.flush(t) @@ -393,13 +354,12 @@ func TestPerformDataWithProofs(t *testing.T) { } func TestPerformSponsorshipWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createPerformerTestObjects(t, checkerInfo) + to := createPerformerTestObjects(t) to.stor.addBlock(t, blockID0) tx := createSponsorshipWithProofs(t, 1000) - _, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performSponsorshipWithProofs() failed") assetID := proto.AssetIDFromDigest(tx.AssetID) @@ -437,8 +397,7 @@ func TestPerformSponsorshipWithProofs(t *testing.T) { } func TestPerformSetScriptWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createPerformerTestObjects(t, checkerInfo) + to := createPerformerTestObjects(t) to.stor.addBlock(t, blockID0) @@ -460,7 +419,7 @@ func TestPerformSetScriptWithProofs(t *testing.T) { require.NoError(t, err) tx := createSetScriptWithProofs(t, scriptBytes) - pi := *defaultPerformerInfo(to.stateActionsCounter) + pi := *defaultPerformerInfo() pi.checkerData.scriptEstimations = &scriptsEstimations{} _, err = to.tp.performSetScriptWithProofs(tx, &pi, nil, nil) assert.NoError(t, err, "performSetScriptWithProofs() failed") @@ -526,13 +485,12 @@ func TestPerformSetScriptWithProofs(t *testing.T) { } func TestPerformSetAssetScriptWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createPerformerTestObjects(t, checkerInfo) + to := createPerformerTestObjects(t) to.stor.addBlock(t, blockID0) tx := createSetAssetScriptWithProofs(t) - pi := *defaultPerformerInfo(to.stateActionsCounter) + pi := *defaultPerformerInfo() currentEstimatorVersion := 4 tree, err := serialization.Parse(tx.Script) @@ -546,7 +504,6 @@ func TestPerformSetAssetScriptWithProofs(t *testing.T) { currentEstimatorVersion: estimation, }, } - checkerInfo.blockID = blockID0 _, err = to.tp.performSetAssetScriptWithProofs(tx, &pi, nil, nil) assert.NoError(t, err, "performSetAssetScriptWithProofs() failed") @@ -623,12 +580,11 @@ func TestPerformSetAssetScriptWithProofs(t *testing.T) { } func TestPerformUpdateAssetInfoWithProofs(t *testing.T) { - checkerInfo := defaultCheckerInfo() - to := createPerformerTestObjects(t, checkerInfo) + to := createPerformerTestObjects(t) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createUpdateAssetInfoWithProofs(t) - _, err := to.tp.performUpdateAssetInfoWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) + _, err := to.tp.performUpdateAssetInfoWithProofs(tx, defaultPerformerInfo(), nil, nil) assert.NoError(t, err, "performUpdateAssetInfoWithProofs() failed") to.stor.flush(t) assetInfo.name = tx.Name From 228332fec98a3b3e5c858df26d4293a07a851366 Mon Sep 17 00:00:00 2001 From: esuwu Date: Fri, 11 Aug 2023 12:08:44 -0500 Subject: [PATCH 052/139] Added asset script atomic snapshot to the issue script actions --- pkg/state/appender.go | 8 +- pkg/state/invoke_applier.go | 370 ++++++++++++++++++-------------- pkg/state/orders_volume.go | 2 +- pkg/state/snapshot_applier.go | 9 +- pkg/state/snapshot_generator.go | 25 ++- 5 files changed, 242 insertions(+), 172 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 4cd7fb183..0f8eeb563 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -423,7 +423,9 @@ type appendTxParams struct { snapshotApplier SnapshotApplier } -func (a *txAppender) handleInvokeOrExchangeTransaction(tx proto.Transaction, fallibleInfo *fallibleValidationParams) (*invocationResult, *applicationResult, error) { +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" @@ -672,7 +674,7 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { } // TODO apply this snapshot when balances are refatored - //err = initialSnapshot.Apply(&snapshotApplier) + // err = initialSnapshot.Apply(&snapshotApplier) // Save miner diff first (for validation) if err := a.diffStor.saveTxDiff(minerAndRewardDiff); err != nil { @@ -731,7 +733,7 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { return nil } -// used only in tests now. All diffs are applied in snapshotApplier +// used only in tests now. All diffs are applied in snapshotApplier. func (a *txAppender) applyAllDiffs() error { a.recentTxIds = make(map[string]struct{}) return a.moveChangesToHistoryStorage() diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index c5469dc53..64654824c 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -2,10 +2,6 @@ package state import ( "fmt" - "math" - "math/big" - "strings" - "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/errs" @@ -16,6 +12,9 @@ import ( "github.com/wavesplatform/gowaves/pkg/settings" "github.com/wavesplatform/gowaves/pkg/types" "go.uber.org/zap" + "math" + "math/big" + "strings" ) type invokeApplier struct { @@ -725,88 +724,223 @@ func (ia *invokeApplier) fallibleValidation(tx proto.Transaction, info *addlInvo return 0, totalChanges, nil } -// applyInvokeScript checks InvokeScript transaction, creates its balance diffs and adds changes to `uncertain` storage. -// 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) (*invocationResult, *applicationResult, error) { - // In defer we should clean all the temp changes invoke does to state. - defer func() { - ia.invokeDiffStor.invokeDiffsStor.reset() - }() +func (ia *invokeApplier) handleInvokeFunctionError( + err error, + info *fallibleValidationParams, + txID crypto.Digest, + checkerData txCheckerData, + failedChanges txBalanceChanges, +) (*invocationResult, *applicationResult, error) { + // After activation of RideV6 feature transactions are failed if they are not cheap regardless the error kind. + isCheap := int(ia.sc.recentTxComplexity) <= FailFreeInvokeComplexity + if info.rideV6Activated { + if !info.acceptFailed || isCheap { + 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"), + ) + } + invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error()} + applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) + 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 + // 2) The error is ride.InternalInvocationError and correct fail/reject behaviour is activated + // 3) The spent complexity is less than limit + switch ride.GetEvaluationErrorType(err) { + case ride.UserError, ride.RuntimeError, ride.ComplexityLimitExceed: + // 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, 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"), + ) + } + invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error()} + applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) + 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, 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"), + ) + } + invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error()} + applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) + return invocationRes, applicationRes, err - var ( - paymentsLength int - scriptAddr proto.WavesAddress - txID crypto.Digest - sender proto.Address - tree *ast.Tree - scriptPK crypto.PublicKey - ) + case ride.Undefined, ride.EvaluationFailure: // Unhandled or evaluator error + return nil, nil, errors.Wrapf(err, "invocation of transaction '%s' failed", txID.String()) + default: + return nil, nil, errors.Wrapf(err, "invocation of transaction '%s' failed", txID.String()) + } +} + +type scriptParameters struct { + paymentsLength int + scriptAddr proto.WavesAddress + txID crypto.Digest + sender proto.Address + tree *ast.Tree + scriptPK crypto.PublicKey +} + +func (ia *invokeApplier) collectScriptParameters(tx proto.Transaction) (scriptParameters, error) { + scriptParams := scriptParameters{} + var err error switch transaction := tx.(type) { case *proto.InvokeScriptWithProofs: - var err error - scriptAddr, err = recipientToAddress(transaction.ScriptRecipient, ia.stor.aliases) + scriptParams.scriptAddr, err = recipientToAddress(transaction.ScriptRecipient, ia.stor.aliases) if err != nil { - return nil, nil, errors.Wrap(err, "recipientToAddress() failed") + return scriptParameters{}, errors.Wrap(err, "recipientToAddress() failed") } - paymentsLength = len(transaction.Payments) - txID = *transaction.ID - sender, err = proto.NewAddressFromPublicKey(ia.settings.AddressSchemeCharacter, transaction.SenderPK) + scriptParams.paymentsLength = len(transaction.Payments) + scriptParams.txID = *transaction.ID + scriptParams.sender, err = proto.NewAddressFromPublicKey(ia.settings.AddressSchemeCharacter, transaction.SenderPK) if err != nil { - return nil, nil, errors.Wrapf(err, "failed to apply script invocation") + return scriptParameters{}, errors.Wrapf(err, "failed to apply script invocation") } - tree, err = ia.stor.scriptsStorage.newestScriptByAddr(scriptAddr) + scriptParams.tree, err = ia.stor.scriptsStorage.newestScriptByAddr(scriptParams.scriptAddr) if err != nil { - return nil, nil, errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptAddr.String()) + return scriptParameters{}, errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptParams.scriptAddr.String()) } - si, err := ia.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptAddr.ID()) + si, err := ia.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptParams.scriptAddr.ID()) if err != nil { - return nil, nil, errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptAddr.String()) + return scriptParameters{}, errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptParams.scriptAddr.String()) } - scriptPK = si.PK + scriptParams.scriptPK = si.PK case *proto.InvokeExpressionTransactionWithProofs: addr, err := proto.NewAddressFromPublicKey(ia.settings.AddressSchemeCharacter, transaction.SenderPK) if err != nil { - return nil, nil, errors.Wrap(err, "recipientToAddress() failed") + return scriptParameters{}, errors.Wrap(err, "recipientToAddress() failed") } - sender = addr - scriptAddr = addr - tree, err = serialization.Parse(transaction.Expression) + scriptParams.sender = addr + scriptParams.scriptAddr = addr + scriptParams.tree, err = serialization.Parse(transaction.Expression) if err != nil { - return nil, nil, errors.Wrap(err, "failed to parse decoded invoke expression into tree") + return scriptParameters{}, errors.Wrap(err, "failed to parse decoded invoke expression into tree") } - txID = *transaction.ID - scriptPK = transaction.SenderPK + scriptParams.txID = *transaction.ID + scriptParams.scriptPK = transaction.SenderPK case *proto.EthereumTransaction: - var err error - scriptAddr, err = transaction.WavesAddressTo(ia.settings.AddressSchemeCharacter) + scriptParams.scriptAddr, err = transaction.WavesAddressTo(ia.settings.AddressSchemeCharacter) if err != nil { - return nil, nil, err + return scriptParameters{}, err } decodedData := transaction.TxKind.DecodedData() - paymentsLength = len(decodedData.Payments) - txID = *transaction.ID - sender, err = transaction.WavesAddressFrom(ia.settings.AddressSchemeCharacter) + scriptParams.paymentsLength = len(decodedData.Payments) + scriptParams.txID = *transaction.ID + scriptParams.sender, err = transaction.WavesAddressFrom(ia.settings.AddressSchemeCharacter) if err != nil { - return nil, nil, errors.Wrapf(err, "failed to apply script invocation") + return scriptParameters{}, errors.Wrapf(err, "failed to apply script invocation") } - tree, err = ia.stor.scriptsStorage.newestScriptByAddr(scriptAddr) + scriptParams.tree, err = ia.stor.scriptsStorage.newestScriptByAddr(scriptParams.scriptAddr) if err != nil { - return nil, nil, errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptAddr.String()) + return scriptParameters{}, errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptParams.scriptAddr.String()) } - si, err := ia.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptAddr.ID()) + si, err := ia.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptParams.scriptAddr.ID()) if err != nil { - return nil, nil, errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptAddr.String()) + return scriptParameters{}, errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptParams.scriptAddr.String()) } - scriptPK = si.PK + scriptParams.scriptPK = si.PK default: - return nil, nil, errors.Errorf("failed to apply an invoke script: unexpected type of transaction (%T)", tx) + return scriptParameters{}, errors.Errorf("failed to apply an invoke script: unexpected type of transaction (%T)", tx) + } + + return scriptParams, nil +} + +func (ia *invokeApplier) handleFallibleValidationError(err error, + txID crypto.Digest, + code proto.TxFailureReason, + info *fallibleValidationParams, + scriptRuns uint64, + r ride.Result) (*invocationResult, error) { + + var invocationRes *invocationResult + if err != nil { + zap.S().Debugf("fallibleValidation error in tx %s. Error: %s", txID.String(), err.Error()) + // If fallibleValidation fails, we should save transaction to blockchain when acceptFailed is true. + if !info.acceptFailed || + (ia.sc.recentTxComplexity <= FailFreeInvokeComplexity && + info.checkerInfo.height >= ia.settings.InternalInvokeCorrectFailRejectBehaviourAfterHeight) { + return nil, err + } + invocationRes = &invocationResult{ + failed: true, + code: code, + text: err.Error(), + scriptRuns: scriptRuns, + actions: r.ScriptActions(), + } + } else { + invocationRes = &invocationResult{ + failed: false, + scriptRuns: scriptRuns, + actions: r.ScriptActions(), + } + } + return invocationRes, nil +} + +func (ia *invokeApplier) countScriptRuns(info *fallibleValidationParams, + paymentSmartAssets []crypto.Digest, + scriptActions []proto.ScriptAction) (uint64, error) { + var scriptRuns uint64 = 0 + + // After activation of RideV5 (16) feature we don't take extra fee for execution of smart asset scripts. + if !info.rideV5Activated { + actionScriptRuns, err := ia.countActionScriptRuns(scriptActions) + if err != nil { + return 0, errors.Wrap(err, "failed to countActionScriptRuns") + } + scriptRuns += uint64(len(paymentSmartAssets)) + actionScriptRuns + } + if info.senderScripted { + // Since activation of RideV5 (16) feature we don't take fee for verifier execution if it's complexity is less than `FreeVerifierComplexity` limit + if info.rideV5Activated { + treeEstimation, err := ia.stor.scriptsComplexity.newestScriptComplexityByAddr(info.senderAddress, info.checkerInfo.estimatorVersion()) + if err != nil { + return 0, errors.Wrap(err, "invoke failed to get verifier complexity") + } + if treeEstimation.Verifier > FreeVerifierComplexity { + scriptRuns++ + } + } else { + scriptRuns++ + } + } + return scriptRuns, nil +} + +// applyInvokeScript checks InvokeScript transaction, creates its balance diffs and adds changes to `uncertain` storage. +// 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) (*invocationResult, *applicationResult, error) { + // In defer we should clean all the temp changes invoke does to state. + defer func() { + ia.invokeDiffStor.invokeDiffsStor.reset() + }() + + scriptParams, err := ia.collectScriptParameters(tx) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to collect script parameters") } // If BlockV5 feature is not activated, we never accept failed transactions. @@ -827,13 +961,13 @@ func (ia *invokeApplier) applyInvokeScript( // 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, nil, errors.Errorf("multiple payments is not allowed for RIDE library version %d", tree.LibVersion) + if scriptParams.paymentsLength >= 2 && scriptParams.tree.LibVersion < ast.LibV4 { + return nil, nil, errors.Errorf("multiple payments is not allowed for RIDE library version %d", scriptParams.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 { + disableSelfTransfers := info.acceptFailed && scriptParams.tree.LibVersion >= 4 + if disableSelfTransfers && scriptParams.paymentsLength > 0 { + if scriptParams.sender == scriptParams.scriptAddr { return nil, nil, errors.New("paying to DApp itself is forbidden since RIDE V4") } @@ -846,121 +980,33 @@ func (ia *invokeApplier) applyInvokeScript( } // Call script function. - r, err := ia.sc.invokeFunction(tree, tx, info, scriptAddr) + r, err := ia.sc.invokeFunction(scriptParams.tree, tx, info, scriptParams.scriptAddr) if err != nil { - // Script returned error, it's OK, but we have to decide is it failed or rejected transaction. - // After activation of RideV6 feature transactions are failed if they are not cheap regardless the error kind. - isCheap := int(ia.sc.recentTxComplexity) <= FailFreeInvokeComplexity - if info.rideV6Activated { - if !info.acceptFailed || isCheap { - 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"), - ) - } - invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error()} - applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) - 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 - // 2) The error is ride.InternalInvocationError and correct fail/reject behaviour is activated - // 3) The spent complexity is less than limit - switch ride.GetEvaluationErrorType(err) { - case ride.UserError, ride.RuntimeError, ride.ComplexityLimitExceed: - // 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, 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"), - ) - } - invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error()} - applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) - 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, 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"), - ) - } - invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error()} - applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) - return invocationRes, applicationRes, err - - case ride.Undefined, ride.EvaluationFailure: // Unhandled or evaluator error - return nil, nil, errors.Wrapf(err, "invocation of transaction '%s' failed", txID.String()) - default: - return nil, nil, errors.Wrapf(err, "invocation of transaction '%s' failed", txID.String()) - } + // Script returned error, it's OK, but we have to decide if it's a failed or rejected transaction. + return ia.handleInvokeFunctionError(err, info, scriptParams.txID, checkerData, failedChanges) } - var scriptRuns uint64 = 0 - // After activation of RideV5 (16) feature we don't take extra fee for execution of smart asset scripts. - if !info.rideV5Activated { - actionScriptRuns, err := ia.countActionScriptRuns(r.ScriptActions()) - if err != nil { - return nil, nil, errors.Wrap(err, "failed to countActionScriptRuns") - } - scriptRuns += uint64(len(paymentSmartAssets)) + actionScriptRuns - } - if info.senderScripted { - // Since activation of RideV5 (16) feature we don't take fee for verifier execution if it's complexity is less than `FreeVerifierComplexity` limit - if info.rideV5Activated { - treeEstimation, err := ia.stor.scriptsComplexity.newestScriptComplexityByAddr(info.senderAddress, info.checkerInfo.estimatorVersion()) - if err != nil { - return nil, nil, errors.Wrap(err, "invoke failed to get verifier complexity") - } - if treeEstimation.Verifier > FreeVerifierComplexity { - scriptRuns++ - } - } else { - scriptRuns++ - } + + scriptRuns, err := ia.countScriptRuns(info, paymentSmartAssets, r.ScriptActions()) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to count scripts runs") } - var invocationRes *invocationResult code, balanceChanges, err := ia.fallibleValidation(tx, &addlInvokeInfo{ fallibleValidationParams: info, - scriptAddr: scriptAddr, - scriptPK: scriptPK, + scriptAddr: scriptParams.scriptAddr, + scriptPK: scriptParams.scriptPK, scriptRuns: scriptRuns, failedChanges: failedChanges, actions: r.ScriptActions(), paymentSmartAssets: paymentSmartAssets, disableSelfTransfers: disableSelfTransfers, - libVersion: tree.LibVersion, + libVersion: scriptParams.tree.LibVersion, }) + invocationRes, err := ia.handleFallibleValidationError(err, scriptParams.txID, code, info, scriptRuns, r) if err != nil { - zap.S().Debugf("fallibleValidation error in tx %s. Error: %s", txID.String(), err.Error()) - // If fallibleValidation fails, we should save transaction to blockchain when acceptFailed is true. - if !info.acceptFailed || - (ia.sc.recentTxComplexity <= FailFreeInvokeComplexity && - info.checkerInfo.height >= ia.settings.InternalInvokeCorrectFailRejectBehaviourAfterHeight) { - return nil, nil, err - } - invocationRes = &invocationResult{ - failed: true, - code: code, - text: err.Error(), - scriptRuns: scriptRuns, - actions: r.ScriptActions(), - } - } else { - invocationRes = &invocationResult{ - failed: false, - scriptRuns: scriptRuns, - actions: r.ScriptActions(), - } + return nil, nil, err } - applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes, balanceChanges) + + applicationRes, err := ia.handleInvocationResult(scriptParams.txID, checkerData, info, invocationRes, balanceChanges) return invocationRes, applicationRes, err } diff --git a/pkg/state/orders_volume.go b/pkg/state/orders_volume.go index 64cc9a421..ad657698c 100644 --- a/pkg/state/orders_volume.go +++ b/pkg/state/orders_volume.go @@ -76,7 +76,7 @@ func (ov *ordersVolumes) increaseFilled(orderID []byte, amountChange, feeChange return ov.addNewRecord(orderID, prevVolume, blockID) } -func (ov *ordersVolumes) newestFilled(orderID []byte) (amount, fee uint64, err error) { +func (ov *ordersVolumes) newestFilled(orderID []byte) (uint64, uint64, error) { volume, err := ov.newestVolumeById(orderID) if err != nil { if isNotFoundInHistoryOrDBErr(err) { // No fee volume filled yet. diff --git a/pkg/state/snapshot_applier.go b/pkg/state/snapshot_applier.go index babf78c82..70a9b6465 100644 --- a/pkg/state/snapshot_applier.go +++ b/pkg/state/snapshot_applier.go @@ -101,6 +101,7 @@ func (a *blockSnapshotsApplier) ApplyWavesBalance(snapshot WavesBalanceSnapshot) func (a *blockSnapshotsApplier) ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) error { addrID := snapshot.Address.ID() + var err error profile, err := a.stor.balances.wavesBalance(addrID) if err != nil { return errors.Wrapf(err, "failed to get waves balance profile for address %q", snapshot.Address.String()) @@ -109,7 +110,7 @@ func (a *blockSnapshotsApplier) ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) newProfile.leaseIn = int64(snapshot.LeaseIn) newProfile.leaseOut = int64(snapshot.LeaseOut) value := newWavesValue(profile, newProfile) - if err := a.stor.balances.setWavesBalance(addrID, value, a.info.BlockID()); err != nil { + if err = a.stor.balances.setWavesBalance(addrID, value, a.info.BlockID()); err != nil { return errors.Wrapf(err, "failed to get set balance profile for address %q", snapshot.Address.String()) } return nil @@ -169,10 +170,10 @@ func (a *blockSnapshotsApplier) ApplyAssetScript(snapshot AssetScriptSnapshot) e if err := a.stor.scriptsComplexity.saveComplexitiesForAsset(snapshot.AssetID, estimation, a.info.BlockID()); err != nil { return errors.Wrapf(err, "failed to store asset script estimation for asset %q", snapshot.AssetID.String()) } - //constInfo, err := a.stor.assets.newestConstInfo(proto.AssetIDFromDigest(snapshot.AssetID)) // only issuer can set new asset script - //if err != nil { + // constInfo, err := a.stor.assets.newestConstInfo(proto.AssetIDFromDigest(snapshot.AssetID)) // only issuer can set new asset script + // if err != nil { // return errors.Wrapf(err, "failed to get const asset info for asset %q", snapshot.AssetID.String()) - //} + // } return a.stor.scriptsStorage.setAssetScript(snapshot.AssetID, snapshot.Script, snapshot.SenderPK, a.info.BlockID()) } diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index ea6d0ecc8..509de9e1e 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -82,12 +82,12 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) if scriptInformation != nil { - sponsorshipSnapshot := &AssetScriptSnapshot{ + assetScriptSnapshot := &AssetScriptSnapshot{ AssetID: assetID, Script: scriptInformation.script, Complexity: uint64(scriptInformation.complexity), } - snapshot = append(snapshot, sponsorshipSnapshot) + snapshot = append(snapshot, assetScriptSnapshot) } wavesBalancesSnapshot, assetBalancesSnapshot, err := sg.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) @@ -428,6 +428,27 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( IsReissuable: assetInfo.reissuable, TotalQuantity: assetInfo.quantity, } + + var scriptInfo *scriptInformation + if se := info.checkerData.scriptEstimations; se.isPresent() { + // Save complexities to storage, so we won't have to calculate it every time the script is called. + complexity, ok := se.estimations[se.currentEstimatorVersion] + if !ok { + return nil, errors.Errorf("failed to calculate asset script complexity by estimator version %d", se.currentEstimatorVersion) + } + scriptInfo = &scriptInformation{ + script: a.Script, + complexity: complexity.Verifier, + } + } + if scriptInfo != nil { + assetScriptSnapshot := &AssetScriptSnapshot{ + AssetID: a.ID, + Script: scriptInfo.script, + Complexity: uint64(scriptInfo.complexity), + } + snapshot = append(snapshot, assetScriptSnapshot) + } snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) addSenderToAssetBalanceDiff(addrAssetBalanceDiff, issuerAddress, proto.AssetIDFromDigest(a.ID), a.Quantity) From 5d2f1d8171a99026ea476d5d5196bcbc2c2a7daf Mon Sep 17 00:00:00 2001 From: esuwu Date: Sat, 12 Aug 2023 19:53:25 -0500 Subject: [PATCH 053/139] Fixed some linter issues --- pkg/state/appender.go | 28 +- pkg/state/invoke_applier.go | 57 +- pkg/state/leases.go | 8 +- pkg/state/orders_volume.go | 6 +- pkg/state/scripts_complexity.go | 3 +- pkg/state/snapshot_applier.go | 23 +- pkg/state/snapshot_generator.go | 746 ++++++++++++++++-------- pkg/state/snapshot_generator_test.go | 330 +++++++---- pkg/state/snapshot_types.go | 6 +- pkg/state/transaction_checker.go | 6 +- pkg/state/transaction_checker_test.go | 4 +- pkg/state/transaction_differ.go | 8 +- pkg/state/transaction_differ_test.go | 4 +- pkg/state/transaction_handler.go | 86 ++- pkg/state/transaction_performer.go | 214 ++++--- pkg/state/transaction_performer_test.go | 4 +- 16 files changed, 949 insertions(+), 584 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 0f8eeb563..a07b29375 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -14,6 +14,8 @@ import ( "github.com/wavesplatform/gowaves/pkg/types" ) +const snapshotLimit = 1000 + type blockInfoProvider interface { NewestBlockInfoByHeight(height proto.Height) (*proto.BlockInfo, error) } @@ -337,7 +339,7 @@ func (a *txAppender) commitTxApplication( // Update complexity. a.sc.addRecentTxComplexity() // Save balance diff. - if err := a.diffStor.saveTxDiff(applicationRes.changes.diff); err != nil { + if err = a.diffStor.saveTxDiff(applicationRes.changes.diff); err != nil { return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to save balance diff: %v", err)) } currentMinerAddress := proto.MustAddressFromPublicKey(a.settings.AddressSchemeCharacter, params.currentMinerPK) @@ -356,11 +358,10 @@ func (a *txAppender) commitTxApplication( 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, !applicationRes.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 { @@ -369,7 +370,7 @@ func (a *txAppender) commitTxApplication( return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to count miner fee: %v", err)) } // Save transaction to storage. - if err := a.rw.writeTransaction(tx, !applicationRes.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)) } } @@ -572,7 +573,7 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro return err } // a temporary dummy for linters - if len(snapshot) > 1000 { + if len(snapshot) > snapshotLimit { zap.S().Debug(snapshot) } // Store additional data for API: transaction by address. @@ -586,15 +587,15 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro // 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) + addrWavesBalanceDiff, _, err := balanceDiffFromTxDiff(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()) + var fullBalance balanceProfile + fullBalance, err = a.stor.balances.wavesBalance(wavesAddress.ID()) if err != nil { return nil, errors.Wrap(err, "failed to receive sender's waves balance") } @@ -677,7 +678,7 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { // err = initialSnapshot.Apply(&snapshotApplier) // Save miner diff first (for validation) - if err := a.diffStor.saveTxDiff(minerAndRewardDiff); err != nil { + if err = a.diffStor.saveTxDiff(minerAndRewardDiff); err != nil { return err } blockInfo, err := a.currentBlockInfo() @@ -762,8 +763,9 @@ func newApplicationResult(status bool, totalScriptsRuns uint64, changes txBalanc return &applicationResult{status, totalScriptsRuns, changes, checkerData} // all fields must be initialized } -func (a *txAppender) handleInvoke(tx proto.Transaction, info *fallibleValidationParams) (*invocationResult, *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: @@ -894,7 +896,9 @@ func (a *txAppender) handleExchange(tx proto.Transaction, info *fallibleValidati return newApplicationResult(true, scriptsRuns, successfulChanges, checkerData), nil } -func (a *txAppender) handleFallible(tx proto.Transaction, info *fallibleValidationParams) (*invocationResult, *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, nil, err diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index 64654824c..8ef447c96 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -2,6 +2,10 @@ package state import ( "fmt" + "math" + "math/big" + "strings" + "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/errs" @@ -12,9 +16,6 @@ import ( "github.com/wavesplatform/gowaves/pkg/settings" "github.com/wavesplatform/gowaves/pkg/types" "go.uber.org/zap" - "math" - "math/big" - "strings" ) type invokeApplier struct { @@ -742,7 +743,8 @@ func (ia *invokeApplier) handleInvokeFunctionError( ) } invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error()} - applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) + var applicationRes *applicationResult + applicationRes, err = ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) return invocationRes, applicationRes, err } // Before RideV6 activation in the following cases the transaction is rejected: @@ -761,7 +763,8 @@ func (ia *invokeApplier) handleInvokeFunctionError( ) } invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error()} - applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) + var applicationRes *applicationResult + applicationRes, err = ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) return invocationRes, applicationRes, err case ride.InternalInvocationError: @@ -776,7 +779,8 @@ func (ia *invokeApplier) handleInvokeFunctionError( ) } invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error()} - applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) + var applicationRes *applicationResult + applicationRes, err = ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) return invocationRes, applicationRes, err case ride.Undefined, ride.EvaluationFailure: // Unhandled or evaluator error @@ -812,11 +816,14 @@ func (ia *invokeApplier) collectScriptParameters(tx proto.Transaction) (scriptPa } scriptParams.tree, err = ia.stor.scriptsStorage.newestScriptByAddr(scriptParams.scriptAddr) if err != nil { - return scriptParameters{}, errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptParams.scriptAddr.String()) + return scriptParameters{}, + errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptParams.scriptAddr.String()) } - si, err := ia.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptParams.scriptAddr.ID()) + var si scriptBasicInfoRecord + si, err = ia.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptParams.scriptAddr.ID()) if err != nil { - return scriptParameters{}, errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptParams.scriptAddr.String()) + return scriptParameters{}, + errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptParams.scriptAddr.String()) } scriptParams.scriptPK = si.PK @@ -848,11 +855,14 @@ func (ia *invokeApplier) collectScriptParameters(tx proto.Transaction) (scriptPa } scriptParams.tree, err = ia.stor.scriptsStorage.newestScriptByAddr(scriptParams.scriptAddr) if err != nil { - return scriptParameters{}, errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptParams.scriptAddr.String()) + return scriptParameters{}, + errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptParams.scriptAddr.String()) } - si, err := ia.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptParams.scriptAddr.ID()) + var si scriptBasicInfoRecord + si, err = ia.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptParams.scriptAddr.ID()) if err != nil { - return scriptParameters{}, errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptParams.scriptAddr.String()) + return scriptParameters{}, + errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptParams.scriptAddr.String()) } scriptParams.scriptPK = si.PK @@ -869,7 +879,6 @@ func (ia *invokeApplier) handleFallibleValidationError(err error, info *fallibleValidationParams, scriptRuns uint64, r ride.Result) (*invocationResult, error) { - var invocationRes *invocationResult if err != nil { zap.S().Debugf("fallibleValidation error in tx %s. Error: %s", txID.String(), err.Error()) @@ -899,7 +908,7 @@ func (ia *invokeApplier) handleFallibleValidationError(err error, func (ia *invokeApplier) countScriptRuns(info *fallibleValidationParams, paymentSmartAssets []crypto.Digest, scriptActions []proto.ScriptAction) (uint64, error) { - var scriptRuns uint64 = 0 + var scriptRuns uint64 // After activation of RideV5 (16) feature we don't take extra fee for execution of smart asset scripts. if !info.rideV5Activated { @@ -910,9 +919,12 @@ func (ia *invokeApplier) countScriptRuns(info *fallibleValidationParams, scriptRuns += uint64(len(paymentSmartAssets)) + actionScriptRuns } if info.senderScripted { - // Since activation of RideV5 (16) feature we don't take fee for verifier execution if it's complexity is less than `FreeVerifierComplexity` limit + // Since activation of RideV5 (16) feature + // we don't take fee for verifier execution if it's complexity is less than `FreeVerifierComplexity` limit + if info.rideV5Activated { - treeEstimation, err := ia.stor.scriptsComplexity.newestScriptComplexityByAddr(info.senderAddress, info.checkerInfo.estimatorVersion()) + treeEstimation, err := ia.stor.scriptsComplexity.newestScriptComplexityByAddr( + info.senderAddress, info.checkerInfo.estimatorVersion()) if err != nil { return 0, errors.Wrap(err, "invoke failed to get verifier complexity") } @@ -929,7 +941,8 @@ func (ia *invokeApplier) countScriptRuns(info *fallibleValidationParams, // applyInvokeScript checks InvokeScript transaction, creates its balance diffs and adds changes to `uncertain` storage. // 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(). +// If the transaction fails, +// performInvokeScriptWithProofs() is not called and changes are discarded later using dropUncertain(). func (ia *invokeApplier) applyInvokeScript( tx proto.Transaction, info *fallibleValidationParams) (*invocationResult, *applicationResult, error) { @@ -962,14 +975,14 @@ func (ia *invokeApplier) applyInvokeScript( // Check that the script's library supports multiple payments. // We don't have to check feature activation because we've done it before. if scriptParams.paymentsLength >= 2 && scriptParams.tree.LibVersion < ast.LibV4 { - return nil, nil, errors.Errorf("multiple payments is not allowed for RIDE library version %d", scriptParams.tree.LibVersion) + return nil, nil, + errors.Errorf("multiple payments is not allowed for RIDE library version %d", scriptParams.tree.LibVersion) } // Refuse payments to DApp itself since activation of BlockV5 (acceptFailed) and for DApps with StdLib V4. - disableSelfTransfers := info.acceptFailed && scriptParams.tree.LibVersion >= 4 + disableSelfTransfers := info.acceptFailed && scriptParams.tree.LibVersion >= ast.LibV4 if disableSelfTransfers && scriptParams.paymentsLength > 0 { if scriptParams.sender == scriptParams.scriptAddr { return nil, nil, errors.New("paying to DApp itself is forbidden since RIDE V4") - } } // Basic differ for InvokeScript creates only fee and payment diff. @@ -1028,7 +1041,9 @@ func toScriptResult(ir *invocationResult) (*proto.ScriptResult, error) { return sr, err } -func (ia *invokeApplier) handleInvocationResult(txID crypto.Digest, checkerData txCheckerData, info *fallibleValidationParams, res *invocationResult, balanceChanges txBalanceChanges) (*applicationResult, error) { +func (ia *invokeApplier) handleInvocationResult(txID crypto.Digest, checkerData txCheckerData, + info *fallibleValidationParams, res *invocationResult, + balanceChanges txBalanceChanges) (*applicationResult, error) { if ia.buildApiData && !info.validatingUtx { // Save invoke result for extended API. res, err := toScriptResult(res) diff --git a/pkg/state/leases.go b/pkg/state/leases.go index e4a4636f0..8db3fb930 100644 --- a/pkg/state/leases.go +++ b/pkg/state/leases.go @@ -99,7 +99,7 @@ func (l *leases) cancelLeases(bySenders map[proto.WavesAddress]struct{}, blockID key := keyvalue.SafeKey(leaseIter) leaseBytes := keyvalue.SafeValue(leaseIter) record := new(leasing) - if err := record.unmarshalBinary(leaseBytes); err != nil { + if err = record.unmarshalBinary(leaseBytes); err != nil { return errors.Wrap(err, "failed to unmarshal lease") } toCancel := true @@ -176,7 +176,7 @@ func (l *leases) validLeaseIns() (map[proto.WavesAddress]int64, error) { for leaseIter.Next() { leaseBytes := keyvalue.SafeValue(leaseIter) record := new(leasing) - if err := record.unmarshalBinary(leaseBytes); err != nil { + if err = record.unmarshalBinary(leaseBytes); err != nil { return nil, errors.Wrap(err, "failed to unmarshal lease") } if record.isActive() { @@ -199,7 +199,7 @@ func (l *leases) newestLeasingInfo(id crypto.Digest) (*leasing, error) { return nil, err } record := new(leasing) - if err := record.unmarshalBinary(recordBytes); err != nil { + if err = record.unmarshalBinary(recordBytes); err != nil { return nil, errors.Wrap(err, "failed to unmarshal record") } if record.OriginTransactionID == nil { @@ -216,7 +216,7 @@ func (l *leases) leasingInfo(id crypto.Digest) (*leasing, error) { return nil, err } record := new(leasing) - if err := record.unmarshalBinary(recordBytes); err != nil { + if err = record.unmarshalBinary(recordBytes); err != nil { return nil, errors.Wrap(err, "failed to unmarshal record") } if record.OriginTransactionID == nil { diff --git a/pkg/state/orders_volume.go b/pkg/state/orders_volume.go index ad657698c..39712eea8 100644 --- a/pkg/state/orders_volume.go +++ b/pkg/state/orders_volume.go @@ -41,7 +41,7 @@ func newOrdersVolumes(hs *historyStorage) *ordersVolumes { return &ordersVolumes{hs: hs} } -func (ov *ordersVolumes) newestVolumeById(orderID []byte) (*orderVolumeRecord, error) { +func (ov *ordersVolumes) newestVolumeByID(orderID []byte) (*orderVolumeRecord, error) { key := ordersVolumeKey{orderID} recordBytes, err := ov.hs.newestTopEntryData(key.bytes()) if err != nil { @@ -64,7 +64,7 @@ func (ov *ordersVolumes) addNewRecord(orderID []byte, record *orderVolumeRecord, } func (ov *ordersVolumes) increaseFilled(orderID []byte, amountChange, feeChange uint64, blockID proto.BlockID) error { - prevVolume, err := ov.newestVolumeById(orderID) + prevVolume, err := ov.newestVolumeByID(orderID) if err != nil { if isNotFoundInHistoryOrDBErr(err) { // New record. return ov.addNewRecord(orderID, &orderVolumeRecord{amountFilled: amountChange, feeFilled: feeChange}, blockID) @@ -77,7 +77,7 @@ func (ov *ordersVolumes) increaseFilled(orderID []byte, amountChange, feeChange } func (ov *ordersVolumes) newestFilled(orderID []byte) (uint64, uint64, error) { - volume, err := ov.newestVolumeById(orderID) + volume, err := ov.newestVolumeByID(orderID) if err != nil { if isNotFoundInHistoryOrDBErr(err) { // No fee volume filled yet. return 0, 0, nil diff --git a/pkg/state/scripts_complexity.go b/pkg/state/scripts_complexity.go index 6ddad61bb..e51f0c292 100644 --- a/pkg/state/scripts_complexity.go +++ b/pkg/state/scripts_complexity.go @@ -95,7 +95,8 @@ func (sc *scriptsComplexity) scriptComplexityByAddress(addr proto.Address, ev in return record, nil } -func (sc *scriptsComplexity) saveComplexitiesForAddr(addr proto.Address, estimations treeEstimations, blockID proto.BlockID) error { +func (sc *scriptsComplexity) saveComplexitiesForAddr(addr proto.Address, + estimations treeEstimations, blockID proto.BlockID) error { min := math.MaxUint8 addrID := addr.ID() for v, e := range estimations { diff --git a/pkg/state/snapshot_applier.go b/pkg/state/snapshot_applier.go index 70a9b6465..e8a7a4e8b 100644 --- a/pkg/state/snapshot_applier.go +++ b/pkg/state/snapshot_applier.go @@ -4,6 +4,7 @@ import ( "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/ride" + "github.com/wavesplatform/gowaves/pkg/ride/ast" "github.com/wavesplatform/gowaves/pkg/ride/serialization" ) @@ -56,7 +57,8 @@ type blockSnapshotsApplierInfo struct { var _ = newBlockSnapshotsApplierInfo -func newBlockSnapshotsApplierInfo(ci *checkerInfo, scheme proto.Scheme, cnt *proto.StateActionsCounter) blockSnapshotsApplierInfo { +func newBlockSnapshotsApplierInfo(ci *checkerInfo, scheme proto.Scheme, + cnt *proto.StateActionsCounter) blockSnapshotsApplierInfo { return blockSnapshotsApplierInfo{ ci: ci, scheme: scheme, @@ -93,7 +95,7 @@ func (a *blockSnapshotsApplier) ApplyWavesBalance(snapshot WavesBalanceSnapshot) newProfile := profile newProfile.balance = snapshot.Balance value := newWavesValue(profile, newProfile) - if err := a.stor.balances.setWavesBalance(addrID, value, a.info.BlockID()); err != nil { + if err = a.stor.balances.setWavesBalance(addrID, value, a.info.BlockID()); err != nil { return errors.Wrapf(err, "failed to get set balance profile for address %q", snapshot.Address.String()) } return nil @@ -167,10 +169,13 @@ func (a *blockSnapshotsApplier) ApplyAssetScript(snapshot AssetScriptSnapshot) e Verifier: int(snapshot.Complexity), Functions: nil, } - if err := a.stor.scriptsComplexity.saveComplexitiesForAsset(snapshot.AssetID, estimation, a.info.BlockID()); err != nil { - return errors.Wrapf(err, "failed to store asset script estimation for asset %q", snapshot.AssetID.String()) + if err := a.stor.scriptsComplexity.saveComplexitiesForAsset( + snapshot.AssetID, estimation, a.info.BlockID()); err != nil { + return errors.Wrapf(err, "failed to store asset script estimation for asset %q", + snapshot.AssetID.String()) } - // constInfo, err := a.stor.assets.newestConstInfo(proto.AssetIDFromDigest(snapshot.AssetID)) // only issuer can set new asset script + // only issuer can set new asset script + // constInfo, err := a.stor.assets.newestConstInfo(proto.AssetIDFromDigest(snapshot.AssetID)) // if err != nil { // return errors.Wrapf(err, "failed to get const asset info for asset %q", snapshot.AssetID.String()) // } @@ -189,7 +194,8 @@ func (a *blockSnapshotsApplier) ApplyAccountScript(snapshot AccountScriptSnapsho } var estimations treeEstimations if !snapshot.Script.IsEmpty() { - tree, err := serialization.Parse(snapshot.Script) + var tree *ast.Tree + tree, err = serialization.Parse(snapshot.Script) if err != nil { return errors.Wrapf(err, "failed to parse script from account script snapshot for addr %q", addr.String()) } @@ -198,14 +204,15 @@ func (a *blockSnapshotsApplier) ApplyAccountScript(snapshot AccountScriptSnapsho return errors.Wrapf(err, "failed to make account script estimations for addr %q", addr.String()) } } - if err := a.stor.scriptsComplexity.saveComplexitiesForAddr(addr, estimations, a.info.BlockID()); err != nil { + if err = a.stor.scriptsComplexity.saveComplexitiesForAddr(addr, estimations, a.info.BlockID()); err != nil { return errors.Wrapf(err, "failed to store account script estimation for addr %q", addr.String()) } return a.stor.scriptsStorage.setAccountScript(addr, snapshot.Script, snapshot.SenderPublicKey, a.info.BlockID()) } func (a *blockSnapshotsApplier) ApplyFilledVolumeAndFee(snapshot FilledVolumeFeeSnapshot) error { - return a.stor.ordersVolumes.increaseFilled(snapshot.OrderID.Bytes(), snapshot.FilledVolume, snapshot.FilledFee, a.info.BlockID()) + return a.stor.ordersVolumes.increaseFilled(snapshot.OrderID.Bytes(), + snapshot.FilledVolume, snapshot.FilledFee, a.info.BlockID()) } func (a *blockSnapshotsApplier) ApplyDataEntries(snapshot DataEntriesSnapshot) error { diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index 509de9e1e..7f8c912b4 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -1,10 +1,11 @@ package state import ( + "math/big" + "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" - "math/big" ) type snapshotGenerator struct { @@ -12,14 +13,74 @@ type snapshotGenerator struct { scheme proto.Scheme } +type addressWavesBalanceDiff map[proto.WavesAddress]balanceDiff + +func (wavesDiff addressWavesBalanceDiff) append( + senderAddress proto.WavesAddress, + recipientAddress proto.WavesAddress, + amount int64) { + if _, ok := wavesDiff[senderAddress]; ok { + prevBalance := wavesDiff[senderAddress] + prevBalance.balance -= amount + wavesDiff[senderAddress] = prevBalance + } else { + wavesDiff[senderAddress] = balanceDiff{balance: amount} + } + + if _, ok := wavesDiff[recipientAddress]; ok { + prevRecipientBalance := wavesDiff[recipientAddress] + prevRecipientBalance.balance += amount + wavesDiff[recipientAddress] = prevRecipientBalance + } else { + wavesDiff[recipientAddress] = balanceDiff{balance: amount} + } +} + type assetBalanceDiffKey struct { address proto.WavesAddress asset proto.AssetID } - -type addressWavesBalanceDiff map[proto.WavesAddress]balanceDiff type addressAssetBalanceDiff map[assetBalanceDiffKey]int64 +func (assetDiff addressAssetBalanceDiff) append( + 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 := assetDiff[keySender]; ok { + prevSenderBalance := assetDiff[keySender] + prevSenderBalance -= amount + assetDiff[keySender] = prevSenderBalance + } else { + assetDiff[keySender] = amount + } + + if _, ok := assetDiff[keyRecipient]; ok { + prevRecipientBalance := assetDiff[keyRecipient] + prevRecipientBalance += amount + assetDiff[keyRecipient] = prevRecipientBalance + } else { + assetDiff[keyRecipient] = amount + } +} + +func (assetDiff addressAssetBalanceDiff) appendOnlySender( + senderAddress proto.WavesAddress, + asset proto.AssetID, + amount int64) { + keySender := assetBalanceDiffKey{address: senderAddress, asset: asset} + if _, ok := assetDiff[keySender]; ok { + prevSenderBalance := assetDiff[keySender] + prevSenderBalance += amount + assetDiff[keySender] = prevSenderBalance + } else { + assetDiff[keySender] = amount + } +} + func (sg *snapshotGenerator) generateSnapshotForGenesisTx(balanceChanges txDiff) (TransactionSnapshot, error) { return sg.generateBalancesSnapshot(balanceChanges) } @@ -37,13 +98,16 @@ type scriptInformation struct { complexity int } -func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, txID crypto.Digest, senderPK crypto.PublicKey, assetInfo assetInfo, balanceChanges txDiff, scriptInformation *scriptInformation) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, txID crypto.Digest, + senderPK crypto.PublicKey, assetInfo assetInfo, balanceChanges txDiff, + scriptInformation *scriptInformation) (TransactionSnapshot, error) { var snapshot TransactionSnapshot - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.scheme) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := balanceDiffFromTxDiff(balanceChanges, sg.scheme) 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 + // 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) { @@ -90,7 +154,8 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t snapshot = append(snapshot, assetScriptSnapshot) } - wavesBalancesSnapshot, assetBalancesSnapshot, err := sg.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) + wavesBalancesSnapshot, assetBalancesSnapshot, err := + sg.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -108,7 +173,8 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, change assetReissueChange, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, + change assetReissueChange, balanceChanges txDiff) (TransactionSnapshot, error) { quantityDiff := big.NewInt(change.diff) assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) if err != nil { @@ -129,7 +195,8 @@ func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, change assetBurnChange, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, change assetBurnChange, + balanceChanges txDiff) (TransactionSnapshot, error) { quantityDiff := big.NewInt(change.diff) assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) if err != nil { @@ -150,7 +217,9 @@ func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, ch return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForExchangeTx(sellOrder proto.Order, sellFee uint64, buyOrder proto.Order, buyFee uint64, volume uint64, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForExchangeTx(sellOrder proto.Order, sellFee uint64, + buyOrder proto.Order, buyFee uint64, volume uint64, + balanceChanges txDiff) (TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") @@ -177,14 +246,16 @@ func (sg *snapshotGenerator) generateSnapshotForExchangeTx(sellOrder proto.Order return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForLeaseTx(lease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForLeaseTx(lease leasing, leaseID crypto.Digest, + originalTxID crypto.Digest, balanceChanges txDiff) (TransactionSnapshot, error) { var err error snapshot, err := sg.generateBalancesSnapshot(balanceChanges) 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 := sg.generateLeaseAtomicSnapshots(leaseID, lease, originalTxID, lease.Sender, lease.Recipient, amount) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := + sg.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") } @@ -193,14 +264,17 @@ func (sg *snapshotGenerator) generateSnapshotForLeaseTx(lease leasing, leaseID c return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Digest, oldLease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, cancelHeight uint64, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Digest, oldLease leasing, + leaseID crypto.Digest, originalTxID crypto.Digest, + cancelHeight uint64, balanceChanges txDiff) (TransactionSnapshot, error) { var err error snapshot, err := sg.generateBalancesSnapshot(balanceChanges) 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 := sg.generateLeaseAtomicSnapshots(leaseID, oldLease, originalTxID, oldLease.Sender, oldLease.Recipient, negativeAmount) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := + sg.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") } @@ -214,7 +288,8 @@ func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Diges return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForCreateAliasTx(senderAddress proto.WavesAddress, alias proto.Alias, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForCreateAliasTx(senderAddress proto.WavesAddress, alias proto.Alias, + balanceChanges txDiff) (TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -231,7 +306,8 @@ func (sg *snapshotGenerator) generateSnapshotForMassTransferTx(balanceChanges tx return sg.generateBalancesSnapshot(balanceChanges) } -func (sg *snapshotGenerator) generateSnapshotForDataTx(senderAddress proto.WavesAddress, entries []proto.DataEntry, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForDataTx(senderAddress proto.WavesAddress, entries []proto.DataEntry, + balanceChanges txDiff) (TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -244,7 +320,8 @@ func (sg *snapshotGenerator) generateSnapshotForDataTx(senderAddress proto.Waves return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Digest, minAssetFee uint64, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Digest, + minAssetFee uint64, balanceChanges txDiff) (TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -257,7 +334,8 @@ func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Dig return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.PublicKey, script proto.Script, complexity int, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.PublicKey, script proto.Script, + complexity int, _ *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -272,7 +350,8 @@ func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.Publ return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, complexity int, senderPK crypto.PublicKey, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, + complexity int, senderPK crypto.PublicKey, balanceChanges txDiff) (TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -288,20 +367,23 @@ func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto. return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForInvokeScriptTx(txID crypto.Digest, info *performerInfo, + invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges) } -func (sg *snapshotGenerator) generateSnapshotForInvokeExpressionTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForInvokeExpressionTx(txID crypto.Digest, info *performerInfo, + invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges) } -func (sg *snapshotGenerator) generateSnapshotForEthereumInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForEthereumInvokeScriptTx(txID crypto.Digest, info *performerInfo, + invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges) } -func (sg *snapshotGenerator) generateSnapshotForUpdateAssetInfoTx(assetID crypto.Digest, assetName string, assetDescription string, changeHeight proto.Height, balanceChanges txDiff) (TransactionSnapshot, error) { - +func (sg *snapshotGenerator) generateSnapshotForUpdateAssetInfoTx(assetID crypto.Digest, assetName string, + assetDescription string, changeHeight proto.Height, balanceChanges txDiff) (TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -316,235 +398,375 @@ func (sg *snapshotGenerator) generateSnapshotForUpdateAssetInfoTx(assetID crypto return snapshot, nil } -// TODO optimize this +type SenderDataEntries map[proto.WavesAddress]proto.DataEntries + +func (senderDataEntries SenderDataEntries) collectEntryFromAction( + action proto.DataEntryScriptAction, scheme proto.Scheme) error { + if senderDataEntries == nil { + return errors.New("senderDataEntries map is not initialized") + } + senderAddr, err := proto.NewAddressFromPublicKey(scheme, *action.Sender) + if err != nil { + return err + } + if _, ok := senderDataEntries[senderAddr]; ok { + entries := senderDataEntries[senderAddr] + entries = append(entries, action.Entry) + senderDataEntries[senderAddr] = entries + } else { + senderDataEntries[senderAddr] = proto.DataEntries{action.Entry} + } + return nil +} + +func (sg *snapshotGenerator) updateBalanceDiffFromPaymentAction( + action proto.AttachedPaymentScriptAction, + wavesBalanceDiff addressWavesBalanceDiff, + assetBalanceDiff addressAssetBalanceDiff, +) error { + senderAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *action.Sender) + if err != nil { + return errors.Wrap(err, "failed to get an address from a public key") + } + recipientAddress, err := recipientToAddress(action.Recipient, sg.stor.aliases) + if err != nil { + return errors.Wrap(err, "failed to apply attached payment") + } + // No balance validation done below + if action.Asset.Present { // Update asset balance + assetBalanceDiff.append(senderAddress, recipientAddress, proto.AssetIDFromDigest(action.Asset.ID), action.Amount) + } else { // Update Waves balance + wavesBalanceDiff.append(senderAddress, recipientAddress, action.Amount) + } + return nil +} + +func (sg *snapshotGenerator) updateBalanceDiffFromTransferAction( + action proto.TransferScriptAction, + wavesBalanceDiff addressWavesBalanceDiff, + assetBalanceDiff addressAssetBalanceDiff, +) error { + senderAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *action.Sender) + if err != nil { + return errors.Wrap(err, "failed to get an address from a public key") + } + recipientAddress, err := recipientToAddress(action.Recipient, sg.stor.aliases) + if err != nil { + return errors.Wrap(err, "failed to apply attached payment") + } + // No balance validation done below + if action.Asset.Present { // Update asset balance + assetBalanceDiff.append(senderAddress, recipientAddress, proto.AssetIDFromDigest(action.Asset.ID), action.Amount) + } else { // Update Waves balance + wavesBalanceDiff.append(senderAddress, recipientAddress, action.Amount) + } + return nil +} + +func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( + action proto.IssueScriptAction, + blockHeight uint64, + info *performerInfo, + txID crypto.Digest) ([]AtomicSnapshot, error) { + var atomicSnapshots []AtomicSnapshot + assetInf := assetInfo{ + assetConstInfo: assetConstInfo{ + tail: proto.DigestTail(action.ID), + issuer: *action.Sender, + decimals: uint8(action.Decimals), + issueHeight: blockHeight, + issueSequenceInBlock: info.stateActionsCounter.NextIssueActionNumber(), + }, + assetChangeableInfo: assetChangeableInfo{ + quantity: *big.NewInt(action.Quantity), + name: action.Name, + description: action.Description, + lastNameDescChangeHeight: blockHeight, + reissuable: action.Reissuable, + }, + } + + issueStaticInfoSnapshot := &StaticAssetInfoSnapshot{ + AssetID: action.ID, + IssuerPublicKey: *action.Sender, + SourceTransactionID: txID, + Decimals: assetInf.decimals, + IsNFT: assetInf.isNFT(), + } + + assetDescription := &AssetDescriptionSnapshot{ + AssetID: action.ID, + AssetName: assetInf.name, + AssetDescription: assetInf.description, + ChangeHeight: assetInf.lastNameDescChangeHeight, + } + + assetReissuability := &AssetVolumeSnapshot{ + AssetID: action.ID, + IsReissuable: assetInf.reissuable, + TotalQuantity: assetInf.quantity, + } + + var scriptInfo *scriptInformation + if se := info.checkerData.scriptEstimations; se.isPresent() { + // Save complexities to storage, so we won't have to calculate it every time the script is called. + complexity, ok := se.estimations[se.currentEstimatorVersion] + if !ok { + return nil, + errors.Errorf("failed to calculate asset script complexity by estimator version %d", + se.currentEstimatorVersion) + } + scriptInfo = &scriptInformation{ + script: action.Script, + complexity: complexity.Verifier, + } + } + if scriptInfo != nil { + assetScriptSnapshot := &AssetScriptSnapshot{ + AssetID: action.ID, + Script: scriptInfo.script, + Complexity: uint64(scriptInfo.complexity), + } + atomicSnapshots = append(atomicSnapshots, assetScriptSnapshot) + } + atomicSnapshots = append(atomicSnapshots, issueStaticInfoSnapshot, assetDescription, assetReissuability) + return atomicSnapshots, nil +} + +func (sg *snapshotGenerator) atomicActionsFromReissueAction( + action proto.ReissueScriptAction) ([]AtomicSnapshot, error) { + var atomicSnapshots []AtomicSnapshot + assetInf, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(action.AssetID)) + if err != nil { + return nil, err + } + quantityDiff := big.NewInt(action.Quantity) + resQuantity := assetInf.quantity.Add(&assetInf.quantity, quantityDiff) + assetReissuability := &AssetVolumeSnapshot{ + AssetID: action.AssetID, + TotalQuantity: *resQuantity, + IsReissuable: action.Reissuable, + } + + atomicSnapshots = append(atomicSnapshots, assetReissuability) + return atomicSnapshots, nil +} + +func (sg *snapshotGenerator) atomicActionsFromBurnAction(action proto.BurnScriptAction) ([]AtomicSnapshot, error) { + var atomicSnapshots []AtomicSnapshot + var assetInf *assetInfo + assetInf, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(action.AssetID)) + if err != nil { + return nil, err + } + quantityDiff := big.NewInt(action.Quantity) + resQuantity := assetInf.quantity.Sub(&assetInf.quantity, quantityDiff) + assetReissuability := &AssetVolumeSnapshot{ + AssetID: action.AssetID, + TotalQuantity: *resQuantity, + IsReissuable: assetInf.reissuable, + } + + atomicSnapshots = append(atomicSnapshots, assetReissuability) + return atomicSnapshots, nil +} + +func (sg *snapshotGenerator) atomicActionsFromLeaseAction( + action proto.LeaseScriptAction, + info *performerInfo, + txID crypto.Digest) ([]AtomicSnapshot, error) { + var atomicSnapshots []AtomicSnapshot + senderAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *action.Sender) + if err != nil { + return nil, err + } + var recipientAddr proto.WavesAddress + if addr := action.Recipient.Address(); addr == nil { + recipientAddr, err = sg.stor.aliases.newestAddrByAlias(action.Recipient.Alias().Alias) + if err != nil { + return nil, errors.Errorf("invalid alias: %v", err) + } + } else { + recipientAddr = *addr + } + l := &leasing{ + Sender: senderAddress, + Recipient: recipientAddr, + Amount: uint64(action.Amount), + Height: info.height, + Status: LeaseActive, + } + var amount = int64(l.Amount) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := + sg.generateLeaseAtomicSnapshots(action.ID, *l, txID, senderAddress, recipientAddr, amount) + if err != nil { + return nil, errors.Wrap(err, "failed to generate snapshots for a lease action") + } + atomicSnapshots = append(atomicSnapshots, + leaseStatusSnapshot, + senderLeaseBalanceSnapshot, + recipientLeaseBalanceSnapshot) + return atomicSnapshots, nil +} + +func (sg *snapshotGenerator) atomicSnapshotsFromLeaseCancelAction( + action proto.LeaseCancelScriptAction, + txID crypto.Digest) ([]AtomicSnapshot, error) { + var atomicSnapshots []AtomicSnapshot + // TODO what if the leasing is not in the stor yet? lease and leaseCancel in the same contract? + leasingInfo, err := sg.stor.leases.leasingInfo(action.LeaseID) + if err != nil { + return nil, errors.Wrap(err, "failed to receiver leasing info") + } + + var amount = -int64(leasingInfo.Amount) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := + sg.generateLeaseAtomicSnapshots(action.LeaseID, *leasingInfo, txID, leasingInfo.Sender, leasingInfo.Recipient, amount) + if err != nil { + return nil, errors.Wrap(err, "failed to generate snapshots for a lease cancel action") + } + atomicSnapshots = append(atomicSnapshots, + leaseStatusSnapshot, + senderLeaseBalanceSnapshot, + recipientLeaseBalanceSnapshot) + return atomicSnapshots, nil +} + +func (sg *snapshotGenerator) collectBalanceAndSnapshotFromAction( + action proto.ScriptAction, + dataEntries SenderDataEntries, + wavesBalanceDiff addressWavesBalanceDiff, + assetBalanceDiff addressAssetBalanceDiff, + blockHeight uint64, + info *performerInfo, + txID crypto.Digest, +) ([]AtomicSnapshot, error) { + var atomicSnapshots []AtomicSnapshot + switch a := action.(type) { + case *proto.DataEntryScriptAction: + // snapshots store data entries in a different format, so we convert the actions to this format + err := dataEntries.collectEntryFromAction(*a, sg.scheme) + if err != nil { + return nil, err + } + case *proto.AttachedPaymentScriptAction: + err := sg.updateBalanceDiffFromPaymentAction(*a, wavesBalanceDiff, assetBalanceDiff) + if err != nil { + return nil, err + } + case *proto.TransferScriptAction: + err := sg.updateBalanceDiffFromTransferAction(*a, wavesBalanceDiff, assetBalanceDiff) + if err != nil { + return nil, err + } + case *proto.SponsorshipScriptAction: + sponsorshipSnapshot := &SponsorshipSnapshot{ + AssetID: a.AssetID, + MinSponsoredFee: uint64(a.MinFee), + } + atomicSnapshots = append(atomicSnapshots, sponsorshipSnapshot) + case *proto.IssueScriptAction: + issueSnapshots, err := sg.atomicSnapshotsFromIssueAction(*a, blockHeight, info, txID) + if err != nil { + return nil, err + } + atomicSnapshots = append(atomicSnapshots, issueSnapshots...) + issuerAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) + if err != nil { + return nil, errors.Wrap(err, "failed to get an address from a public key") + } + assetBalanceDiff.appendOnlySender(issuerAddress, proto.AssetIDFromDigest(a.ID), a.Quantity) + case *proto.ReissueScriptAction: + reissueSnapshots, err := sg.atomicActionsFromReissueAction(*a) + if err != nil { + return nil, err + } + atomicSnapshots = append(atomicSnapshots, reissueSnapshots...) + issueAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) + if err != nil { + return nil, errors.Wrap(err, "failed to get an address from a public key") + } + assetBalanceDiff.appendOnlySender(issueAddress, proto.AssetIDFromDigest(a.AssetID), a.Quantity) + + case *proto.BurnScriptAction: + burnSnapshots, err := sg.atomicActionsFromBurnAction(*a) + if err != nil { + return nil, err + } + atomicSnapshots = append(atomicSnapshots, burnSnapshots...) + issueAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) + if err != nil { + return nil, errors.Wrap(err, "failed to get an address from a public key") + } + assetBalanceDiff.appendOnlySender(issueAddress, proto.AssetIDFromDigest(a.AssetID), -a.Quantity) + case *proto.LeaseScriptAction: + leaseSnapshots, err := sg.atomicActionsFromLeaseAction(*a, info, txID) + if err != nil { + return nil, err + } + atomicSnapshots = append(atomicSnapshots, leaseSnapshots...) + case *proto.LeaseCancelScriptAction: + leaseSnapshots, err := sg.atomicSnapshotsFromLeaseCancelAction(*a, txID) + if err != nil { + return nil, err + } + atomicSnapshots = append(atomicSnapshots, leaseSnapshots...) + default: + return nil, errors.Errorf("unknown script action type %T", a) + } + return atomicSnapshots, nil +} + +func (sg *snapshotGenerator) atomicSnapshotsFromScriptActions( + actions []proto.ScriptAction, + wavesBalanceDiff addressWavesBalanceDiff, + assetBalanceDiff addressAssetBalanceDiff, + blockHeight uint64, + info *performerInfo, + txID crypto.Digest) ([]AtomicSnapshot, error) { + var dataEntries = make(SenderDataEntries) + var atomicSnapshots []AtomicSnapshot + for _, action := range actions { + snapshotsFromAction, err := sg.collectBalanceAndSnapshotFromAction(action, dataEntries, + wavesBalanceDiff, assetBalanceDiff, blockHeight, info, txID) + if err != nil { + return nil, err + } + atomicSnapshots = append(atomicSnapshots, snapshotsFromAction...) + } + + for address, entries := range dataEntries { + dataEntrySnapshot := &DataEntriesSnapshot{Address: address, DataEntries: entries} + atomicSnapshots = append(atomicSnapshots, dataEntrySnapshot) + } + return atomicSnapshots, nil +} + func (sg *snapshotGenerator) generateInvokeSnapshot( txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { - blockHeight := info.height + 1 - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.scheme) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := balanceDiffFromTxDiff(balanceChanges, sg.scheme) 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(sg.scheme, *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(sg.scheme, *a.Sender) - if err != nil { - return nil, errors.Wrap(err, "failed to get an address from a public key") - } - recipientAddress, err := recipientToAddress(a.Recipient, sg.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(sg.scheme, *a.Sender) - if err != nil { - return nil, errors.Wrap(err, "failed to get an address from a public key") - } - recipientAddress, err := recipientToAddress(a.Recipient, sg.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(sg.scheme, *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, - } - - var scriptInfo *scriptInformation - if se := info.checkerData.scriptEstimations; se.isPresent() { - // Save complexities to storage, so we won't have to calculate it every time the script is called. - complexity, ok := se.estimations[se.currentEstimatorVersion] - if !ok { - return nil, errors.Errorf("failed to calculate asset script complexity by estimator version %d", se.currentEstimatorVersion) - } - scriptInfo = &scriptInformation{ - script: a.Script, - complexity: complexity.Verifier, - } - } - if scriptInfo != nil { - assetScriptSnapshot := &AssetScriptSnapshot{ - AssetID: a.ID, - Script: scriptInfo.script, - Complexity: uint64(scriptInfo.complexity), - } - snapshot = append(snapshot, assetScriptSnapshot) - } - snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) - - addSenderToAssetBalanceDiff(addrAssetBalanceDiff, issuerAddress, proto.AssetIDFromDigest(a.ID), a.Quantity) - - case *proto.ReissueScriptAction: - - assetInfo, err := sg.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(sg.scheme, *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 := sg.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(sg.scheme, *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(sg.scheme, *a.Sender) - if err != nil { - return nil, err - } - var recipientAddr proto.WavesAddress - if addr := a.Recipient.Address(); addr == nil { - recipientAddr, err = sg.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 := sg.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 := sg.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 := sg.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) + var atomicSnapshots []AtomicSnapshot + atomicSnapshots, err = sg.atomicSnapshotsFromScriptActions( + invocationRes.actions, addrWavesBalanceDiff, + addrAssetBalanceDiff, blockHeight, info, txID) + if err != nil { + return nil, errors.Wrap(err, "failed to generate atomic snapshots from script actions") } - + snapshot = append(snapshot, atomicSnapshots...) } - wavesBalancesSnapshot, assetBalancesSnapshot, err := sg.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) + wavesBalancesSnapshot, assetBalancesSnapshot, err := + sg.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -559,8 +781,11 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( return snapshot, nil } -func (sg *snapshotGenerator) generateLeaseAtomicSnapshots(leaseID crypto.Digest, l leasing, originalTxID crypto.Digest, - senderAddress proto.WavesAddress, receiverAddress proto.WavesAddress, amount int64) (*LeaseStateSnapshot, *LeaseBalanceSnapshot, *LeaseBalanceSnapshot, error) { +func (sg *snapshotGenerator) 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{ @@ -596,17 +821,18 @@ func (sg *snapshotGenerator) generateLeaseAtomicSnapshots(leaseID crypto.Digest, return leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, nil } -func (sg *snapshotGenerator) generateOrderAtomicSnapshot(orderID []byte, volume uint64, fee uint64) (*FilledVolumeFeeSnapshot, error) { +func (sg *snapshotGenerator) generateOrderAtomicSnapshot(orderID []byte, + volume uint64, fee uint64) (*FilledVolumeFeeSnapshot, error) { newestFilledAmount, newestFilledFee, err := sg.stor.ordersVolumes.newestFilled(orderID) if err != nil { return nil, err } - orderIdDigset, err := crypto.NewDigestFromBytes(orderID) + 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, + OrderID: orderIDDigset, FilledFee: newestFilledFee + fee, FilledVolume: newestFilledAmount + volume, } @@ -615,11 +841,12 @@ func (sg *snapshotGenerator) generateOrderAtomicSnapshot(orderID []byte, volume func (sg *snapshotGenerator) generateBalancesSnapshot(balanceChanges txDiff) (TransactionSnapshot, error) { var transactionSnapshot TransactionSnapshot - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.scheme) + addrWavesBalanceDiff, addrAssetBalanceDiff, err := balanceDiffFromTxDiff(balanceChanges, sg.scheme) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") } - wavesBalancesSnapshot, assetBalancesSnapshot, err := sg.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) + wavesBalancesSnapshot, assetBalancesSnapshot, err := + sg.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -632,8 +859,9 @@ func (sg *snapshotGenerator) generateBalancesSnapshot(balanceChanges txDiff) (Tr return transactionSnapshot, nil } -func (sg *snapshotGenerator) generateBalancesAtomicSnapshots(addrWavesBalanceDiff addressWavesBalanceDiff, addrAssetBalanceDiff addressAssetBalanceDiff) ([]WavesBalanceSnapshot, []AssetBalanceSnapshot, error) { - wavesBalanceSnapshot, err := sg.constructWavesBalanceSnapshotFromDiff(addrWavesBalanceDiff) +func (sg *snapshotGenerator) generateBalancesAtomicSnapshots(addrWavesBalanceDiff addressWavesBalanceDiff, + addrAssetBalanceDiff addressAssetBalanceDiff) ([]WavesBalanceSnapshot, []AssetBalanceSnapshot, error) { + wavesBalanceSnapshot, err := sg.wavesBalanceSnapshotFromBalanceDiff(addrWavesBalanceDiff) if err != nil { return nil, nil, errors.Wrap(err, "failed to construct waves balance snapshot") } @@ -641,29 +869,30 @@ func (sg *snapshotGenerator) generateBalancesAtomicSnapshots(addrWavesBalanceDif return wavesBalanceSnapshot, nil, nil } - assetBalanceSnapshot, err := sg.constructAssetBalanceSnapshotFromDiff(addrAssetBalanceDiff) + assetBalanceSnapshot, err := sg.assetBalanceSnapshotFromBalanceDiff(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) { +func balanceDiffFromTxDiff(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)) + var address proto.WavesAddress if err != nil { + // if the waves balance unmarshal failed, try to marshal into asset balance, and if it fails, then return the error assetBalanceKey := &assetBalanceKey{} - err := assetBalanceKey.unmarshal([]byte(balanceKeyString)) + 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) + address, err = assetBalanceKey.address.ToWavesAddress(scheme) if err != nil { return nil, nil, errors.Wrap(err, "failed to convert address id to waves address") } @@ -671,12 +900,12 @@ func addressBalanceDiffFromTxDiff(diff txDiff, scheme proto.Scheme) (addressWave addrAssetBalanceDiff[assetBalKey] = diffAmount.balance continue } - address, err := wavesBalanceKey.address.ToWavesAddress(scheme) + 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 the waves balance diff is 0, it means it did not change. + // The reason for the 0 diff to exist is because of how LeaseIn and LeaseOut are handled in transaction differ. if diffAmount.balance == 0 { continue } @@ -686,12 +915,12 @@ func addressBalanceDiffFromTxDiff(diff txDiff, scheme proto.Scheme) (addressWave } // from txDiff and fees. no validation needed at this point. -func (sg *snapshotGenerator) constructWavesBalanceSnapshotFromDiff(diff addressWavesBalanceDiff) ([]WavesBalanceSnapshot, error) { +func (sg *snapshotGenerator) wavesBalanceSnapshotFromBalanceDiff( + diff addressWavesBalanceDiff) ([]WavesBalanceSnapshot, error) { var wavesBalances []WavesBalanceSnapshot // add miner address to the diff for wavesAddress, diffAmount := range diff { - fullBalance, err := sg.stor.balances.newestWavesBalance(wavesAddress.ID()) if err != nil { return nil, errors.Wrap(err, "failed to receive sender's waves balance") @@ -705,7 +934,8 @@ func (sg *snapshotGenerator) constructWavesBalanceSnapshotFromDiff(diff addressW return wavesBalances, nil } -func (sg *snapshotGenerator) constructAssetBalanceSnapshotFromDiff(diff addressAssetBalanceDiff) ([]AssetBalanceSnapshot, error) { +func (sg *snapshotGenerator) assetBalanceSnapshotFromBalanceDiff( + diff addressAssetBalanceDiff) ([]AssetBalanceSnapshot, error) { var assetBalances []AssetBalanceSnapshot // add miner address to the diff diff --git a/pkg/state/snapshot_generator_test.go b/pkg/state/snapshot_generator_test.go index 104e9de65..ad8c0a086 100644 --- a/pkg/state/snapshot_generator_test.go +++ b/pkg/state/snapshot_generator_test.go @@ -3,6 +3,10 @@ package state import ( "encoding/base64" "encoding/json" + "math/big" + "sort" + "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/wavesplatform/gowaves/pkg/crypto" @@ -10,12 +14,11 @@ import ( "github.com/wavesplatform/gowaves/pkg/ride" "github.com/wavesplatform/gowaves/pkg/ride/serialization" "github.com/wavesplatform/gowaves/pkg/settings" - "math/big" - "sort" - "testing" ) -func defaultAssetInfoTransfer(tail [12]byte, reissuable bool, amount int64, issuer crypto.PublicKey, name string) *assetInfo { +func defaultAssetInfoTransfer(tail [12]byte, reissuable bool, + amount int64, issuer crypto.PublicKey, + name string) *assetInfo { return &assetInfo{ assetConstInfo: assetConstInfo{ tail: tail, @@ -60,17 +63,21 @@ func TestDefaultTransferWavesAndAssetSnapshot(t *testing.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) + 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) + 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{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performTransferWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performTransferWithSig(tx, + defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform transfer tx") expectedSnapshot := TransactionSnapshot{ &WavesBalanceSnapshot{ @@ -87,18 +94,19 @@ func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { }, } + var snapshotI []byte + var snapshotJ []byte sort.Slice(expectedSnapshot, func(i, j int) bool { - snapshotI, err := json.Marshal(expectedSnapshot[i]) + snapshotI, err = json.Marshal(expectedSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(expectedSnapshot[j]) + 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]) + snapshotI, err = json.Marshal(transactionSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(transactionSnapshot[j]) + snapshotJ, err = json.Marshal(transactionSnapshot[j]) assert.NoError(t, err, "failed to marshal snapshots") return string(snapshotI) < string(snapshotJ) }) @@ -114,16 +122,20 @@ func TestDefaultIssueTransactionSnapshot(t *testing.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) + 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.NewUnsignedIssueWithSig(testGlobal.issuerInfo.pk, "asset0", "description", defaultQuantity, defaultDecimals, true, defaultTimestamp, uint64(1*FeeUnit)) + 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()) assert.NoError(t, err, "createDiffIssueWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performIssueWithSig(tx, + defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform issue tx") expectedSnapshot := TransactionSnapshot{ @@ -158,18 +170,20 @@ func TestDefaultIssueTransactionSnapshot(t *testing.T) { Balance: 1000, }, } + + var snapshotI []byte + var snapshotJ []byte sort.Slice(expectedSnapshot, func(i, j int) bool { - snapshotI, err := json.Marshal(expectedSnapshot[i]) + snapshotI, err = json.Marshal(expectedSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(expectedSnapshot[j]) + 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]) + snapshotI, err = json.Marshal(transactionSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(transactionSnapshot[j]) + snapshotJ, err = json.Marshal(transactionSnapshot[j]) assert.NoError(t, err, "failed to marshal snapshots") return string(snapshotI) < string(snapshotJ) }) @@ -184,21 +198,28 @@ 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, testGlobal.issuerInfo.pk, "asset0"), 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) + 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) + 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(1*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 reissue tx") ch, err := to.td.createDiffReissueWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffReissueWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performReissueWithSig(tx, + defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform reissue tx") expectedSnapshot := TransactionSnapshot{ @@ -222,18 +243,19 @@ func TestDefaultReissueSnapshot(t *testing.T) { }, } + var snapshotI []byte + var snapshotJ []byte sort.Slice(expectedSnapshot, func(i, j int) bool { - snapshotI, err := json.Marshal(expectedSnapshot[i]) + snapshotI, err = json.Marshal(expectedSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(expectedSnapshot[j]) + 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]) + snapshotI, err = json.Marshal(transactionSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(transactionSnapshot[j]) + snapshotJ, err = json.Marshal(transactionSnapshot[j]) assert.NoError(t, err, "failed to marshal snapshots") return string(snapshotI) < string(snapshotJ) }) @@ -248,21 +270,27 @@ 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, testGlobal.issuerInfo.pk, "asset0"), 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) + 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) + 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(1*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 burn tx") ch, err := to.td.createDiffBurnWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performBurnWithSig(tx, + defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -286,18 +314,19 @@ func TestDefaultBurnSnapshot(t *testing.T) { }, } + var snapshotI []byte + var snapshotJ []byte sort.Slice(expectedSnapshot, func(i, j int) bool { - snapshotI, err := json.Marshal(expectedSnapshot[i]) + snapshotI, err = json.Marshal(expectedSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(expectedSnapshot[j]) + 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]) + snapshotI, err = json.Marshal(transactionSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(transactionSnapshot[j]) + snapshotJ, err = json.Marshal(transactionSnapshot[j]) assert.NoError(t, err, "failed to marshal snapshots") return string(snapshotI) < string(snapshotJ) }) @@ -313,31 +342,44 @@ func TestDefaultExchangeTransaction(t *testing.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) + 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) + 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) + 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) + 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) + 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) + 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) + 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) + 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) + 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) @@ -347,7 +389,8 @@ func TestDefaultExchangeTransaction(t *testing.T) { ch, err := to.td.createDiffExchange(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performExchange(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performExchange(tx, defaultPerformerInfo(to.stateActionsCounter), + nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -399,18 +442,19 @@ func TestDefaultExchangeTransaction(t *testing.T) { }, } + var snapshotI []byte + var snapshotJ []byte sort.Slice(expectedSnapshot, func(i, j int) bool { - snapshotI, err := json.Marshal(expectedSnapshot[i]) + snapshotI, err = json.Marshal(expectedSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(expectedSnapshot[j]) + 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]) + snapshotI, err = json.Marshal(transactionSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(transactionSnapshot[j]) + snapshotJ, err = json.Marshal(transactionSnapshot[j]) assert.NoError(t, err, "failed to marshal snapshots") return string(snapshotI) < string(snapshotJ) }) @@ -426,16 +470,19 @@ func TestDefaultLeaseSnapshot(t *testing.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) + 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) + 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{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), + nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -470,18 +517,19 @@ func TestDefaultLeaseSnapshot(t *testing.T) { }, } + var snapshotI []byte + var snapshotJ []byte sort.Slice(expectedSnapshot, func(i, j int) bool { - snapshotI, err := json.Marshal(expectedSnapshot[i]) + snapshotI, err = json.Marshal(expectedSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(expectedSnapshot[j]) + 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]) + snapshotI, err = json.Marshal(transactionSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(transactionSnapshot[j]) + snapshotJ, err = json.Marshal(transactionSnapshot[j]) assert.NoError(t, err, "failed to marshal snapshots") return string(snapshotI) < string(snapshotJ) }) @@ -509,9 +557,13 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { 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) + 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) + 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) @@ -520,7 +572,8 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { ch, err := to.td.createDiffLeaseCancelWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), + nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -556,18 +609,19 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { LeaseOut: 0, }, } + var snapshotI []byte + var snapshotJ []byte sort.Slice(expectedSnapshot, func(i, j int) bool { - snapshotI, err := json.Marshal(expectedSnapshot[i]) + snapshotI, err = json.Marshal(expectedSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(expectedSnapshot[j]) + 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]) + snapshotI, err = json.Marshal(transactionSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(transactionSnapshot[j]) + snapshotJ, err = json.Marshal(transactionSnapshot[j]) assert.NoError(t, err, "failed to marshal snapshots") return string(snapshotI) < string(snapshotJ) }) @@ -582,7 +636,8 @@ func TestDefaultCreateAliasSnapshot(t *testing.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) + 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") @@ -592,7 +647,8 @@ func TestDefaultCreateAliasSnapshot(t *testing.T) { ch, err := to.td.createDiffCreateAliasWithSig(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), + nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -610,18 +666,19 @@ func TestDefaultCreateAliasSnapshot(t *testing.T) { }, } + var snapshotI []byte + var snapshotJ []byte sort.Slice(expectedSnapshot, func(i, j int) bool { - snapshotI, err := json.Marshal(expectedSnapshot[i]) + snapshotI, err = json.Marshal(expectedSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(expectedSnapshot[j]) + 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]) + snapshotI, err = json.Marshal(transactionSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(transactionSnapshot[j]) + snapshotJ, err = json.Marshal(transactionSnapshot[j]) assert.NoError(t, err, "failed to marshal snapshots") return string(snapshotI) < string(snapshotJ) }) @@ -636,7 +693,10 @@ func TestDefaultDataSnapshot(t *testing.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) + 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) @@ -652,7 +712,8 @@ func TestDefaultDataSnapshot(t *testing.T) { ch, err := to.td.createDiffDataWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), + nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -665,23 +726,25 @@ func TestDefaultDataSnapshot(t *testing.T) { 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}}, + Address: testGlobal.senderInfo.addr, + DataEntries: []proto.DataEntry{&proto.StringDataEntry{Key: "key_str", Value: "value_str"}, + &proto.IntegerDataEntry{Key: "key_int", Value: 2}}, }, } + var snapshotI []byte + var snapshotJ []byte sort.Slice(expectedSnapshot, func(i, j int) bool { - snapshotI, err := json.Marshal(expectedSnapshot[i]) + snapshotI, err = json.Marshal(expectedSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(expectedSnapshot[j]) + 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]) + snapshotI, err = json.Marshal(transactionSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(transactionSnapshot[j]) + snapshotJ, err = json.Marshal(transactionSnapshot[j]) assert.NoError(t, err, "failed to marshal snapshots") return string(snapshotI) < string(snapshotJ) }) @@ -696,17 +759,20 @@ func TestDefaultSponsorshipSnapshot(t *testing.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) + 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) + 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{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performSponsorshipWithProofs(tx, + defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -724,18 +790,20 @@ func TestDefaultSponsorshipSnapshot(t *testing.T) { }, } + var snapshotI []byte + var snapshotJ []byte sort.Slice(expectedSnapshot, func(i, j int) bool { - snapshotI, err := json.Marshal(expectedSnapshot[i]) + snapshotI, err = json.Marshal(expectedSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(expectedSnapshot[j]) + 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]) + snapshotI, err = json.Marshal(transactionSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(transactionSnapshot[j]) + snapshotJ, err = json.Marshal(transactionSnapshot[j]) assert.NoError(t, err, "failed to marshal snapshots") return string(snapshotI) < string(snapshotJ) }) @@ -750,10 +818,12 @@ func TestDefaultSetScriptSnapshot(t *testing.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) + 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) + 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") @@ -766,7 +836,8 @@ func TestDefaultSetScriptSnapshot(t *testing.T) { ch, err := to.td.createDiffSetScriptWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performSetScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performSetScriptWithProofs(tx, + defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -785,18 +856,19 @@ func TestDefaultSetScriptSnapshot(t *testing.T) { }, } + var snapshotI []byte + var snapshotJ []byte sort.Slice(expectedSnapshot, func(i, j int) bool { - snapshotI, err := json.Marshal(expectedSnapshot[i]) + snapshotI, err = json.Marshal(expectedSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(expectedSnapshot[j]) + 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]) + snapshotI, err = json.Marshal(transactionSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(transactionSnapshot[j]) + snapshotJ, err = json.Marshal(transactionSnapshot[j]) assert.NoError(t, err, "failed to marshal snapshots") return string(snapshotI) < string(snapshotJ) }) @@ -811,16 +883,22 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.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) + var err error + 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) + 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) + 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) + 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") @@ -833,7 +911,8 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.T) { ch, err := to.td.createDiffSetAssetScriptWithProofs(tx, defaultDifferInfo()) assert.NoError(t, err, "createDiffBurnWithSig() failed") applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performSetAssetScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performSetAssetScriptWithProofs(tx, + defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") expectedSnapshot := TransactionSnapshot{ @@ -853,18 +932,20 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.T) { }, } + var snapshotI []byte + var snapshotJ []byte sort.Slice(expectedSnapshot, func(i, j int) bool { - snapshotI, err := json.Marshal(expectedSnapshot[i]) + snapshotI, err = json.Marshal(expectedSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(expectedSnapshot[j]) + 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]) + snapshotI, err = json.Marshal(transactionSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(transactionSnapshot[j]) + snapshotJ, err = json.Marshal(transactionSnapshot[j]) assert.NoError(t, err, "failed to marshal snapshots") return string(snapshotI) < string(snapshotJ) }) @@ -878,7 +959,8 @@ func setScript(t *testing.T, to *differTestObjects, addr proto.WavesAddress, pk 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) + 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") @@ -899,7 +981,9 @@ func TestDefaultInvokeScriptSnapshot(t *testing.T) { ] } */ - script := "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAAEY2FsbAAAAAAJAARMAAAAAgkBAAAADEJvb2xlYW5FbnRyeQAAAAICAAAABGJvb2wGCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAANpbnQAAAAAAAAAAAEJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgIAAAADc3RyAgAAAAAFAAAAA25pbAAAAADr9Rv/" + script := "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAAEY2FsbAAAAAAJAARMAAAAAgkBAAAA" + + "DEJvb2xlYW5FbnRyeQAAAAICAAAABGJvb2wGCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAAN" + + "pbnQAAAAAAAAAAAEJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgIAAAADc3RyAgAAAAAFAAAAA25pbAAAAADr9Rv/" scriptsBytes, err := base64.StdEncoding.DecodeString(script) assert.NoError(t, err, "failed to set decode base64 script") @@ -913,14 +997,17 @@ func TestDefaultInvokeScriptSnapshot(t *testing.T) { 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) + 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) + 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") @@ -947,7 +1034,8 @@ func TestDefaultInvokeScriptSnapshot(t *testing.T) { invocationResult := &invocationResult{actions: actions} applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performInvokeScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerData), invocationResult, applicationRes.changes.diff) + transactionSnapshot, err := to.tp.performInvokeScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerData), + invocationResult, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform invoke script tx") expectedSnapshot := TransactionSnapshot{ @@ -969,18 +1057,20 @@ func TestDefaultInvokeScriptSnapshot(t *testing.T) { }, } + var snapshotI []byte + var snapshotJ []byte sort.Slice(expectedSnapshot, func(i, j int) bool { - snapshotI, err := json.Marshal(expectedSnapshot[i]) + snapshotI, err = json.Marshal(expectedSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(expectedSnapshot[j]) + 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]) + snapshotI, err = json.Marshal(transactionSnapshot[i]) assert.NoError(t, err, "failed to marshal snapshots") - snapshotJ, err := json.Marshal(transactionSnapshot[j]) + snapshotJ, err = json.Marshal(transactionSnapshot[j]) assert.NoError(t, err, "failed to marshal snapshots") return string(snapshotI) < string(snapshotJ) }) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 1551c3e59..850f475f6 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -1,9 +1,10 @@ package state import ( - "github.com/pkg/errors" "math/big" + "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" ) @@ -24,7 +25,8 @@ func (ts TransactionSnapshot) Apply(a SnapshotApplier) error { type AtomicSnapshot interface { Apply(SnapshotApplier) error - /*is temporarily used to mark snapshots generated by tx diff that shouldn't be applied , because balances diffs are applied later in the block */ + /* is temporarily used to mark snapshots generated by tx diff that shouldn't be applied, + because balances diffs are applied later in the block. */ IsGeneratedByTxDiff() bool } diff --git a/pkg/state/transaction_checker.go b/pkg/state/transaction_checker.go index df95519ab..ac05cbf81 100644 --- a/pkg/state/transaction_checker.go +++ b/pkg/state/transaction_checker.go @@ -184,7 +184,8 @@ func (tc *transactionChecker) checkDAppCallables(tree *ast.Tree, rideV6Activated type treeEstimations map[int]ride.TreeEstimation -func (tc *transactionChecker) checkScript(script proto.Script, estimatorVersion int, reducedVerifierComplexity, expandEstimations bool) (treeEstimations, error) { +func (tc *transactionChecker) checkScript(script proto.Script, estimatorVersion int, + reducedVerifierComplexity, expandEstimations bool) (treeEstimations, error) { tree, err := serialization.Parse(script) if err != nil { return nil, errs.Extend(err, "failed to build AST") @@ -213,7 +214,8 @@ func (tc *transactionChecker) checkScript(script proto.Script, estimatorVersion if err != nil { return nil, errs.Extend(err, "failed to make ride estimations") } - if err := tc.checkScriptComplexity(tree.LibVersion, estimations[estimatorVersion], tree.IsDApp(), reducedVerifierComplexity); err != nil { + if err = tc.checkScriptComplexity(tree.LibVersion, estimations[estimatorVersion], + tree.IsDApp(), reducedVerifierComplexity); err != nil { return nil, errors.Wrap(err, "failed to check script complexity") } return estimations, nil diff --git a/pkg/state/transaction_checker_test.go b/pkg/state/transaction_checker_test.go index ff7f81942..98b9a8e9b 100644 --- a/pkg/state/transaction_checker_test.go +++ b/pkg/state/transaction_checker_test.go @@ -51,11 +51,11 @@ func createCheckerTestObjects(t *testing.T, checkerInfo *checkerInfo) *checkerTe leases: stor.entities.leases, }, ) - snapshotGenerator := snapshotGenerator{stor: stor.entities, scheme: settings.MainNetSettings.AddressSchemeCharacter} + snapshotGen := snapshotGenerator{stor: stor.entities, scheme: settings.MainNetSettings.AddressSchemeCharacter} tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings) tp.snapshotApplier = &snapshotApplier - tp.snapshotGenerator = &snapshotGenerator + tp.snapshotGenerator = &snapshotGen require.NoError(t, err, "newTransactionPerformer() failed") return &checkerTestObjects{stor, tc, tp, actionsCounter} } diff --git a/pkg/state/transaction_differ.go b/pkg/state/transaction_differ.go index 7e020928d..663b593e3 100644 --- a/pkg/state/transaction_differ.go +++ b/pkg/state/transaction_differ.go @@ -81,7 +81,7 @@ func (diff *balanceDiff) applyTo(profile balanceProfile) (balanceProfile, error) // Check min intermediate change. minBalance, err := common.AddInt64(diff.minBalance, int64(profile.balance)) if err != nil { - return balanceProfile{}, errors.Errorf("failed to add balance and min balance diff: %v\n", err) + return balanceProfile{}, errors.Errorf("failed to add balance and min balance diff: %v", err) } if minBalance < 0 { return balanceProfile{}, errors.Errorf( @@ -93,19 +93,19 @@ func (diff *balanceDiff) applyTo(profile balanceProfile) (balanceProfile, error) // Check main balance diff. newBalance, err := common.AddInt64(diff.balance, int64(profile.balance)) if err != nil { - return balanceProfile{}, errors.Errorf("failed to add balance and balance diff: %v\n", err) + return balanceProfile{}, errors.Errorf("failed to add balance and balance diff: %v", err) } if newBalance < 0 { return balanceProfile{}, errors.New("negative result balance (Attempt to transfer unavailable funds)") } newLeaseIn, err := common.AddInt64(diff.leaseIn, profile.leaseIn) if err != nil { - return balanceProfile{}, errors.Errorf("failed to add leaseIn and leaseIn diff: %v\n", err) + return balanceProfile{}, errors.Errorf("failed to add leaseIn and leaseIn diff: %v", err) } // Check leasing change. newLeaseOut, err := common.AddInt64(diff.leaseOut, profile.leaseOut) if err != nil { - return balanceProfile{}, errors.Errorf("failed to add leaseOut and leaseOut diff: %v\n", err) + return balanceProfile{}, errors.Errorf("failed to add leaseOut and leaseOut diff: %v", err) } if (newBalance < newLeaseOut) && !diff.allowLeasedTransfer { return balanceProfile{}, errs.NewTxValidationError("Reason: Cannot lease more than own") diff --git a/pkg/state/transaction_differ_test.go b/pkg/state/transaction_differ_test.go index a20236f51..6540982d8 100644 --- a/pkg/state/transaction_differ_test.go +++ b/pkg/state/transaction_differ_test.go @@ -57,10 +57,10 @@ func createDifferTestObjects(t *testing.T, checkerInfo *checkerInfo) *differTest leases: stor.entities.leases, }, ) - snapshotGenerator := snapshotGenerator{stor: stor.entities, scheme: settings.MainNetSettings.AddressSchemeCharacter} + snapshotGen := snapshotGenerator{stor: stor.entities, scheme: settings.MainNetSettings.AddressSchemeCharacter} tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings) tp.snapshotApplier = &snapshotApplier - tp.snapshotGenerator = &snapshotGenerator + tp.snapshotGenerator = &snapshotGen require.NoError(t, err, "newTransactionPerformer() failed") return &differTestObjects{stor, td, tp, actionsCounter} } diff --git a/pkg/state/transaction_handler.go b/pkg/state/transaction_handler.go index fef38b57e..2d57ee3c3 100644 --- a/pkg/state/transaction_handler.go +++ b/pkg/state/transaction_handler.go @@ -49,85 +49,112 @@ type transactionHandler struct { func buildHandles(tc *transactionChecker, tp *transactionPerformer, td *transactionDiffer, tf *transactionFeeCounter) handles { return handles{ proto.TransactionTypeInfo{Type: proto.GenesisTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkGenesis, tp.performGenesis, td.createDiffGenesis, nil, + tc.checkGenesis, tp.performGenesis, + td.createDiffGenesis, nil, }, proto.TransactionTypeInfo{Type: proto.PaymentTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkPayment, tp.performPayment, td.createDiffPayment, tf.minerFeePayment, + tc.checkPayment, tp.performPayment, + td.createDiffPayment, tf.minerFeePayment, }, proto.TransactionTypeInfo{Type: proto.TransferTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkTransferWithSig, tp.performTransferWithSig, td.createDiffTransferWithSig, tf.minerFeeTransferWithSig, + tc.checkTransferWithSig, tp.performTransferWithSig, + td.createDiffTransferWithSig, tf.minerFeeTransferWithSig, }, proto.TransactionTypeInfo{Type: proto.TransferTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkTransferWithProofs, tp.performTransferWithProofs, 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, + tc.checkIssueWithSig, tp.performIssueWithSig, + td.createDiffIssueWithSig, tf.minerFeeIssueWithSig, }, proto.TransactionTypeInfo{Type: proto.IssueTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkIssueWithProofs, tp.performIssueWithProofs, td.createDiffIssueWithProofs, tf.minerFeeIssueWithProofs, + tc.checkIssueWithProofs, tp.performIssueWithProofs, + td.createDiffIssueWithProofs, tf.minerFeeIssueWithProofs, }, proto.TransactionTypeInfo{Type: proto.ReissueTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkReissueWithSig, tp.performReissueWithSig, td.createDiffReissueWithSig, tf.minerFeeReissueWithSig, + tc.checkReissueWithSig, tp.performReissueWithSig, + td.createDiffReissueWithSig, tf.minerFeeReissueWithSig, }, proto.TransactionTypeInfo{Type: proto.ReissueTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkReissueWithProofs, tp.performReissueWithProofs, td.createDiffReissueWithProofs, tf.minerFeeReissueWithProofs, + tc.checkReissueWithProofs, tp.performReissueWithProofs, + td.createDiffReissueWithProofs, tf.minerFeeReissueWithProofs, }, proto.TransactionTypeInfo{Type: proto.BurnTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkBurnWithSig, tp.performBurnWithSig, td.createDiffBurnWithSig, tf.minerFeeBurnWithSig, + tc.checkBurnWithSig, tp.performBurnWithSig, + td.createDiffBurnWithSig, tf.minerFeeBurnWithSig, }, proto.TransactionTypeInfo{Type: proto.BurnTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkBurnWithProofs, tp.performBurnWithProofs, td.createDiffBurnWithProofs, tf.minerFeeBurnWithProofs, + tc.checkBurnWithProofs, tp.performBurnWithProofs, + td.createDiffBurnWithProofs, tf.minerFeeBurnWithProofs, }, proto.TransactionTypeInfo{Type: proto.ExchangeTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkExchangeWithSig, tp.performExchange, td.createDiffExchange, tf.minerFeeExchange, + tc.checkExchangeWithSig, tp.performExchange, + td.createDiffExchange, tf.minerFeeExchange, }, proto.TransactionTypeInfo{Type: proto.ExchangeTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkExchangeWithProofs, tp.performExchange, td.createDiffExchange, tf.minerFeeExchange, + tc.checkExchangeWithProofs, tp.performExchange, + td.createDiffExchange, tf.minerFeeExchange, }, proto.TransactionTypeInfo{Type: proto.LeaseTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkLeaseWithSig, tp.performLeaseWithSig, td.createDiffLeaseWithSig, tf.minerFeeLeaseWithSig, + tc.checkLeaseWithSig, tp.performLeaseWithSig, + td.createDiffLeaseWithSig, tf.minerFeeLeaseWithSig, }, proto.TransactionTypeInfo{Type: proto.LeaseTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkLeaseWithProofs, tp.performLeaseWithProofs, td.createDiffLeaseWithProofs, tf.minerFeeLeaseWithProofs, + tc.checkLeaseWithProofs, tp.performLeaseWithProofs, + td.createDiffLeaseWithProofs, tf.minerFeeLeaseWithProofs, }, proto.TransactionTypeInfo{Type: proto.LeaseCancelTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkLeaseCancelWithSig, tp.performLeaseCancelWithSig, td.createDiffLeaseCancelWithSig, tf.minerFeeLeaseCancelWithSig, + tc.checkLeaseCancelWithSig, tp.performLeaseCancelWithSig, + td.createDiffLeaseCancelWithSig, tf.minerFeeLeaseCancelWithSig, }, proto.TransactionTypeInfo{Type: proto.LeaseCancelTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkLeaseCancelWithProofs, tp.performLeaseCancelWithProofs, td.createDiffLeaseCancelWithProofs, tf.minerFeeLeaseCancelWithProofs, + tc.checkLeaseCancelWithProofs, tp.performLeaseCancelWithProofs, + td.createDiffLeaseCancelWithProofs, tf.minerFeeLeaseCancelWithProofs, }, proto.TransactionTypeInfo{Type: proto.CreateAliasTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkCreateAliasWithSig, tp.performCreateAliasWithSig, td.createDiffCreateAliasWithSig, tf.minerFeeCreateAliasWithSig, + tc.checkCreateAliasWithSig, tp.performCreateAliasWithSig, + td.createDiffCreateAliasWithSig, tf.minerFeeCreateAliasWithSig, }, proto.TransactionTypeInfo{Type: proto.CreateAliasTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkCreateAliasWithProofs, tp.performCreateAliasWithProofs, td.createDiffCreateAliasWithProofs, tf.minerFeeCreateAliasWithProofs, + tc.checkCreateAliasWithProofs, tp.performCreateAliasWithProofs, + td.createDiffCreateAliasWithProofs, tf.minerFeeCreateAliasWithProofs, }, proto.TransactionTypeInfo{Type: proto.MassTransferTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkMassTransferWithProofs, tp.performMassTransferWithProofs, 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, + tc.checkDataWithProofs, tp.performDataWithProofs, + td.createDiffDataWithProofs, tf.minerFeeDataWithProofs, }, proto.TransactionTypeInfo{Type: proto.SponsorshipTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkSponsorshipWithProofs, tp.performSponsorshipWithProofs, td.createDiffSponsorshipWithProofs, tf.minerFeeSponsorshipWithProofs, + tc.checkSponsorshipWithProofs, tp.performSponsorshipWithProofs, + td.createDiffSponsorshipWithProofs, tf.minerFeeSponsorshipWithProofs, }, proto.TransactionTypeInfo{Type: proto.SetScriptTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkSetScriptWithProofs, tp.performSetScriptWithProofs, td.createDiffSetScriptWithProofs, tf.minerFeeSetScriptWithProofs, + tc.checkSetScriptWithProofs, tp.performSetScriptWithProofs, + td.createDiffSetScriptWithProofs, tf.minerFeeSetScriptWithProofs, }, proto.TransactionTypeInfo{Type: proto.SetAssetScriptTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkSetAssetScriptWithProofs, tp.performSetAssetScriptWithProofs, td.createDiffSetAssetScriptWithProofs, tf.minerFeeSetAssetScriptWithProofs, + tc.checkSetAssetScriptWithProofs, tp.performSetAssetScriptWithProofs, + td.createDiffSetAssetScriptWithProofs, tf.minerFeeSetAssetScriptWithProofs, }, proto.TransactionTypeInfo{Type: proto.InvokeScriptTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkInvokeScriptWithProofs, tp.performInvokeScriptWithProofs, td.createDiffInvokeScriptWithProofs, tf.minerFeeInvokeScriptWithProofs, + tc.checkInvokeScriptWithProofs, tp.performInvokeScriptWithProofs, + td.createDiffInvokeScriptWithProofs, tf.minerFeeInvokeScriptWithProofs, }, proto.TransactionTypeInfo{Type: proto.InvokeExpressionTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkInvokeExpressionWithProofs, tp.performInvokeExpressionWithProofs, td.createDiffInvokeExpressionWithProofs, tf.minerFeeInvokeExpressionWithProofs, + tc.checkInvokeExpressionWithProofs, tp.performInvokeExpressionWithProofs, + td.createDiffInvokeExpressionWithProofs, tf.minerFeeInvokeExpressionWithProofs, }, proto.TransactionTypeInfo{Type: proto.UpdateAssetInfoTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkUpdateAssetInfoWithProofs, tp.performUpdateAssetInfoWithProofs, td.createDiffUpdateAssetInfoWithProofs, tf.minerFeeUpdateAssetInfoWithProofs, + tc.checkUpdateAssetInfoWithProofs, tp.performUpdateAssetInfoWithProofs, + td.createDiffUpdateAssetInfoWithProofs, tf.minerFeeUpdateAssetInfoWithProofs, }, proto.TransactionTypeInfo{Type: proto.EthereumMetamaskTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkEthereumTransactionWithProofs, tp.performEthereumTransactionWithProofs, td.createDiffEthereumTransactionWithProofs, tf.minerFeeEthereumTxWithProofs, + tc.checkEthereumTransactionWithProofs, tp.performEthereumTransactionWithProofs, + td.createDiffEthereumTransactionWithProofs, tf.minerFeeEthereumTxWithProofs, }, } } @@ -169,11 +196,12 @@ func (h *transactionHandler) checkTx(tx proto.Transaction, info *checkerInfo) (t return funcs.check(tx, info) } -func (h *transactionHandler) performTx(tx proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (h *transactionHandler) performTx(tx proto.Transaction, info *performerInfo, + invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tv := tx.GetTypeInfo() funcs, ok := h.funcs[tv] if !ok { - return nil, 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", tx) } if funcs.perform == nil { // No perform func for this combination of transaction type and version. diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index d05afc5fd..0cf449a4d 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -17,8 +17,12 @@ type performerInfo struct { checkerData txCheckerData } -func newPerformerInfo(height proto.Height, stateActionsCounter *proto.StateActionsCounter, blockID proto.BlockID, currentMinerAddress proto.WavesAddress, checkerData txCheckerData) *performerInfo { - return &performerInfo{height, blockID, currentMinerAddress, stateActionsCounter, checkerData} // all fields must be initialized +func newPerformerInfo(height proto.Height, stateActionsCounter *proto.StateActionsCounter, + blockID proto.BlockID, currentMinerAddress proto.WavesAddress, + checkerData txCheckerData) *performerInfo { + return &performerInfo{height, blockID, + currentMinerAddress, stateActionsCounter, + checkerData} // all fields must be initialized } type transactionPerformer struct { @@ -32,7 +36,10 @@ func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings return &transactionPerformer{stor: stor, settings: settings}, nil } -func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performGenesis( + transaction proto.Transaction, + _ *performerInfo, _ *invocationResult, + balanceChanges txDiff) (TransactionSnapshot, error) { _, ok := transaction.(*proto.Genesis) if !ok { return nil, errors.New("failed to convert interface to genesis transaction") @@ -44,7 +51,8 @@ func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, _ return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performPayment(transaction proto.Transaction, _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performPayment(transaction proto.Transaction, _ *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { _, ok := transaction.(*proto.Payment) if !ok { return nil, errors.New("failed to convert interface to payment transaction") @@ -64,7 +72,8 @@ func (tp *transactionPerformer) performTransfer(balanceChanges txDiff) (Transact return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transaction, _ *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { _, ok := transaction.(*proto.TransferWithSig) if !ok { return nil, errors.New("failed to convert interface to transfer with sig transaction") @@ -72,7 +81,8 @@ func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transac return tp.performTransfer(balanceChanges) } -func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Transaction, _ *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { _, ok := transaction.(*proto.TransferWithProofs) if !ok { return nil, errors.New("failed to convert interface to transfer with proofs transaction") @@ -80,7 +90,9 @@ func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Tran return tp.performTransfer(balanceChanges) } -func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest, assetID crypto.Digest, info *performerInfo, balanceChanges txDiff, scriptInformation *scriptInformation) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest, + assetID crypto.Digest, info *performerInfo, + balanceChanges txDiff, scriptInformation *scriptInformation) (TransactionSnapshot, error) { blockHeight := info.height + 1 // Create new asset. assetInfo := &assetInfo{ @@ -99,7 +111,8 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest }, } - snapshot, err := tp.snapshotGenerator.generateSnapshotForIssueTx(assetID, txID, tx.SenderPK, *assetInfo, balanceChanges, scriptInformation) + snapshot, err := tp.snapshotGenerator.generateSnapshotForIssueTx(assetID, txID, tx.SenderPK, + *assetInfo, balanceChanges, scriptInformation) if err != nil { return nil, err @@ -107,14 +120,15 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.IssueWithSig) if !ok { return nil, errors.New("failed to convert interface to IssueWithSig transaction") } txID, err := tx.GetID(tp.settings.AddressSchemeCharacter) if err != nil { - return nil, errors.Errorf("failed to get transaction ID: %v\n", err) + return nil, errors.Errorf("failed to get transaction ID: %v", err) } assetID, err := crypto.NewDigestFromBytes(txID) if err != nil { @@ -124,14 +138,15 @@ func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transactio return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges, nil) } -func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.IssueWithProofs) if !ok { return nil, errors.New("failed to convert interface to IssueWithProofs transaction") } txID, err := tx.GetID(tp.settings.AddressSchemeCharacter) if err != nil { - return nil, errors.Errorf("failed to get transaction ID: %v\n", err) + return nil, errors.Errorf("failed to get transaction ID: %v", err) } assetID, err := crypto.NewDigestFromBytes(txID) if err != nil { @@ -142,7 +157,9 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac // Save complexities to storage, so we won't have to calculate it every time the script is called. complexity, ok := se.estimations[se.currentEstimatorVersion] if !ok { - return nil, errors.Errorf("failed to calculate asset script complexity by estimator version %d", se.currentEstimatorVersion) + return nil, + errors.Errorf("failed to calculate asset script complexity by estimator version %d", + se.currentEstimatorVersion) } scriptInfo = &scriptInformation{ script: tx.Script, @@ -152,7 +169,8 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges, scriptInfo) } -func (tp *transactionPerformer) performReissue(tx *proto.Reissue, _ *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performReissue(tx *proto.Reissue, _ *performerInfo, + balanceChanges txDiff) (TransactionSnapshot, error) { // Modify asset. change := &assetReissueChange{ reissuable: tx.Reissuable, @@ -166,7 +184,8 @@ func (tp *transactionPerformer) performReissue(tx *proto.Reissue, _ *performerIn return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.ReissueWithSig) if !ok { return nil, errors.New("failed to convert interface to ReissueWithSig transaction") @@ -174,7 +193,8 @@ func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transact return tp.performReissue(&tx.Reissue, info, balanceChanges) } -func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Transaction, + info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.ReissueWithProofs) if !ok { return nil, errors.New("failed to convert interface to ReissueWithProofs transaction") @@ -182,7 +202,8 @@ func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Trans return tp.performReissue(&tx.Reissue, info, balanceChanges) } -func (tp *transactionPerformer) performBurn(tx *proto.Burn, _ *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performBurn(tx *proto.Burn, _ *performerInfo, + balanceChanges txDiff) (TransactionSnapshot, error) { // Modify asset. change := &assetBurnChange{ diff: int64(tx.Amount), @@ -195,7 +216,8 @@ func (tp *transactionPerformer) performBurn(tx *proto.Burn, _ *performerInfo, ba return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.BurnWithSig) if !ok { return nil, errors.New("failed to convert interface to BurnWithSig transaction") @@ -203,7 +225,8 @@ func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction return tp.performBurn(&tx.Burn, info, balanceChanges) } -func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.BurnWithProofs) if !ok { return nil, errors.New("failed to convert interface to BurnWithProofs transaction") @@ -211,7 +234,8 @@ func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transact return tp.performBurn(&tx.Burn, info, balanceChanges) } -func (tp *transactionPerformer) performExchange(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performExchange(transaction proto.Transaction, _ *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(proto.Exchange) if !ok { return nil, errors.New("failed to convert interface to Exchange transaction") @@ -229,14 +253,16 @@ func (tp *transactionPerformer) performExchange(transaction proto.Transaction, i buyFee := tx.GetBuyMatcherFee() // snapshot must be generated before the state with orders is changed - snapshot, err := tp.snapshotGenerator.generateSnapshotForExchangeTx(sellOrder, sellFee, buyOrder, buyFee, volume, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForExchangeTx(sellOrder, + sellFee, buyOrder, buyFee, volume, balanceChanges) if err != nil { return nil, err } return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest, info *performerInfo, + balanceChanges txDiff) (TransactionSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { return nil, err @@ -245,7 +271,7 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest if addr := tx.Recipient.Address(); addr == nil { recipientAddr, err = tp.stor.aliases.newestAddrByAlias(tx.Recipient.Alias().Alias) if err != nil { - return nil, errors.Errorf("invalid alias: %v\n", err) + return nil, errors.Errorf("invalid alias: %v", err) } } else { recipientAddr = *addr @@ -265,7 +291,8 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseWithSig) if !ok { return nil, errors.New("failed to convert interface to LeaseWithSig transaction") @@ -273,7 +300,8 @@ func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transactio return tp.performLease(&tx.Lease, *tx.ID, info, balanceChanges) } -func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseWithProofs) if !ok { return nil, errors.New("failed to convert interface to LeaseWithProofs transaction") @@ -281,20 +309,24 @@ func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transac return tp.performLease(&tx.Lease, *tx.ID, info, balanceChanges) } -func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID *crypto.Digest, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID *crypto.Digest, info *performerInfo, + balanceChanges txDiff) (TransactionSnapshot, error) { oldLease, err := tp.stor.leases.newestLeasingInfo(tx.LeaseID) if err != nil { return nil, errors.Wrap(err, "failed to receiver leasing info") } - snapshot, err := tp.snapshotGenerator.generateSnapshotForLeaseCancelTx(txID, *oldLease, tx.LeaseID, *oldLease.OriginTransactionID, info.height, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForLeaseCancelTx(txID, + *oldLease, tx.LeaseID, *oldLease.OriginTransactionID, + info.height, balanceChanges) if err != nil { return nil, err } return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseCancelWithSig) if !ok { return nil, errors.New("failed to convert interface to LeaseCancelWithSig transaction") @@ -302,7 +334,8 @@ func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Tran return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info, balanceChanges) } -func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseCancelWithProofs) if !ok { return nil, errors.New("failed to convert interface to LeaseCancelWithProofs transaction") @@ -310,7 +343,8 @@ func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.T return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info, balanceChanges) } -func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, _ *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, + _ *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { return nil, err @@ -323,7 +357,8 @@ func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, _ *per return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.CreateAliasWithSig) if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithSig transaction") @@ -331,7 +366,8 @@ func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Tran return tp.performCreateAlias(&tx.CreateAlias, info, balanceChanges) } -func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.CreateAliasWithProofs) if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") @@ -339,7 +375,8 @@ func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.T return tp.performCreateAlias(&tx.CreateAlias, info, balanceChanges) } -func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto.Transaction, _ *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { _, ok := transaction.(*proto.MassTransferWithProofs) if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") @@ -351,8 +388,8 @@ func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto. return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { - +func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, + _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.DataWithProofs) if !ok { return nil, errors.New("failed to convert interface to DataWithProofs transaction") @@ -369,7 +406,8 @@ func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transact return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.Transaction, _ *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.SponsorshipWithProofs) if !ok { return nil, errors.New("failed to convert interface to SponsorshipWithProofs transaction") @@ -382,7 +420,8 @@ func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.T return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.SetScriptWithProofs) if !ok { return nil, errors.New("failed to convert interface to SetScriptWithProofs transaction") @@ -395,7 +434,8 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra // TODO check on correctness complexity := info.checkerData.scriptEstimations.estimations[se.currentEstimatorVersion].Verifier - snapshot, err := tp.snapshotGenerator.generateSnapshotForSetScriptTx(tx.SenderPK, tx.Script, complexity, info, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForSetScriptTx(tx.SenderPK, + tx.Script, complexity, info, balanceChanges) if err != nil { return nil, err @@ -403,7 +443,8 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.SetAssetScriptWithProofs) if !ok { return nil, errors.New("failed to convert interface to SetAssetScriptWithProofs transaction") @@ -415,82 +456,22 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot } estimation, ok := se.estimations[se.currentEstimatorVersion] if !ok { - return nil, errors.Errorf("failed to calculate asset script complexity by estimator version %d", se.currentEstimatorVersion) + return nil, errors.Errorf( + "failed to calculate asset script complexity by estimator version %d", + se.currentEstimatorVersion) } complexity := estimation.Verifier - snapshot, err := tp.snapshotGenerator.generateSnapshotForSetAssetScriptTx(tx.AssetID, tx.Script, complexity, tx.SenderPK, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForSetAssetScriptTx(tx.AssetID, + tx.Script, complexity, tx.SenderPK, balanceChanges) if err != nil { return nil, err } return snapshot, snapshot.Apply(tp.snapshotApplier) } -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 _, ok := addrWavesBalanceDiff[recipientAddress]; ok { - prevRecipientBalance := addrWavesBalanceDiff[recipientAddress] - prevRecipientBalance.balance += amount - addrWavesBalanceDiff[recipientAddress] = prevRecipientBalance - } else { - addrWavesBalanceDiff[recipientAddress] = balanceDiff{balance: amount} - } -} - -// subtracts the amount from the sender's balance and add it to the recipient's balance. -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) performInvokeScriptWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto.Transaction, info *performerInfo, + invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { if _, ok := transaction.(*proto.InvokeScriptWithProofs); !ok { return nil, errors.New("failed to convert interface to InvokeScriptWithProofs transaction") } @@ -500,7 +481,7 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. } txIDBytes, err := transaction.GetID(tp.settings.AddressSchemeCharacter) if err != nil { - return nil, errors.Errorf("failed to get transaction ID: %v\n", err) + return nil, errors.Errorf("failed to get transaction ID: %v", err) } txID, err := crypto.NewDigestFromBytes(txIDBytes) if err != nil { @@ -514,7 +495,8 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo, + invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { if _, ok := transaction.(*proto.InvokeExpressionTransactionWithProofs); !ok { return nil, errors.New("failed to convert interface to InvokeExpressionWithProofs transaction") } @@ -524,7 +506,7 @@ func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction pr } txIDBytes, err := transaction.GetID(tp.settings.AddressSchemeCharacter) if err != nil { - return nil, errors.Errorf("failed to get transaction ID: %v\n", err) + return nil, errors.Errorf("failed to get transaction ID: %v", err) } txID, err := crypto.NewDigestFromBytes(txIDBytes) if err != nil { @@ -538,7 +520,8 @@ func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction pr return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo, + invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { ethTx, ok := transaction.(*proto.EthereumTransaction) if !ok { return nil, errors.New("failed to convert interface to EthereumTransaction transaction") @@ -551,28 +534,31 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction } txIDBytes, err := transaction.GetID(tp.settings.AddressSchemeCharacter) if err != nil { - return nil, errors.Errorf("failed to get transaction ID: %v\n", err) + return nil, errors.Errorf("failed to get transaction ID: %v", err) } txID, err := crypto.NewDigestFromBytes(txIDBytes) if err != nil { return nil, err } - snapshot, err := tp.snapshotGenerator.generateSnapshotForEthereumInvokeScriptTx(txID, info, invocationRes, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForEthereumInvokeScriptTx(txID, + info, invocationRes, balanceChanges) if err != nil { return nil, err } return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.UpdateAssetInfoWithProofs) if !ok { return nil, errors.New("failed to convert interface to UpdateAssetInfoWithProofs transaction") } blockHeight := info.height + 1 - snapshot, err := tp.snapshotGenerator.generateSnapshotForUpdateAssetInfoTx(tx.AssetID, tx.Name, tx.Description, blockHeight, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForUpdateAssetInfoTx(tx.AssetID, + tx.Name, tx.Description, blockHeight, balanceChanges) if err != nil { return nil, err } diff --git a/pkg/state/transaction_performer_test.go b/pkg/state/transaction_performer_test.go index 96400f168..7672f4742 100644 --- a/pkg/state/transaction_performer_test.go +++ b/pkg/state/transaction_performer_test.go @@ -44,9 +44,9 @@ func createPerformerTestObjects(t *testing.T, checkerInfo *checkerInfo) *perform leases: stor.entities.leases, }, ) - snapshotGenerator := snapshotGenerator{stor: stor.entities, scheme: settings.MainNetSettings.AddressSchemeCharacter} + snapshotGen := snapshotGenerator{stor: stor.entities, scheme: settings.MainNetSettings.AddressSchemeCharacter} tp.snapshotApplier = &snapshotApplier - tp.snapshotGenerator = &snapshotGenerator + tp.snapshotGenerator = &snapshotGen require.NoError(t, err, "newTransactionPerformer() failed") return &performerTestObjects{stor, tp, actionsCounter} } From fccc3d0c658bc4c88c0adb3270dc436f780ba84c Mon Sep 17 00:00:00 2001 From: esuwu Date: Sat, 12 Aug 2023 20:14:36 -0500 Subject: [PATCH 054/139] Fixed a few more linter issues --- pkg/state/invoke_applier.go | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index 8ef447c96..f41c03e1c 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -919,25 +919,31 @@ func (ia *invokeApplier) countScriptRuns(info *fallibleValidationParams, scriptRuns += uint64(len(paymentSmartAssets)) + actionScriptRuns } if info.senderScripted { + treeEstimation, err := ia.stor.scriptsComplexity.newestScriptComplexityByAddr( + info.senderAddress, info.checkerInfo.estimatorVersion()) + if err != nil { + return 0, errors.Wrap(err, "invoke failed to get verifier complexity") + } // Since activation of RideV5 (16) feature - // we don't take fee for verifier execution if it's complexity is less than `FreeVerifierComplexity` limit - - if info.rideV5Activated { - treeEstimation, err := ia.stor.scriptsComplexity.newestScriptComplexityByAddr( - info.senderAddress, info.checkerInfo.estimatorVersion()) - if err != nil { - return 0, errors.Wrap(err, "invoke failed to get verifier complexity") - } - if treeEstimation.Verifier > FreeVerifierComplexity { - scriptRuns++ - } - } else { + // we don't take fee for verifier execution if it's complexity is less than `FreeVerifierComplexity` limit, + // take fee in any other case + if !(info.rideV5Activated && treeEstimation.Verifier <= FreeVerifierComplexity) { + // take fee scriptRuns++ } } return scriptRuns, nil } +func (ia *invokeApplier) refusePayments(scriptParams scriptParameters, disableSelfTransfers bool) bool { + if disableSelfTransfers && scriptParams.paymentsLength > 0 { + if scriptParams.sender == scriptParams.scriptAddr { + return true + } + } + return false +} + // applyInvokeScript checks InvokeScript transaction, creates its balance diffs and adds changes to `uncertain` storage. // If the transaction does not fail, changes are committed (moved from uncertain to normal storage) // later in performInvokeScriptWithProofs(). @@ -980,11 +986,10 @@ func (ia *invokeApplier) applyInvokeScript( } // Refuse payments to DApp itself since activation of BlockV5 (acceptFailed) and for DApps with StdLib V4. disableSelfTransfers := info.acceptFailed && scriptParams.tree.LibVersion >= ast.LibV4 - if disableSelfTransfers && scriptParams.paymentsLength > 0 { - if scriptParams.sender == scriptParams.scriptAddr { - return nil, nil, errors.New("paying to DApp itself is forbidden since RIDE V4") - } + if ia.refusePayments(scriptParams, disableSelfTransfers) { + 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)) From 6ddb1bdf9fa0600681bd4dcf6a55a2410fae3610 Mon Sep 17 00:00:00 2001 From: esuwu Date: Sun, 13 Aug 2023 23:39:16 -0500 Subject: [PATCH 055/139] Fixed all linter issues --- pkg/state/invoke_applier.go | 138 +++++++++++------- pkg/state/snapshot_generator.go | 51 ++++--- ...go => snapshot_generator_internal_test.go} | 6 +- 3 files changed, 114 insertions(+), 81 deletions(-) rename pkg/state/{snapshot_generator_test.go => snapshot_generator_internal_test.go} (99%) diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index f41c03e1c..87960dd63 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -799,73 +799,103 @@ type scriptParameters struct { scriptPK crypto.PublicKey } +func (ia *invokeApplier) scriptParametersFromInvokeScript( + transaction *proto.InvokeScriptWithProofs, +) (scriptParameters, error) { + var scriptParams scriptParameters + var err error + scriptParams.scriptAddr, err = recipientToAddress(transaction.ScriptRecipient, ia.stor.aliases) + if err != nil { + return scriptParameters{}, errors.Wrap(err, "recipientToAddress() failed") + } + scriptParams.paymentsLength = len(transaction.Payments) + scriptParams.txID = *transaction.ID + scriptParams.sender, err = proto.NewAddressFromPublicKey(ia.settings.AddressSchemeCharacter, transaction.SenderPK) + if err != nil { + return scriptParameters{}, errors.Wrapf(err, "failed to apply script invocation") + } + scriptParams.tree, err = ia.stor.scriptsStorage.newestScriptByAddr(scriptParams.scriptAddr) + if err != nil { + return scriptParameters{}, + errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptParams.scriptAddr.String()) + } + var si scriptBasicInfoRecord + si, err = ia.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptParams.scriptAddr.ID()) + if err != nil { + return scriptParameters{}, + errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptParams.scriptAddr.String()) + } + scriptParams.scriptPK = si.PK + return scriptParams, nil +} + +func (ia *invokeApplier) scriptParametersFromInvokeExpression( + transaction *proto.InvokeExpressionTransactionWithProofs) (scriptParameters, error) { + var scriptParams scriptParameters + addr, err := proto.NewAddressFromPublicKey(ia.settings.AddressSchemeCharacter, transaction.SenderPK) + if err != nil { + return scriptParameters{}, errors.Wrap(err, "recipientToAddress() failed") + } + scriptParams.sender = addr + scriptParams.scriptAddr = addr + scriptParams.tree, err = serialization.Parse(transaction.Expression) + if err != nil { + return scriptParameters{}, errors.Wrap(err, "failed to parse decoded invoke expression into tree") + } + scriptParams.txID = *transaction.ID + scriptParams.scriptPK = transaction.SenderPK + return scriptParams, nil +} + +func (ia *invokeApplier) scriptParametersFromEthereumInvokeTransaction( + transaction *proto.EthereumTransaction) (scriptParameters, error) { + var scriptParams scriptParameters + var err error + scriptParams.scriptAddr, err = transaction.WavesAddressTo(ia.settings.AddressSchemeCharacter) + if err != nil { + return scriptParameters{}, err + } + decodedData := transaction.TxKind.DecodedData() + scriptParams.paymentsLength = len(decodedData.Payments) + scriptParams.txID = *transaction.ID + scriptParams.sender, err = transaction.WavesAddressFrom(ia.settings.AddressSchemeCharacter) + if err != nil { + return scriptParameters{}, errors.Wrapf(err, "failed to apply script invocation") + } + scriptParams.tree, err = ia.stor.scriptsStorage.newestScriptByAddr(scriptParams.scriptAddr) + if err != nil { + return scriptParameters{}, + errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptParams.scriptAddr.String()) + } + var si scriptBasicInfoRecord + si, err = ia.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptParams.scriptAddr.ID()) + if err != nil { + return scriptParameters{}, + errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptParams.scriptAddr.String()) + } + scriptParams.scriptPK = si.PK + return scriptParams, nil +} + func (ia *invokeApplier) collectScriptParameters(tx proto.Transaction) (scriptParameters, error) { - scriptParams := scriptParameters{} + var scriptParams scriptParameters var err error switch transaction := tx.(type) { case *proto.InvokeScriptWithProofs: - scriptParams.scriptAddr, err = recipientToAddress(transaction.ScriptRecipient, ia.stor.aliases) + scriptParams, err = ia.scriptParametersFromInvokeScript(transaction) if err != nil { - return scriptParameters{}, errors.Wrap(err, "recipientToAddress() failed") - } - scriptParams.paymentsLength = len(transaction.Payments) - scriptParams.txID = *transaction.ID - scriptParams.sender, err = proto.NewAddressFromPublicKey(ia.settings.AddressSchemeCharacter, transaction.SenderPK) - if err != nil { - return scriptParameters{}, errors.Wrapf(err, "failed to apply script invocation") - } - scriptParams.tree, err = ia.stor.scriptsStorage.newestScriptByAddr(scriptParams.scriptAddr) - if err != nil { - return scriptParameters{}, - errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptParams.scriptAddr.String()) - } - var si scriptBasicInfoRecord - si, err = ia.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptParams.scriptAddr.ID()) - if err != nil { - return scriptParameters{}, - errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptParams.scriptAddr.String()) + return scriptParameters{}, err } - scriptParams.scriptPK = si.PK - case *proto.InvokeExpressionTransactionWithProofs: - addr, err := proto.NewAddressFromPublicKey(ia.settings.AddressSchemeCharacter, transaction.SenderPK) - if err != nil { - return scriptParameters{}, errors.Wrap(err, "recipientToAddress() failed") - } - scriptParams.sender = addr - scriptParams.scriptAddr = addr - scriptParams.tree, err = serialization.Parse(transaction.Expression) + scriptParams, err = ia.scriptParametersFromInvokeExpression(transaction) if err != nil { - return scriptParameters{}, errors.Wrap(err, "failed to parse decoded invoke expression into tree") + return scriptParameters{}, err } - scriptParams.txID = *transaction.ID - scriptParams.scriptPK = transaction.SenderPK - case *proto.EthereumTransaction: - scriptParams.scriptAddr, err = transaction.WavesAddressTo(ia.settings.AddressSchemeCharacter) + scriptParams, err = ia.scriptParametersFromEthereumInvokeTransaction(transaction) if err != nil { return scriptParameters{}, err } - decodedData := transaction.TxKind.DecodedData() - scriptParams.paymentsLength = len(decodedData.Payments) - scriptParams.txID = *transaction.ID - scriptParams.sender, err = transaction.WavesAddressFrom(ia.settings.AddressSchemeCharacter) - if err != nil { - return scriptParameters{}, errors.Wrapf(err, "failed to apply script invocation") - } - scriptParams.tree, err = ia.stor.scriptsStorage.newestScriptByAddr(scriptParams.scriptAddr) - if err != nil { - return scriptParameters{}, - errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptParams.scriptAddr.String()) - } - var si scriptBasicInfoRecord - si, err = ia.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptParams.scriptAddr.ID()) - if err != nil { - return scriptParameters{}, - errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptParams.scriptAddr.String()) - } - scriptParams.scriptPK = si.PK - default: return scriptParameters{}, errors.Errorf("failed to apply an invoke script: unexpected type of transaction (%T)", tx) } diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index 7f8c912b4..62a094fbd 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -467,7 +467,8 @@ func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( action proto.IssueScriptAction, blockHeight uint64, info *performerInfo, - txID crypto.Digest) ([]AtomicSnapshot, error) { + txID crypto.Digest, + assetBalanceDiff addressAssetBalanceDiff) ([]AtomicSnapshot, error) { var atomicSnapshots []AtomicSnapshot assetInf := assetInfo{ assetConstInfo: assetConstInfo{ @@ -530,11 +531,18 @@ func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( atomicSnapshots = append(atomicSnapshots, assetScriptSnapshot) } atomicSnapshots = append(atomicSnapshots, issueStaticInfoSnapshot, assetDescription, assetReissuability) + + issuerAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *action.Sender) + if err != nil { + return nil, errors.Wrap(err, "failed to get an address from a public key") + } + assetBalanceDiff.appendOnlySender(issuerAddress, proto.AssetIDFromDigest(action.ID), action.Quantity) return atomicSnapshots, nil } func (sg *snapshotGenerator) atomicActionsFromReissueAction( - action proto.ReissueScriptAction) ([]AtomicSnapshot, error) { + action proto.ReissueScriptAction, + assetBalanceDiff addressAssetBalanceDiff) ([]AtomicSnapshot, error) { var atomicSnapshots []AtomicSnapshot assetInf, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(action.AssetID)) if err != nil { @@ -547,12 +555,18 @@ func (sg *snapshotGenerator) atomicActionsFromReissueAction( TotalQuantity: *resQuantity, IsReissuable: action.Reissuable, } - + issueAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *action.Sender) + if err != nil { + return nil, errors.Wrap(err, "failed to get an address from a public key") + } + assetBalanceDiff.appendOnlySender(issueAddress, proto.AssetIDFromDigest(action.AssetID), action.Quantity) atomicSnapshots = append(atomicSnapshots, assetReissuability) return atomicSnapshots, nil } -func (sg *snapshotGenerator) atomicActionsFromBurnAction(action proto.BurnScriptAction) ([]AtomicSnapshot, error) { +func (sg *snapshotGenerator) atomicActionsFromBurnAction( + action proto.BurnScriptAction, + assetBalanceDiff addressAssetBalanceDiff) ([]AtomicSnapshot, error) { var atomicSnapshots []AtomicSnapshot var assetInf *assetInfo assetInf, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(action.AssetID)) @@ -566,8 +580,12 @@ func (sg *snapshotGenerator) atomicActionsFromBurnAction(action proto.BurnScript TotalQuantity: *resQuantity, IsReissuable: assetInf.reissuable, } - atomicSnapshots = append(atomicSnapshots, assetReissuability) + issueAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *action.Sender) + if err != nil { + return nil, errors.Wrap(err, "failed to get an address from a public key") + } + assetBalanceDiff.appendOnlySender(issueAddress, proto.AssetIDFromDigest(action.AssetID), -action.Quantity) return atomicSnapshots, nil } @@ -666,39 +684,24 @@ func (sg *snapshotGenerator) collectBalanceAndSnapshotFromAction( } atomicSnapshots = append(atomicSnapshots, sponsorshipSnapshot) case *proto.IssueScriptAction: - issueSnapshots, err := sg.atomicSnapshotsFromIssueAction(*a, blockHeight, info, txID) + issueSnapshots, err := sg.atomicSnapshotsFromIssueAction(*a, blockHeight, info, txID, assetBalanceDiff) if err != nil { return nil, err } atomicSnapshots = append(atomicSnapshots, issueSnapshots...) - issuerAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) - if err != nil { - return nil, errors.Wrap(err, "failed to get an address from a public key") - } - assetBalanceDiff.appendOnlySender(issuerAddress, proto.AssetIDFromDigest(a.ID), a.Quantity) + case *proto.ReissueScriptAction: - reissueSnapshots, err := sg.atomicActionsFromReissueAction(*a) + reissueSnapshots, err := sg.atomicActionsFromReissueAction(*a, assetBalanceDiff) if err != nil { return nil, err } atomicSnapshots = append(atomicSnapshots, reissueSnapshots...) - issueAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) - if err != nil { - return nil, errors.Wrap(err, "failed to get an address from a public key") - } - assetBalanceDiff.appendOnlySender(issueAddress, proto.AssetIDFromDigest(a.AssetID), a.Quantity) - case *proto.BurnScriptAction: - burnSnapshots, err := sg.atomicActionsFromBurnAction(*a) + burnSnapshots, err := sg.atomicActionsFromBurnAction(*a, assetBalanceDiff) if err != nil { return nil, err } atomicSnapshots = append(atomicSnapshots, burnSnapshots...) - issueAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *a.Sender) - if err != nil { - return nil, errors.Wrap(err, "failed to get an address from a public key") - } - assetBalanceDiff.appendOnlySender(issueAddress, proto.AssetIDFromDigest(a.AssetID), -a.Quantity) case *proto.LeaseScriptAction: leaseSnapshots, err := sg.atomicActionsFromLeaseAction(*a, info, txID) if err != nil { diff --git a/pkg/state/snapshot_generator_test.go b/pkg/state/snapshot_generator_internal_test.go similarity index 99% rename from pkg/state/snapshot_generator_test.go rename to pkg/state/snapshot_generator_internal_test.go index ad8c0a086..6f7b3d454 100644 --- a/pkg/state/snapshot_generator_test.go +++ b/pkg/state/snapshot_generator_internal_test.go @@ -272,7 +272,7 @@ func TestDefaultBurnSnapshot(t *testing.T) { 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, testGlobal.issuerInfo.pk, "asset0"), blockID0) + false, 950, testGlobal.issuerInfo.pk, "asset0"), blockID0) assert.NoError(t, err, "failed to issue asset") err = to.stor.entities.balances.setWavesBalance(testGlobal.issuerInfo.addr.ID(), @@ -309,8 +309,8 @@ func TestDefaultBurnSnapshot(t *testing.T) { }, &AssetVolumeSnapshot{ AssetID: testGlobal.asset0.assetID, - TotalQuantity: *big.NewInt(int64(defaultQuantity - 50)), - IsReissuable: true, + TotalQuantity: *big.NewInt(int64(defaultQuantity - 100)), + IsReissuable: false, }, } From 0be06b382d581e04ec5221f3817519af9da63c2e Mon Sep 17 00:00:00 2001 From: esuwu Date: Sun, 13 Aug 2023 23:50:38 -0500 Subject: [PATCH 056/139] Fixed err shadowing --- pkg/state/fee_validation.go | 4 +++- pkg/state/scripts_complexity.go | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/state/fee_validation.go b/pkg/state/fee_validation.go index 3dea7d366..b0082b384 100644 --- a/pkg/state/fee_validation.go +++ b/pkg/state/fee_validation.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/ride" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/errs" @@ -264,7 +265,8 @@ func scriptsCost(tx proto.Transaction, params *feeValidationParams) (*txCosts, e // check complexity of script for free verifier if complexity <= 200 complexity := 0 if accountScripted && params.rideV5Activated { - treeEstimation, err := params.stor.scriptsComplexity.newestScriptComplexityByAddr(senderAddr, params.estimatorVersion) + var treeEstimation *ride.TreeEstimation + treeEstimation, err = params.stor.scriptsComplexity.newestScriptComplexityByAddr(senderAddr, params.estimatorVersion) if err != nil { return nil, errors.Errorf("failed to get complexity by addr from store, %v", err) } diff --git a/pkg/state/scripts_complexity.go b/pkg/state/scripts_complexity.go index e51f0c292..d2ece0f9b 100644 --- a/pkg/state/scripts_complexity.go +++ b/pkg/state/scripts_complexity.go @@ -48,7 +48,8 @@ func (sc *scriptsComplexity) originalEstimatorVersion(addr proto.Address) (int, return int(record.Version), nil } -func (sc *scriptsComplexity) newestOriginalScriptComplexityByAddr(addr proto.WavesAddress) (*ride.TreeEstimation, error) { +func (sc *scriptsComplexity) newestOriginalScriptComplexityByAddr( + addr proto.WavesAddress) (*ride.TreeEstimation, error) { ev, err := sc.originalEstimatorVersion(addr) if err != nil { return nil, err From 4518e13fb1ddf26084a96381a61518ac3d249a50 Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 16 Aug 2023 02:44:34 -0500 Subject: [PATCH 057/139] Fixed a mistake with issue counter --- pkg/state/appender.go | 7 ++++--- pkg/state/snapshot_generator.go | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index a07b29375..142dc1550 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -639,13 +639,14 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { if hasParent { checkerInfo.parentTimestamp = params.parent.Timestamp } - stateActionsCounterInBlock := new(proto.StateActionsCounter) + stateActionsCounterInBlockValidation := new(proto.StateActionsCounter) + stateActionsCounterInBlockSnapshots := new(proto.StateActionsCounter) snapshotApplier := newBlockSnapshotsApplier( blockSnapshotsApplierInfo{ ci: checkerInfo, scheme: a.settings.AddressSchemeCharacter, - stateActionsCounter: stateActionsCounterInBlock, + stateActionsCounter: stateActionsCounterInBlockSnapshots, }, snapshotApplierStorages{ balances: a.stor.balances, @@ -717,7 +718,7 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { blockRewardDistributionActivated: blockRewardDistributionActivated, invokeExpressionActivated: invokeExpressionActivated, validatingUtx: false, - stateActionsCounterInBlock: stateActionsCounterInBlock, + stateActionsCounterInBlock: stateActionsCounterInBlockValidation, currentMinerPK: params.block.GeneratorPublicKey, snapshotGenerator: &snapshotGenerator, snapshotApplier: &snapshotApplier, diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index 62a094fbd..59547c223 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -476,7 +476,7 @@ func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( issuer: *action.Sender, decimals: uint8(action.Decimals), issueHeight: blockHeight, - issueSequenceInBlock: info.stateActionsCounter.NextIssueActionNumber(), + issueSequenceInBlock: 0, }, assetChangeableInfo: assetChangeableInfo{ quantity: *big.NewInt(action.Quantity), From 8c0a424e73002a27dd028d19f0818c4d49cb5949 Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 16 Aug 2023 02:47:23 -0500 Subject: [PATCH 058/139] removed a useless line --- pkg/state/snapshot_generator.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index 59547c223..502ffaef3 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -472,11 +472,10 @@ func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( var atomicSnapshots []AtomicSnapshot assetInf := assetInfo{ assetConstInfo: assetConstInfo{ - tail: proto.DigestTail(action.ID), - issuer: *action.Sender, - decimals: uint8(action.Decimals), - issueHeight: blockHeight, - issueSequenceInBlock: 0, + tail: proto.DigestTail(action.ID), + issuer: *action.Sender, + decimals: uint8(action.Decimals), + issueHeight: blockHeight, }, assetChangeableInfo: assetChangeableInfo{ quantity: *big.NewInt(action.Quantity), From e6a2fdb43512dd7ae1e881d954c9146d8c03d797 Mon Sep 17 00:00:00 2001 From: esuwu Date: Tue, 22 Aug 2023 01:36:07 -0500 Subject: [PATCH 059/139] Fixed applying order transactions --- pkg/state/orders_volume.go | 6 ++++++ pkg/state/snapshot_applier.go | 3 ++- pkg/state/snapshot_generator.go | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pkg/state/orders_volume.go b/pkg/state/orders_volume.go index 39712eea8..4e8e91c6a 100644 --- a/pkg/state/orders_volume.go +++ b/pkg/state/orders_volume.go @@ -63,6 +63,7 @@ func (ov *ordersVolumes) addNewRecord(orderID []byte, record *orderVolumeRecord, return ov.hs.addNewEntry(ordersVolume, key.bytes(), recordBytes, blockID) } +// TODO remove it func (ov *ordersVolumes) increaseFilled(orderID []byte, amountChange, feeChange uint64, blockID proto.BlockID) error { prevVolume, err := ov.newestVolumeByID(orderID) if err != nil { @@ -76,6 +77,11 @@ func (ov *ordersVolumes) increaseFilled(orderID []byte, amountChange, feeChange return ov.addNewRecord(orderID, prevVolume, blockID) } +func (ov *ordersVolumes) storeFilled(orderID []byte, amountFilled, feeFilled uint64, blockID proto.BlockID) error { + newVolume := &orderVolumeRecord{amountFilled: amountFilled, feeFilled: feeFilled} + return ov.addNewRecord(orderID, newVolume, blockID) +} + func (ov *ordersVolumes) newestFilled(orderID []byte) (uint64, uint64, error) { volume, err := ov.newestVolumeByID(orderID) if err != nil { diff --git a/pkg/state/snapshot_applier.go b/pkg/state/snapshot_applier.go index e8a7a4e8b..4211225c1 100644 --- a/pkg/state/snapshot_applier.go +++ b/pkg/state/snapshot_applier.go @@ -210,8 +210,9 @@ func (a *blockSnapshotsApplier) ApplyAccountScript(snapshot AccountScriptSnapsho return a.stor.scriptsStorage.setAccountScript(addr, snapshot.Script, snapshot.SenderPublicKey, a.info.BlockID()) } +// TODO must be applied as it is and not just increased func (a *blockSnapshotsApplier) ApplyFilledVolumeAndFee(snapshot FilledVolumeFeeSnapshot) error { - return a.stor.ordersVolumes.increaseFilled(snapshot.OrderID.Bytes(), + return a.stor.ordersVolumes.storeFilled(snapshot.OrderID.Bytes(), snapshot.FilledVolume, snapshot.FilledFee, a.info.BlockID()) } diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index 502ffaef3..c82feb755 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -833,6 +833,7 @@ func (sg *snapshotGenerator) generateOrderAtomicSnapshot(orderID []byte, if err != nil { return nil, errors.Wrap(err, "failed to construct digest from order id bytes") } + // TODO must be added to newest filled amounts and fee orderSnapshot := &FilledVolumeFeeSnapshot{ OrderID: orderIDDigset, FilledFee: newestFilledFee + fee, From 1294e7b192330e33199fdc217e5f18a913161141 Mon Sep 17 00:00:00 2001 From: esuwu Date: Tue, 22 Aug 2023 01:36:29 -0500 Subject: [PATCH 060/139] Fixed applying order transactions --- pkg/state/snapshot_applier.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/state/snapshot_applier.go b/pkg/state/snapshot_applier.go index 4211225c1..f70d6e294 100644 --- a/pkg/state/snapshot_applier.go +++ b/pkg/state/snapshot_applier.go @@ -210,7 +210,6 @@ func (a *blockSnapshotsApplier) ApplyAccountScript(snapshot AccountScriptSnapsho return a.stor.scriptsStorage.setAccountScript(addr, snapshot.Script, snapshot.SenderPublicKey, a.info.BlockID()) } -// TODO must be applied as it is and not just increased func (a *blockSnapshotsApplier) ApplyFilledVolumeAndFee(snapshot FilledVolumeFeeSnapshot) error { return a.stor.ordersVolumes.storeFilled(snapshot.OrderID.Bytes(), snapshot.FilledVolume, snapshot.FilledFee, a.info.BlockID()) From 72b7f1dedd3d389b781faf61eb939022326b1fbf Mon Sep 17 00:00:00 2001 From: esuwu Date: Tue, 22 Aug 2023 03:45:26 -0500 Subject: [PATCH 061/139] Added lising snapshot to the tx diff generated group --- pkg/state/snapshot_types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go index 850f475f6..bed1c253f 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/state/snapshot_types.go @@ -96,7 +96,7 @@ type LeaseBalanceSnapshot struct { } func (s LeaseBalanceSnapshot) IsGeneratedByTxDiff() bool { - return false + return true } func (s LeaseBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseBalance(s) } From a54e8d375cec212a87a9807783a271f499f7c7d3 Mon Sep 17 00:00:00 2001 From: esuwu Date: Fri, 25 Aug 2023 02:18:21 -0500 Subject: [PATCH 062/139] Moved complexity saving into transaction performer --- pkg/state/fee_validation.go | 1 - pkg/state/snapshot_applier.go | 16 ++++++++-------- pkg/state/snapshot_generator.go | 3 --- pkg/state/transaction_checker.go | 3 --- pkg/state/transaction_performer.go | 29 ++++++++++++++++++----------- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/pkg/state/fee_validation.go b/pkg/state/fee_validation.go index 3b76b1d6b..0c96a9474 100644 --- a/pkg/state/fee_validation.go +++ b/pkg/state/fee_validation.go @@ -268,7 +268,6 @@ func scriptsCost(tx proto.Transaction, params *feeValidationParams) (*txCosts, e treeEstimation, err = params.stor.scriptsComplexity.newestScriptComplexityByAddr(senderWavesAddr) if err != nil { return nil, errors.Wrap(err, "failed to get complexity by addr from store") - } complexity = treeEstimation.Verifier } diff --git a/pkg/state/snapshot_applier.go b/pkg/state/snapshot_applier.go index 90b1e93e5..5375925ed 100644 --- a/pkg/state/snapshot_applier.go +++ b/pkg/state/snapshot_applier.go @@ -161,13 +161,13 @@ func (a *blockSnapshotsApplier) ApplyAssetVolume(snapshot AssetVolumeSnapshot) e } func (a *blockSnapshotsApplier) ApplyAssetScript(snapshot AssetScriptSnapshot) error { - //estimation := ride.TreeEstimation{ + // estimation := ride.TreeEstimation{ // Estimation: int(snapshot.Complexity), // Verifier: int(snapshot.Complexity), // Functions: nil, - //} + // } // TODO complexity is being saved in transaction_performer, we need to move to this place - //if err := a.stor.scriptsComplexity.saveComplexitiesForAsset( + // if err := a.stor.scriptsComplexity.saveComplexitiesForAsset( // snapshot.AssetID, estimation, a.info.BlockID()); err != nil { // return errors.Wrapf(err, "failed to store asset script estimation for asset %q", // snapshot.AssetID.String()) @@ -190,8 +190,8 @@ func (a *blockSnapshotsApplier) ApplyAccountScript(snapshot AccountScriptSnapsho return errors.Wrapf(err, "failed to create address from scheme %d and PK %q", a.info.Scheme(), snapshot.SenderPublicKey.String()) } - //var estimations treeEstimations - //if !snapshot.Script.IsEmpty() { + // var estimations treeEstimations + // if !snapshot.Script.IsEmpty() { // var tree *ast.Tree // tree, err = serialization.Parse(snapshot.Script) // if err != nil { @@ -201,10 +201,10 @@ func (a *blockSnapshotsApplier) ApplyAccountScript(snapshot AccountScriptSnapsho // if err != nil { // return errors.Wrapf(err, "failed to make account script estimations for addr %q", addr.String()) // } - //} - //if err = a.stor.scriptsComplexity.saveComplexitiesForAddr(addr, estimations, a.info.BlockID()); err != nil { + // } + // if err = a.stor.scriptsComplexity.saveComplexitiesForAddr(addr, estimations, a.info.BlockID()); err != nil { // return errors.Wrapf(err, "failed to store account script estimation for addr %q", addr.String()) - //} + // } return a.stor.scriptsStorage.setAccountScript(addr, snapshot.Script, snapshot.SenderPublicKey, a.info.BlockID()) } diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index 850c986c6..515f3cef7 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -336,9 +336,6 @@ func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Dig func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.PublicKey, script proto.Script, complexity int, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { diff --git a/pkg/state/transaction_checker.go b/pkg/state/transaction_checker.go index 9165ff945..bd0ca928e 100644 --- a/pkg/state/transaction_checker.go +++ b/pkg/state/transaction_checker.go @@ -183,9 +183,6 @@ func (tc *transactionChecker) checkDAppCallables(tree *ast.Tree, rideV6Activated return nil } -// TODO remove it -//type treeEstimations map[int]ride.TreeEstimation - func (tc *transactionChecker) checkScript( script proto.Script, estimatorVersion int, diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 87e3631ea..87049851f 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -434,6 +434,13 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra if !se.isPresent() { return nil, errors.New("script estimations must be set for SetScriptWithProofs tx") } + senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) + if err != nil { + return nil, errors.Wrapf(err, "failed to create addr from PK %q", tx.SenderPK.String()) + } + if setErr := tp.stor.scriptsComplexity.saveComplexitiesForAddr(senderAddr, *se, info.blockID); setErr != nil { + return nil, errors.Wrapf(setErr, "failed to save script complexities for addr %q", senderAddr.String()) + } snapshot, err := tp.snapshotGenerator.generateSnapshotForSetScriptTx(tx.SenderPK, tx.Script, se.estimation.Verifier, balanceChanges) @@ -444,6 +451,7 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra return snapshot, snapshot.Apply(tp.snapshotApplier) } +// TODO used only in tests func storeScriptByAddress( stor *blockchainEntitiesStorage, scheme proto.Scheme, @@ -459,14 +467,14 @@ func storeScriptByAddress( if setErr := stor.scriptsStorage.setAccountScript(senderAddr, script, senderPK, blockID); setErr != nil { return errors.Wrapf(setErr, "failed to set account script on addr %q", senderAddr.String()) } - // Save complexity to storage, so we won't have to calculate it every time the script is called. if setErr := stor.scriptsComplexity.saveComplexitiesForAddr(senderAddr, se, blockID); setErr != nil { return errors.Wrapf(setErr, "failed to save script complexities for addr %q", senderAddr.String()) } return nil } -func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction proto.Transaction, + info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { tx, ok := transaction.(*proto.SetAssetScriptWithProofs) if !ok { return nil, errors.New("failed to convert interface to SetAssetScriptWithProofs transaction") @@ -476,20 +484,19 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot if !se.isPresent() { return nil, errors.New("script estimations must be set for SetAssetScriptWithProofs tx") } - - snapshot, err := tp.snapshotGenerator.generateSnapshotForSetAssetScriptTx(tx.AssetID, - tx.Script, se.estimation.Verifier, tx.SenderPK, balanceChanges) + senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { - return nil, err + return nil, errors.Wrapf(err, "failed to create addr from PK %q", tx.SenderPK.String()) } - if !se.isPresent() { - return nil, errors.New("script estimations must be set for SetScriptWithProofs tx") + // Save complexity to storage, so we won't have to calculate it every time the script is called. + if setErr := tp.stor.scriptsComplexity.saveComplexitiesForAddr(senderAddr, *se, info.blockID); setErr != nil { + return nil, errors.Wrapf(setErr, "failed to save script complexities for addr %q", senderAddr.String()) } - // script estimation is present and not nil - err = storeScriptByAddress(tp.stor, tp.settings.AddressSchemeCharacter, tx.SenderPK, tx.Script, *se, info.blockID) + snapshot, err := tp.snapshotGenerator.generateSnapshotForSetAssetScriptTx(tx.AssetID, + tx.Script, se.estimation.Verifier, tx.SenderPK, balanceChanges) if err != nil { - return nil, errors.Wrapf(err, "failed to perform SetScriptWithProofs tx %q", tx.ID.String()) + return nil, err } return snapshot, snapshot.Apply(tp.snapshotApplier) From 45f05e5f7c23c16f3006d42d9fc6fc9b26b82cbb Mon Sep 17 00:00:00 2001 From: esuwu Date: Fri, 25 Aug 2023 02:18:28 -0500 Subject: [PATCH 063/139] Moved complexity saving into transaction performer --- itests/node_client/node_client.go | 37 ++++++++++++++++++++++++++++--- pkg/proto/types.go | 8 +++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/itests/node_client/node_client.go b/itests/node_client/node_client.go index e167227ef..976df7602 100644 --- a/itests/node_client/node_client.go +++ b/itests/node_client/node_client.go @@ -98,10 +98,41 @@ func (c *NodesClients) WaitForStateHashEquality(t *testing.T) { } c.WaitForNewHeight(t) } + + if !equal && goStateHash.FieldsHashes.EqualWith(scalaStateHash.FieldsHashes) { + var firstHeight int64 = -1 + for height := h; height > 0; height-- { + goStateHash, scalaStateHash, equal = c.StateHashCmp(t, height) + if !goStateHash.FieldsHashes.EqualWith(scalaStateHash.FieldsHashes) { + firstHeight = int64(height) + } + } + if firstHeight == -1 { + t.Errorf("couldn't find the height when state hashes diverged. should not happen") + } + goStateHashDiverged, scalaStateHashDiverged, _ := c.StateHashCmp(t, uint64(firstHeight)) + goFieldHashesDiverged, err := goStateHashDiverged.FieldsHashes.MarshalJSON() + assert.NoError(t, err) + scalaFieldHashesDiverged, err := scalaStateHashDiverged.FieldsHashes.MarshalJSON() + assert.NoError(t, err) + + t.Logf("First height when state hashes diverged: "+ + "%d:\nGo:\tBlockID=%s\tStateHash=%s\tFieldHashes=%s\n"+ + "Scala:\tBlockID=%s\tStateHash=%s\tFieldHashes=%s", + firstHeight, goStateHashDiverged.BlockID.String(), goStateHashDiverged.SumHash.String(), goFieldHashesDiverged, + scalaStateHashDiverged.BlockID.String(), scalaStateHashDiverged.SumHash.String(), scalaFieldHashesDiverged) + } + + goFieldHashes, err := goStateHash.FieldsHashes.MarshalJSON() + assert.NoError(t, err) + scalaFieldHashes, err := scalaStateHash.FieldsHashes.MarshalJSON() + assert.NoError(t, err) + assert.True(t, equal, - "Not equal state hash at height %d:\nGo:\tBlockID=%s\tStateHash=%s\nScala:\tBlockID=%s\tStateHash=%s", - h, goStateHash.BlockID.String(), goStateHash.SumHash.String(), - scalaStateHash.BlockID.String(), scalaStateHash.SumHash.String()) + "Not equal state hash at height %d:\nGo:\tBlockID=%s\tStateHash=%s\tFieldHashes=%s\n"+ + "Scala:\tBlockID=%s\tStateHash=%s\tFieldHashes=%s", + h, goStateHash.BlockID.String(), goStateHash.SumHash.String(), goFieldHashes, + scalaStateHash.BlockID.String(), scalaStateHash.SumHash.String(), scalaFieldHashes) } func Retry(timeout time.Duration, f func() error) error { diff --git a/pkg/proto/types.go b/pkg/proto/types.go index 8b225b061..597cc9017 100644 --- a/pkg/proto/types.go +++ b/pkg/proto/types.go @@ -4021,6 +4021,14 @@ type FieldsHashes struct { LeaseBalanceHash crypto.Digest } +func (s FieldsHashes) EqualWith(other FieldsHashes) bool { + return s.DataEntryHash == other.DataEntryHash && s.AccountScriptHash == other.AccountScriptHash && + s.AssetScriptHash == other.AssetScriptHash && s.LeaseStatusHash == other.LeaseStatusHash && + s.SponsorshipHash == other.SponsorshipHash && s.AliasesHash == other.AliasesHash && + s.WavesBalanceHash == other.WavesBalanceHash && s.AssetBalanceHash == other.AssetBalanceHash && + s.LeaseBalanceHash == other.LeaseBalanceHash +} + type fieldsHashesJS struct { DataEntryHash DigestWrapped `json:"dataEntryHash"` AccountScriptHash DigestWrapped `json:"accountScriptHash"` From f8793968c3609333112d9cbd71cb48b20e959208 Mon Sep 17 00:00:00 2001 From: esuwu Date: Fri, 25 Aug 2023 02:25:35 -0500 Subject: [PATCH 064/139] removed a line --- pkg/state/snapshot_generator.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index 515f3cef7..8642b116d 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -336,12 +336,10 @@ func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Dig func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.PublicKey, script proto.Script, complexity int, balanceChanges txDiff) (TransactionSnapshot, error) { - snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - sponsorshipSnapshot := &AccountScriptSnapshot{ SenderPublicKey: senderPK, Script: script, From 94c6a4a2eeba3dc712985605f6454086af9aa6a3 Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 30 Aug 2023 03:57:03 -0500 Subject: [PATCH 065/139] Fixed a bug with an empty sender --- pkg/state/snapshot_generator.go | 136 ++++++++++++++++------------- pkg/state/transaction_performer.go | 30 ++++--- 2 files changed, 94 insertions(+), 72 deletions(-) diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index 8642b116d..95e6aa958 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -367,18 +367,21 @@ func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto. } func (sg *snapshotGenerator) generateSnapshotForInvokeScriptTx(txID crypto.Digest, info *performerInfo, - invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { - return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges) + invocationRes *invocationResult, balanceChanges txDiff, + txPublicKey crypto.PublicKey) (TransactionSnapshot, error) { + return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges, txPublicKey) } func (sg *snapshotGenerator) generateSnapshotForInvokeExpressionTx(txID crypto.Digest, info *performerInfo, - invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { - return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges) + invocationRes *invocationResult, balanceChanges txDiff, + txPublicKey crypto.PublicKey) (TransactionSnapshot, error) { + return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges, txPublicKey) } func (sg *snapshotGenerator) generateSnapshotForEthereumInvokeScriptTx(txID crypto.Digest, info *performerInfo, - invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { - return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges) + invocationRes *invocationResult, balanceChanges txDiff, + txPublicKey crypto.PublicKey) (TransactionSnapshot, error) { + return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges, txPublicKey) } func (sg *snapshotGenerator) generateSnapshotForUpdateAssetInfoTx(assetID crypto.Digest, assetName string, @@ -400,20 +403,17 @@ func (sg *snapshotGenerator) generateSnapshotForUpdateAssetInfoTx(assetID crypto type SenderDataEntries map[proto.WavesAddress]proto.DataEntries func (senderDataEntries SenderDataEntries) collectEntryFromAction( - action proto.DataEntryScriptAction, scheme proto.Scheme) error { + action proto.DataEntryScriptAction, + sender proto.WavesAddress) error { if senderDataEntries == nil { return errors.New("senderDataEntries map is not initialized") } - senderAddr, err := proto.NewAddressFromPublicKey(scheme, *action.Sender) - if err != nil { - return err - } - if _, ok := senderDataEntries[senderAddr]; ok { - entries := senderDataEntries[senderAddr] + if _, ok := senderDataEntries[sender]; ok { + entries := senderDataEntries[sender] entries = append(entries, action.Entry) - senderDataEntries[senderAddr] = entries + senderDataEntries[sender] = entries } else { - senderDataEntries[senderAddr] = proto.DataEntries{action.Entry} + senderDataEntries[sender] = proto.DataEntries{action.Entry} } return nil } @@ -422,20 +422,17 @@ func (sg *snapshotGenerator) updateBalanceDiffFromPaymentAction( action proto.AttachedPaymentScriptAction, wavesBalanceDiff addressWavesBalanceDiff, assetBalanceDiff addressAssetBalanceDiff, + sender proto.WavesAddress, ) error { - senderAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *action.Sender) - if err != nil { - return errors.Wrap(err, "failed to get an address from a public key") - } recipientAddress, err := recipientToAddress(action.Recipient, sg.stor.aliases) if err != nil { return errors.Wrap(err, "failed to apply attached payment") } // No balance validation done below if action.Asset.Present { // Update asset balance - assetBalanceDiff.append(senderAddress, recipientAddress, proto.AssetIDFromDigest(action.Asset.ID), action.Amount) + assetBalanceDiff.append(sender, recipientAddress, proto.AssetIDFromDigest(action.Asset.ID), action.Amount) } else { // Update Waves balance - wavesBalanceDiff.append(senderAddress, recipientAddress, action.Amount) + wavesBalanceDiff.append(sender, recipientAddress, action.Amount) } return nil } @@ -444,20 +441,17 @@ func (sg *snapshotGenerator) updateBalanceDiffFromTransferAction( action proto.TransferScriptAction, wavesBalanceDiff addressWavesBalanceDiff, assetBalanceDiff addressAssetBalanceDiff, + sender proto.WavesAddress, ) error { - senderAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *action.Sender) - if err != nil { - return errors.Wrap(err, "failed to get an address from a public key") - } recipientAddress, err := recipientToAddress(action.Recipient, sg.stor.aliases) if err != nil { return errors.Wrap(err, "failed to apply attached payment") } // No balance validation done below if action.Asset.Present { // Update asset balance - assetBalanceDiff.append(senderAddress, recipientAddress, proto.AssetIDFromDigest(action.Asset.ID), action.Amount) + assetBalanceDiff.append(sender, recipientAddress, proto.AssetIDFromDigest(action.Asset.ID), action.Amount) } else { // Update Waves balance - wavesBalanceDiff.append(senderAddress, recipientAddress, action.Amount) + wavesBalanceDiff.append(sender, recipientAddress, action.Amount) } return nil } @@ -467,12 +461,13 @@ func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( blockHeight uint64, info *performerInfo, txID crypto.Digest, - assetBalanceDiff addressAssetBalanceDiff) ([]AtomicSnapshot, error) { + assetBalanceDiff addressAssetBalanceDiff, + senderPK crypto.PublicKey) ([]AtomicSnapshot, error) { var atomicSnapshots []AtomicSnapshot assetInf := assetInfo{ assetConstInfo: assetConstInfo{ tail: proto.DigestTail(action.ID), - issuer: *action.Sender, + issuer: senderPK, decimals: uint8(action.Decimals), issueHeight: blockHeight, }, @@ -487,7 +482,7 @@ func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( issueStaticInfoSnapshot := &StaticAssetInfoSnapshot{ AssetID: action.ID, - IssuerPublicKey: *action.Sender, + IssuerPublicKey: senderPK, SourceTransactionID: txID, Decimals: assetInf.decimals, IsNFT: assetInf.isNFT(), @@ -525,7 +520,7 @@ func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( } atomicSnapshots = append(atomicSnapshots, issueStaticInfoSnapshot, assetDescription, assetReissuability) - issuerAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *action.Sender) + issuerAddress, err := proto.NewAddressFromPublicKey(sg.scheme, senderPK) if err != nil { return nil, errors.Wrap(err, "failed to get an address from a public key") } @@ -535,7 +530,8 @@ func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( func (sg *snapshotGenerator) atomicActionsFromReissueAction( action proto.ReissueScriptAction, - assetBalanceDiff addressAssetBalanceDiff) ([]AtomicSnapshot, error) { + assetBalanceDiff addressAssetBalanceDiff, + issuer proto.WavesAddress) ([]AtomicSnapshot, error) { var atomicSnapshots []AtomicSnapshot assetInf, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(action.AssetID)) if err != nil { @@ -548,18 +544,15 @@ func (sg *snapshotGenerator) atomicActionsFromReissueAction( TotalQuantity: *resQuantity, IsReissuable: action.Reissuable, } - issueAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *action.Sender) - if err != nil { - return nil, errors.Wrap(err, "failed to get an address from a public key") - } - assetBalanceDiff.appendOnlySender(issueAddress, proto.AssetIDFromDigest(action.AssetID), action.Quantity) + assetBalanceDiff.appendOnlySender(issuer, proto.AssetIDFromDigest(action.AssetID), action.Quantity) atomicSnapshots = append(atomicSnapshots, assetReissuability) return atomicSnapshots, nil } func (sg *snapshotGenerator) atomicActionsFromBurnAction( action proto.BurnScriptAction, - assetBalanceDiff addressAssetBalanceDiff) ([]AtomicSnapshot, error) { + assetBalanceDiff addressAssetBalanceDiff, + issuer proto.WavesAddress) ([]AtomicSnapshot, error) { var atomicSnapshots []AtomicSnapshot var assetInf *assetInfo assetInf, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(action.AssetID)) @@ -574,23 +567,18 @@ func (sg *snapshotGenerator) atomicActionsFromBurnAction( IsReissuable: assetInf.reissuable, } atomicSnapshots = append(atomicSnapshots, assetReissuability) - issueAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *action.Sender) - if err != nil { - return nil, errors.Wrap(err, "failed to get an address from a public key") - } - assetBalanceDiff.appendOnlySender(issueAddress, proto.AssetIDFromDigest(action.AssetID), -action.Quantity) + assetBalanceDiff.appendOnlySender(issuer, proto.AssetIDFromDigest(action.AssetID), -action.Quantity) return atomicSnapshots, nil } func (sg *snapshotGenerator) atomicActionsFromLeaseAction( action proto.LeaseScriptAction, info *performerInfo, - txID crypto.Digest) ([]AtomicSnapshot, error) { + txID crypto.Digest, + sender proto.WavesAddress) ([]AtomicSnapshot, error) { var atomicSnapshots []AtomicSnapshot - senderAddress, err := proto.NewAddressFromPublicKey(sg.scheme, *action.Sender) - if err != nil { - return nil, err - } + + var err error var recipientAddr proto.WavesAddress if addr := action.Recipient.Address(); addr == nil { recipientAddr, err = sg.stor.aliases.newestAddrByAlias(action.Recipient.Alias().Alias) @@ -601,7 +589,7 @@ func (sg *snapshotGenerator) atomicActionsFromLeaseAction( recipientAddr = *addr } l := &leasing{ - Sender: senderAddress, + Sender: sender, Recipient: recipientAddr, Amount: uint64(action.Amount), Height: info.height, @@ -609,7 +597,7 @@ func (sg *snapshotGenerator) atomicActionsFromLeaseAction( } var amount = int64(l.Amount) leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := - sg.generateLeaseAtomicSnapshots(action.ID, *l, txID, senderAddress, recipientAddr, amount) + sg.generateLeaseAtomicSnapshots(action.ID, *l, txID, sender, recipientAddr, amount) if err != nil { return nil, errors.Wrap(err, "failed to generate snapshots for a lease action") } @@ -651,22 +639,24 @@ func (sg *snapshotGenerator) collectBalanceAndSnapshotFromAction( blockHeight uint64, info *performerInfo, txID crypto.Digest, + senderAddress proto.WavesAddress, + senderPK crypto.PublicKey, ) ([]AtomicSnapshot, error) { var atomicSnapshots []AtomicSnapshot switch a := action.(type) { case *proto.DataEntryScriptAction: // snapshots store data entries in a different format, so we convert the actions to this format - err := dataEntries.collectEntryFromAction(*a, sg.scheme) + err := dataEntries.collectEntryFromAction(*a, senderAddress) if err != nil { return nil, err } case *proto.AttachedPaymentScriptAction: - err := sg.updateBalanceDiffFromPaymentAction(*a, wavesBalanceDiff, assetBalanceDiff) + err := sg.updateBalanceDiffFromPaymentAction(*a, wavesBalanceDiff, assetBalanceDiff, senderAddress) if err != nil { return nil, err } case *proto.TransferScriptAction: - err := sg.updateBalanceDiffFromTransferAction(*a, wavesBalanceDiff, assetBalanceDiff) + err := sg.updateBalanceDiffFromTransferAction(*a, wavesBalanceDiff, assetBalanceDiff, senderAddress) if err != nil { return nil, err } @@ -677,26 +667,26 @@ func (sg *snapshotGenerator) collectBalanceAndSnapshotFromAction( } atomicSnapshots = append(atomicSnapshots, sponsorshipSnapshot) case *proto.IssueScriptAction: - issueSnapshots, err := sg.atomicSnapshotsFromIssueAction(*a, blockHeight, info, txID, assetBalanceDiff) + issueSnapshots, err := sg.atomicSnapshotsFromIssueAction(*a, blockHeight, info, txID, assetBalanceDiff, senderPK) if err != nil { return nil, err } atomicSnapshots = append(atomicSnapshots, issueSnapshots...) case *proto.ReissueScriptAction: - reissueSnapshots, err := sg.atomicActionsFromReissueAction(*a, assetBalanceDiff) + reissueSnapshots, err := sg.atomicActionsFromReissueAction(*a, assetBalanceDiff, senderAddress) if err != nil { return nil, err } atomicSnapshots = append(atomicSnapshots, reissueSnapshots...) case *proto.BurnScriptAction: - burnSnapshots, err := sg.atomicActionsFromBurnAction(*a, assetBalanceDiff) + burnSnapshots, err := sg.atomicActionsFromBurnAction(*a, assetBalanceDiff, senderAddress) if err != nil { return nil, err } atomicSnapshots = append(atomicSnapshots, burnSnapshots...) case *proto.LeaseScriptAction: - leaseSnapshots, err := sg.atomicActionsFromLeaseAction(*a, info, txID) + leaseSnapshots, err := sg.atomicActionsFromLeaseAction(*a, info, txID, senderAddress) if err != nil { return nil, err } @@ -713,18 +703,41 @@ func (sg *snapshotGenerator) collectBalanceAndSnapshotFromAction( return atomicSnapshots, nil } +func senderFromScriptAction(a proto.ScriptAction, txPublicKey crypto.PublicKey, + scheme proto.Scheme) (proto.WavesAddress, crypto.PublicKey, error) { + senderPK := txPublicKey + senderAddress, err := proto.NewAddressFromPublicKey(scheme, senderPK) + if err != nil { + return proto.WavesAddress{}, crypto.PublicKey{}, err + } + if a.SenderPK() != nil { + senderPK = *a.SenderPK() + senderAddress, err = proto.NewAddressFromPublicKey(scheme, senderPK) + if err != nil { + return proto.WavesAddress{}, crypto.PublicKey{}, err + } + } + return senderAddress, senderPK, nil +} + func (sg *snapshotGenerator) atomicSnapshotsFromScriptActions( actions []proto.ScriptAction, wavesBalanceDiff addressWavesBalanceDiff, assetBalanceDiff addressAssetBalanceDiff, blockHeight uint64, info *performerInfo, - txID crypto.Digest) ([]AtomicSnapshot, error) { + txID crypto.Digest, + txPublicKey crypto.PublicKey) ([]AtomicSnapshot, error) { var dataEntries = make(SenderDataEntries) var atomicSnapshots []AtomicSnapshot for _, action := range actions { + senderAddress, senderPK, err := senderFromScriptAction(action, txPublicKey, sg.scheme) + if err != nil { + return nil, err + } snapshotsFromAction, err := sg.collectBalanceAndSnapshotFromAction(action, dataEntries, - wavesBalanceDiff, assetBalanceDiff, blockHeight, info, txID) + wavesBalanceDiff, assetBalanceDiff, blockHeight, + info, txID, senderAddress, senderPK) if err != nil { return nil, err } @@ -742,7 +755,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff, txPublicKey crypto.PublicKey) (TransactionSnapshot, error) { blockHeight := info.height + 1 addrWavesBalanceDiff, addrAssetBalanceDiff, err := balanceDiffFromTxDiff(balanceChanges, sg.scheme) @@ -754,7 +767,8 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( var atomicSnapshots []AtomicSnapshot atomicSnapshots, err = sg.atomicSnapshotsFromScriptActions( invocationRes.actions, addrWavesBalanceDiff, - addrAssetBalanceDiff, blockHeight, info, txID) + addrAssetBalanceDiff, blockHeight, info, txID, + txPublicKey) if err != nil { return nil, errors.Wrap(err, "failed to generate atomic snapshots from script actions") } diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 87049851f..5df8259d7 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -539,7 +539,8 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. return nil, err } - snapshot, err := tp.snapshotGenerator.generateSnapshotForInvokeScriptTx(txID, info, invocationRes, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForInvokeScriptTx(txID, info, + invocationRes, balanceChanges, tx.SenderPK) if err != nil { return nil, err } @@ -549,7 +550,8 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { - if _, ok := transaction.(*proto.InvokeExpressionTransactionWithProofs); !ok { + tx, ok := transaction.(*proto.InvokeExpressionTransactionWithProofs) + if !ok { return nil, errors.New("failed to convert interface to InvokeExpressionWithProofs transaction") } @@ -562,7 +564,8 @@ func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction pr return nil, err } - snapshot, err := tp.snapshotGenerator.generateSnapshotForInvokeExpressionTx(txID, info, invocationRes, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForInvokeExpressionTx(txID, info, invocationRes, + balanceChanges, tx.SenderPK) if err != nil { return nil, err } @@ -575,12 +578,7 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction if !ok { return nil, errors.New("failed to convert interface to EthereumTransaction transaction") } - if _, ok := ethTx.TxKind.(*proto.EthereumInvokeScriptTxKind); ok { - // TODO remove? - 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", err) @@ -589,9 +587,19 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction if err != nil { return nil, err } - + scriptAddr, err := ethTx.WavesAddressTo(tp.settings.AddressSchemeCharacter) + if err != nil { + return nil, err + } + var si scriptBasicInfoRecord + si, err = tp.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()) + } + scriptPK := si.PK snapshot, err := tp.snapshotGenerator.generateSnapshotForEthereumInvokeScriptTx(txID, - info, invocationRes, balanceChanges) + info, invocationRes, balanceChanges, scriptPK) if err != nil { return nil, err } From aa537ae8cf616f138b272b2c92f2c799b336446a Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 30 Aug 2023 04:07:37 -0500 Subject: [PATCH 066/139] Used error.Is --- cmd/wmd/wmd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/wmd/wmd.go b/cmd/wmd/wmd.go index 39cf6d514..e1ce12a52 100644 --- a/cmd/wmd/wmd.go +++ b/cmd/wmd/wmd.go @@ -69,7 +69,7 @@ func run() error { logger := logging.SetupSimpleLogger(*logLevel) defer func() { err := logger.Sync() - if err != nil && err == os.ErrInvalid { + if err != nil && errors.Is(err, os.ErrInvalid) { panic(fmt.Sprintf("Failed to close logging subsystem: %v\n", err)) } }() From 3bc1592f669b5ee60b5e3a620a088dddd6c33fe8 Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 6 Sep 2023 02:51:08 -0500 Subject: [PATCH 067/139] Set an empty script for issue with sig --- pkg/state/transaction_performer.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 5df8259d7..85e95ad59 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -135,7 +135,9 @@ func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transactio if err != nil { return nil, err } - + if err := tp.stor.scriptsStorage.setAssetScript(assetID, proto.Script{}, tx.SenderPK, info.blockID); err != nil { + return nil, err + } return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges, nil) } From 6c5619d0c7c362186d3509bb3b348e8d647e0102 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Thu, 21 Sep 2023 11:11:15 +0300 Subject: [PATCH 068/139] add light node states --- cmd/node/node.go | 6 +- go.sum | 38 ++++ pkg/node/actions_by_type.go | 57 +++-- pkg/node/fsm/fsm.go | 20 +- pkg/node/fsm/ng_light_state.go | 143 +++++++++++++ pkg/node/fsm/wait_snapshot_state.go | 84 ++++++++ pkg/node/metrics.go | 24 +++ pkg/node/node.go | 5 +- pkg/node/snapshot_applier/snapshot_applier.go | 25 +++ pkg/proto/proto.go | 199 ++++++++++++++++-- 10 files changed, 560 insertions(+), 41 deletions(-) create mode 100644 pkg/node/fsm/ng_light_state.go create mode 100644 pkg/node/fsm/wait_snapshot_state.go create mode 100644 pkg/node/snapshot_applier/snapshot_applier.go diff --git a/cmd/node/node.go b/cmd/node/node.go index 416d7173b..e80a17942 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -108,6 +108,7 @@ type config struct { newConnectionsLimit int disableNTP bool microblockInterval time.Duration + enableLightMode bool } func (c *config) logParameters() { @@ -143,6 +144,7 @@ func (c *config) logParameters() { zap.S().Debugf("enable-metamask: %t", c.enableMetaMaskAPI) zap.S().Debugf("disable-ntp: %t", c.disableNTP) zap.S().Debugf("microblock-interval: %s", c.microblockInterval) + zap.S().Debugf("enable-light-mode: %t", c.enableLightMode) } func (c *config) parse() { @@ -232,6 +234,8 @@ func (c *config) parse() { "Disable NTP synchronization. Useful when running the node in a docker container.") flag.DurationVar(&c.microblockInterval, "microblock-interval", defaultMicroblockInterval, "Interval between microblocks.") + flag.BoolVar(&c.enableLightMode, "enable-light-mode", false, + "Start node in light mode (disable mining and store only snapshots)") flag.Parse() c.logLevel = *l } @@ -491,7 +495,7 @@ func main() { ntw, networkInfoCh := network.NewNetwork(svs, parent, nc.obsolescencePeriod) go ntw.Run(ctx) - n := node.NewNode(svs, declAddr, bindAddr, nc.microblockInterval) + n := node.NewNode(svs, declAddr, bindAddr, nc.microblockInterval, nc.enableLightMode) go n.Run(ctx, parent, svs.InternalChannel, networkInfoCh, ntw.SyncPeer()) go minerScheduler.Reschedule() diff --git a/go.sum b/go.sum index 61b1b8736..58429f367 100644 --- a/go.sum +++ b/go.sum @@ -23,6 +23,8 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= @@ -46,15 +48,18 @@ github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2y github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/apmckinlay/gsuneido v0.0.0-20190404155041-0b6cd442a18f/go.mod h1:JU2DOj5Fc6rol0yaT79Csr47QR0vONGwJtBNGRD7jmc= github.com/beevik/ntp v1.3.0 h1:/w5VhpW5BGKS37vFm1p9oVk/t4HnnkKZAZIubHM6F7Q= github.com/beevik/ntp v1.3.0/go.mod h1:vD6h1um4kzXpqmLTuu0cCLcC+NfvC0IC+ltmEDA8E78= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -66,9 +71,11 @@ github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= @@ -76,12 +83,15 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= @@ -104,6 +114,7 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 h1:BS21ZUJ/B5X2UVUbczfmdWH7GapPWAhxcMsDnjJTU1E= @@ -124,7 +135,9 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= github.com/ericlagergren/decimal v0.0.0-20210307182354-5f8425a47c58 h1:+Ct3FisijQso/lJt1zGGl0eIcFCoM0dozj4tiPJamqw= github.com/ericlagergren/decimal v0.0.0-20210307182354-5f8425a47c58/go.mod h1:ZWP59etEywfyMG2lAqnoi3t8uoiZCiTmLtwt6iESIsQ= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= @@ -140,11 +153,14 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-redis/redis/v8 v8.4.2/go.mod h1:A1tbYoHSa1fXwN+//ljcCYYJeLmVrwL9hbQN45Jdy0M= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= @@ -154,6 +170,7 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -202,6 +219,7 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -225,6 +243,7 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -242,18 +261,23 @@ github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef/go.mod h1:lADxMC39cJ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab h1:HqW4xhhynfjrtEiiSGcQUd6vrK23iMam1FO8rI7mwig= github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -262,10 +286,13 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= @@ -287,10 +314,12 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -315,6 +344,7 @@ github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnz github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc= github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -368,6 +398,7 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -428,6 +459,7 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17 github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xenolf/lego v2.7.2+incompatible h1:aGxxYqhnQLQ71HsvEAjJVw6ao14APwPpRk0mpFroPXk= github.com/xenolf/lego v2.7.2+incompatible/go.mod h1:fwiGnfsIjG7OHPfOvgK7Y/Qo6+2Ox0iozjNTkZICKbY= +github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -447,6 +479,7 @@ go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -560,6 +593,7 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -791,6 +825,8 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= +google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM= google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -831,6 +867,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= @@ -853,6 +890,7 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo= +gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/pkg/node/actions_by_type.go b/pkg/node/actions_by_type.go index b447c9fe9..f812f4fd2 100644 --- a/pkg/node/actions_by_type.go +++ b/pkg/node/actions_by_type.go @@ -255,23 +255,48 @@ func PBTransactionAction(_ services.Services, mess peer.ProtoMessage, fsm *fsm.F return fsm.Transaction(mess.ID, t) } +func MicroSnapshotRequestAction(_ services.Services, mess peer.ProtoMessage, fsm *fsm.FSM) (fsm.Async, error) { + metricMicroSnapshotRequestMessage.Inc() +} + +func GetSnapshotAction(services services.Services, mess peer.ProtoMessage, fsm *fsm.FSM) (fsm.Async, error) { + metricGetSnapshotMessage.Inc() + block, err := services.State.Block(mess.Message.(*proto.GetBlockMessage).BlockID) + if err != nil { + return nil, nil + } + bm, err := proto.MessageByBlock(block, services.Scheme) + if err != nil { + return nil, nil + } + mess.ID.SendMessage(bm) + return nil, nil +} + +func SnapshotAction(_ services.Services, mess peer.ProtoMessage, fsm *fsm.FSM) (fsm.Async, error) { + metricSnapshotMessage.Inc() // TODO(anton): maybe remove some metrics for snapshot +} + func createActions() map[reflect.Type]Action { return map[reflect.Type]Action{ - reflect.TypeOf(&proto.ScoreMessage{}): ScoreAction, - reflect.TypeOf(&proto.GetPeersMessage{}): GetPeersAction, - reflect.TypeOf(&proto.PeersMessage{}): PeersAction, - reflect.TypeOf(&proto.BlockMessage{}): BlockAction, - reflect.TypeOf(&proto.GetBlockMessage{}): GetBlockAction, - reflect.TypeOf(&proto.SignaturesMessage{}): SignaturesAction, - reflect.TypeOf(&proto.GetSignaturesMessage{}): GetSignaturesAction, - reflect.TypeOf(&proto.MicroBlockInvMessage{}): MicroBlockInvAction, - reflect.TypeOf(&proto.MicroBlockRequestMessage{}): MicroBlockRequestAction, - reflect.TypeOf(&proto.MicroBlockMessage{}): MicroBlockAction, - reflect.TypeOf(&proto.PBBlockMessage{}): PBBlockAction, - reflect.TypeOf(&proto.PBMicroBlockMessage{}): PBMicroBlockAction, - reflect.TypeOf(&proto.GetBlockIdsMessage{}): GetBlockIdsAction, - reflect.TypeOf(&proto.BlockIdsMessage{}): BlockIdsAction, - reflect.TypeOf(&proto.TransactionMessage{}): TransactionAction, - reflect.TypeOf(&proto.PBTransactionMessage{}): PBTransactionAction, + reflect.TypeOf(&proto.ScoreMessage{}): ScoreAction, + reflect.TypeOf(&proto.GetPeersMessage{}): GetPeersAction, + reflect.TypeOf(&proto.PeersMessage{}): PeersAction, + reflect.TypeOf(&proto.BlockMessage{}): BlockAction, + reflect.TypeOf(&proto.GetBlockMessage{}): GetBlockAction, + reflect.TypeOf(&proto.SignaturesMessage{}): SignaturesAction, + reflect.TypeOf(&proto.GetSignaturesMessage{}): GetSignaturesAction, + reflect.TypeOf(&proto.MicroBlockInvMessage{}): MicroBlockInvAction, + reflect.TypeOf(&proto.MicroBlockRequestMessage{}): MicroBlockRequestAction, + reflect.TypeOf(&proto.MicroBlockMessage{}): MicroBlockAction, + reflect.TypeOf(&proto.PBBlockMessage{}): PBBlockAction, + reflect.TypeOf(&proto.PBMicroBlockMessage{}): PBMicroBlockAction, + reflect.TypeOf(&proto.GetBlockIdsMessage{}): GetBlockIdsAction, + reflect.TypeOf(&proto.BlockIdsMessage{}): BlockIdsAction, + reflect.TypeOf(&proto.TransactionMessage{}): TransactionAction, + reflect.TypeOf(&proto.PBTransactionMessage{}): PBTransactionAction, + reflect.TypeOf(&proto.GetBlockSnapshotMessage{}): GetSnapshotAction, + reflect.TypeOf(&proto.MicroBlockSnapshotRequestMessage{}): MicroSnapshotRequestAction, + reflect.TypeOf(&proto.BlockSnapshotMessage{}): SnapshotAction, } } diff --git a/pkg/node/fsm/fsm.go b/pkg/node/fsm/fsm.go index c656e1d1f..5ab48f8f3 100644 --- a/pkg/node/fsm/fsm.go +++ b/pkg/node/fsm/fsm.go @@ -2,6 +2,7 @@ package fsm import ( "context" + "github.com/wavesplatform/gowaves/pkg/node/snapshot_applier" "time" "github.com/pkg/errors" @@ -41,10 +42,11 @@ type BaseInfo struct { // ntp time tm types.Time - scheme proto.Scheme - invRequester InvRequester - blocksApplier BlocksApplier - obsolescence time.Duration + scheme proto.Scheme + invRequester InvRequester + blocksApplier BlocksApplier + snapshotApplier *snapshot_applier.SnapshotApplier + obsolescence time.Duration // scheduler scheduler types.Scheduler @@ -63,6 +65,8 @@ type BaseInfo struct { skipMessageList *messages.SkipMessageList syncPeer *network.SyncPeer + + enableLightMode bool } func (a *BaseInfo) BroadcastTransaction(t proto.Transaction, receivedFrom peer.Peer) { @@ -81,6 +85,7 @@ func (a *BaseInfo) CleanUtx() { const ( IdleStateName = "Idle" NGStateName = "NG" + NGLightStateName = "NGLight" PersistStateName = "Persist" SyncStateName = "Sync" HaltStateName = "Halt" @@ -127,6 +132,7 @@ func NewFSM( services services.Services, microblockInterval, obsolescence time.Duration, syncPeer *network.SyncPeer, + enableLightMode bool, ) (*FSM, Async, error) { if microblockInterval <= 0 { return nil, nil, errors.New("microblock interval must be positive") @@ -139,8 +145,9 @@ func NewFSM( obsolescence: obsolescence, // - invRequester: ng.NewInvRequester(), - blocksApplier: services.BlocksApplier, + invRequester: ng.NewInvRequester(), + blocksApplier: services.BlocksApplier, + snapshotApplier: snapshot_applier.NewSnapshotApplier(), scheduler: services.Scheduler, @@ -158,6 +165,7 @@ func NewFSM( skipMessageList: services.SkipMessageList, syncPeer: syncPeer, + enableLightMode: enableLightMode, } info.scheduler.Reschedule() diff --git a/pkg/node/fsm/ng_light_state.go b/pkg/node/fsm/ng_light_state.go new file mode 100644 index 000000000..4a7d3049c --- /dev/null +++ b/pkg/node/fsm/ng_light_state.go @@ -0,0 +1,143 @@ +package fsm + +import ( + "context" + "github.com/pkg/errors" + "github.com/qmuntal/stateless" + "github.com/wavesplatform/gowaves/pkg/node/fsm/tasks" + "github.com/wavesplatform/gowaves/pkg/p2p/peer" + "github.com/wavesplatform/gowaves/pkg/proto" +) + +type NGLightState struct { + baseInfo BaseInfo + blockCache *blockStatesCache +} + +func newNGLightState(baseInfo BaseInfo) State { + baseInfo.syncPeer.Clear() + return &NGLightState{ + baseInfo: baseInfo, + } +} + +func (a *NGLightState) Errorf(err error) error { + return fsmErrorf(a, err) +} + +func (a *NGLightState) String() string { + return NGLightStateName +} + +func (a *NGLightState) Block(peer peer.Peer, block *proto.Block) (State, Async, error) { + return NewWaitSnapshotState(a.baseInfo, a.blockCache).Block(peer, block) +} + +func initNGLightStateInFSM(state *StateData, fsm *stateless.StateMachine, info BaseInfo) { + ngLightSkipMessageList := proto.PeerMessageIDs{ + proto.ContentIDSignatures, + proto.ContentIDBlock, + proto.ContentIDTransaction, + proto.ContentIDInvMicroblock, + proto.ContentIDCheckpoint, + proto.ContentIDMicroblockRequest, + proto.ContentIDMicroblock, + proto.ContentIDPBBlock, + proto.ContentIDPBMicroBlock, + proto.ContentIDPBTransaction, + proto.ContentIDBlockIds, + } + fsm.Configure(NGLightStateName). + SubstateOf(NGStateName). + OnEntry(func(ctx context.Context, args ...interface{}) error { + info.skipMessageList.SetList(ngLightSkipMessageList) + return nil + }). + Ignore(BlockIDsEvent). + Ignore(StartMiningEvent). + Ignore(ChangeSyncPeerEvent). + Ignore(StopSyncEvent). + PermitDynamic(StopMiningEvent, + createPermitDynamicCallback(StopMiningEvent, state, func(args ...interface{}) (State, Async, error) { + a, ok := state.State.(*NGState) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type '%T' expected '*NGState'", state.State)) + } + return a.StopMining() + })). + PermitDynamic(TransactionEvent, + createPermitDynamicCallback(TransactionEvent, state, func(args ...interface{}) (State, Async, error) { + a, ok := state.State.(*NGState) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type '%T' expected '*NGState'", state.State)) + } + return a.Transaction(convertToInterface[peer.Peer](args[0]), + convertToInterface[proto.Transaction](args[1])) + })). + PermitDynamic(TaskEvent, + createPermitDynamicCallback(TaskEvent, state, func(args ...interface{}) (State, Async, error) { + a, ok := state.State.(*NGState) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type '%T' expected '*NGState'", state.State)) + } + return a.Task(args[0].(tasks.AsyncTask)) + })). + PermitDynamic(ScoreEvent, + createPermitDynamicCallback(ScoreEvent, state, func(args ...interface{}) (State, Async, error) { + a, ok := state.State.(*NGState) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type '%T' expected '*NGState'", state.State)) + } + return a.Score(convertToInterface[peer.Peer](args[0]), args[1].(*proto.Score)) + })). + PermitDynamic(BlockEvent, + createPermitDynamicCallback(BlockEvent, state, func(args ...interface{}) (State, Async, error) { + a, ok := state.State.(*NGState) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type '%T' expected '*NGState'", state.State)) + } + return a.Block(convertToInterface[peer.Peer](args[0]), args[1].(*proto.Block)) + })). + PermitDynamic(MinedBlockEvent, + createPermitDynamicCallback(MinedBlockEvent, state, func(args ...interface{}) (State, Async, error) { + a, ok := state.State.(*NGState) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type '%T' expected '*NGState'", state.State)) + } + return a.MinedBlock(args[0].(*proto.Block), args[1].(proto.MiningLimits), + args[2].(proto.KeyPair), args[3].([]byte)) + })). + PermitDynamic(MicroBlockEvent, + createPermitDynamicCallback(MicroBlockEvent, state, func(args ...interface{}) (State, Async, error) { + a, ok := state.State.(*NGState) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type '%T' expected '*NGState'", state.State)) + } + return a.MicroBlock(convertToInterface[peer.Peer](args[0]), args[1].(*proto.MicroBlock)) + })). + PermitDynamic(MicroBlockInvEvent, + createPermitDynamicCallback(MicroBlockInvEvent, state, func(args ...interface{}) (State, Async, error) { + a, ok := state.State.(*NGState) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type '%T' expected '*NGState'", state.State)) + } + return a.MicroBlockInv(convertToInterface[peer.Peer](args[0]), args[1].(*proto.MicroBlockInv)) + })). + PermitDynamic(HaltEvent, + createPermitDynamicCallback(HaltEvent, state, func(args ...interface{}) (State, Async, error) { + a, ok := state.State.(*NGState) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type '%T' expected '*NGState'", state.State)) + } + return a.Halt() + })) +} diff --git a/pkg/node/fsm/wait_snapshot_state.go b/pkg/node/fsm/wait_snapshot_state.go new file mode 100644 index 000000000..72f598557 --- /dev/null +++ b/pkg/node/fsm/wait_snapshot_state.go @@ -0,0 +1,84 @@ +package fsm + +import ( + "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/logging" + "github.com/wavesplatform/gowaves/pkg/metrics" + "github.com/wavesplatform/gowaves/pkg/p2p/peer" + "github.com/wavesplatform/gowaves/pkg/proto" + "github.com/wavesplatform/gowaves/pkg/state" + "go.uber.org/zap" +) + +type WaitSnapshotState struct { + baseInfo BaseInfo + blockCache *blockStatesCache +} + +func NewWaitSnapshotState(baseInfo BaseInfo, blockCache *blockStatesCache) *WaitSnapshotState { + baseInfo.syncPeer.Clear() + return &WaitSnapshotState{ + baseInfo: baseInfo, + blockCache: blockCache, + } +} + +func (a *WaitSnapshotState) Errorf(err error) error { + return fsmErrorf(a, err) +} + +func (a *WaitSnapshotState) String() string { + return NGLightStateName +} + +func (a *WaitSnapshotState) Block(peer peer.Peer, block *proto.Block) (State, Async, error) { + ok, err := a.baseInfo.snapshotApplier.BlockSnapshotExists(a.baseInfo.storage, block.BlockID()) + if err != nil { + return a, nil, a.Errorf(errors.Wrapf(err, "peer '%s'", peer.ID())) + } + if ok { + return a, nil, a.Errorf(proto.NewInfoMsg(errors.Errorf("Block '%s' already exists", block.BlockID().String()))) + } + //metrics.FSMKeyBlockReceived("ng", block, peer.Handshake().NodeName) + + top := a.baseInfo.storage.TopBlock() + if top.BlockID() != block.Parent { // does block refer to last block + zap.S().Named(logging.FSMNamespace).Debugf( + "[%s] Key-block '%s' has parent '%s' which is not the top block '%s'", + a, block.ID.String(), block.Parent.String(), top.ID.String(), + ) + var blockFromCache *proto.Block + if blockFromCache, ok = a.blockCache.Get(block.Parent); ok { + zap.S().Named(logging.FSMNamespace).Debugf("[%s] Re-applying block '%s' from cache", + a, blockFromCache.ID.String()) + if err = a.rollbackToStateFromCache(blockFromCache); err != nil { + return a, nil, a.Errorf(err) + } + } + } + a.blockCache.Clear() + a.blockCache.AddBlockState(block) +} + +func (a *WaitSnapshotState) BlockSnapshot(peer peer.Peer, blockID proto.BlockID, snapshots state.TransactionSnapshot) (State, Async, error) { + // check if this snapshot for our block + if _, ok := a.blockCache.Get(blockID); !ok { + return newNGLightState(a.baseInfo), nil, a.Errorf(errors.Errorf("Snapshot for the block '%s' doestn match", blockID)) + } + + _, err := a.baseInfo.snapshotApplier.Apply(a.baseInfo.storage, []state.TransactionSnapshot{snapshots}, []proto.BlockID{blockID}) + if err != nil { + //metrics.FSMKeyBlockDeclined("ng", block, err) + return a, nil, a.Errorf(errors.Wrapf(err, "peer '%s'", peer.ID())) + } + + metrics.FSMKeyBlockApplied("ng", block) + zap.S().Named(logging.FSMNamespace).Debugf("[%s] Handle received key block message: block '%s' applied to state", + a, block.BlockID()) + + a.baseInfo.scheduler.Reschedule() + a.baseInfo.actions.SendScore(a.baseInfo.storage) + a.baseInfo.CleanUtx() + + return newNGLightState(a.baseInfo), nil, nil +} diff --git a/pkg/node/metrics.go b/pkg/node/metrics.go index 58587c4d4..5777c5ade 100644 --- a/pkg/node/metrics.go +++ b/pkg/node/metrics.go @@ -41,6 +41,30 @@ var metricGetBlockMessage = prometheus.NewCounter( }, ) +var metricGetSnapshotMessage = prometheus.NewCounter( + prometheus.CounterOpts{ + Namespace: "messages", + Name: "get_snapshot", + Help: "Counter of GetSnapshot message.", + }, +) + +var metricMicroSnapshotRequestMessage = prometheus.NewCounter( + prometheus.CounterOpts{ + Namespace: "messages", + Name: "micro_snapshot_request", + Help: "Counter of MicroSnapshotRequest message.", + }, +) + +var metricSnapshotMessage = prometheus.NewCounter( + prometheus.CounterOpts{ + Namespace: "messages", + Name: "snapshot", + Help: "Counter of Snapshot message.", + }, +) + func init() { prometheus.MustRegister(metricInternalChannelSize) prometheus.MustRegister(metricPeersMessage) diff --git a/pkg/node/node.go b/pkg/node/node.go index b3118d374..e50c6aa63 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -47,10 +47,12 @@ type Node struct { services services.Services microblockInterval time.Duration obsolescence time.Duration + enableLightMode bool } func NewNode( services services.Services, declAddr proto.TCPAddr, bindAddr proto.TCPAddr, microblockInterval time.Duration, + enableLightMode bool, ) *Node { if bindAddr.Empty() { bindAddr = declAddr @@ -64,6 +66,7 @@ func NewNode( utx: services.UtxPool, services: services, microblockInterval: microblockInterval, + enableLightMode: enableLightMode, } } @@ -148,7 +151,7 @@ func (a *Node) Run( tasksCh := make(chan tasks.AsyncTask, 10) // TODO: Consider using context `ctx` in FSM, for now FSM works in the background context. - m, async, err := fsm.NewFSM(a.services, a.microblockInterval, a.obsolescence, syncPeer) + m, async, err := fsm.NewFSM(a.services, a.microblockInterval, a.obsolescence, syncPeer, a.enableLightMode) if err != nil { zap.S().Errorf("Failed to create FSM: %v", err) return diff --git a/pkg/node/snapshot_applier/snapshot_applier.go b/pkg/node/snapshot_applier/snapshot_applier.go new file mode 100644 index 000000000..842d1f1d8 --- /dev/null +++ b/pkg/node/snapshot_applier/snapshot_applier.go @@ -0,0 +1,25 @@ +package snapshot_applier + +import ( + "github.com/wavesplatform/gowaves/pkg/proto" + "github.com/wavesplatform/gowaves/pkg/state" +) + +type SnapshotApplier struct { +} + +func NewSnapshotApplier() *SnapshotApplier { + return &SnapshotApplier{} +} + +func (a *SnapshotApplier) BlockSnapshotExists(state state.State, blockID proto.BlockID) (bool, error) { + return true, nil +} + +func (a *SnapshotApplier) Apply(state state.State, snapshots []state.TransactionSnapshot, block []proto.BlockID) (proto.Height, error) { + return 0, nil +} + +func (a *SnapshotApplier) ApplyMicro(state state.State, snapshots []state.TransactionSnapshot, block []proto.BlockID) (proto.Height, error) { + return 0, nil +} diff --git a/pkg/proto/proto.go b/pkg/proto/proto.go index 2c9faf878..bccf870da 100644 --- a/pkg/proto/proto.go +++ b/pkg/proto/proto.go @@ -5,6 +5,7 @@ import ( "encoding" "encoding/binary" "fmt" + "github.com/wavesplatform/gowaves/pkg/state" "io" "net" "strconv" @@ -33,23 +34,27 @@ type ( // Constants for message IDs const ( - ContentIDGetPeers PeerMessageID = 0x1 - ContentIDPeers PeerMessageID = 0x2 - ContentIDGetSignatures PeerMessageID = 0x14 - ContentIDSignatures PeerMessageID = 0x15 - ContentIDGetBlock PeerMessageID = 0x16 - ContentIDBlock PeerMessageID = 0x17 - ContentIDScore PeerMessageID = 0x18 - ContentIDTransaction PeerMessageID = 0x19 - ContentIDInvMicroblock PeerMessageID = 0x1A - ContentIDCheckpoint PeerMessageID = 0x64 - ContentIDMicroblockRequest PeerMessageID = 27 - ContentIDMicroblock PeerMessageID = 28 - ContentIDPBBlock PeerMessageID = 29 - ContentIDPBMicroBlock PeerMessageID = 30 - ContentIDPBTransaction PeerMessageID = 31 - ContentIDGetBlockIds PeerMessageID = 32 - ContentIDBlockIds PeerMessageID = 33 + ContentIDGetPeers PeerMessageID = 0x1 + ContentIDPeers PeerMessageID = 0x2 + ContentIDGetSignatures PeerMessageID = 0x14 + ContentIDSignatures PeerMessageID = 0x15 + ContentIDGetBlock PeerMessageID = 0x16 + ContentIDBlock PeerMessageID = 0x17 + ContentIDScore PeerMessageID = 0x18 + ContentIDTransaction PeerMessageID = 0x19 + ContentIDInvMicroblock PeerMessageID = 0x1A + ContentIDCheckpoint PeerMessageID = 0x64 + ContentIDMicroblockRequest PeerMessageID = 27 + ContentIDMicroblock PeerMessageID = 28 + ContentIDPBBlock PeerMessageID = 29 + ContentIDPBMicroBlock PeerMessageID = 30 + ContentIDPBTransaction PeerMessageID = 31 + ContentIDGetBlockIds PeerMessageID = 32 + ContentIDBlockIds PeerMessageID = 33 + ContentIDGetBlockSnapshot PeerMessageID = 34 + ContentIDMicroBlockSnapshotRequest PeerMessageID = 35 + ContentIDBlockSnapshot PeerMessageID = 36 + ContentIDMicroBlockSnapshot PeerMessageID = 37 ) var ProtocolVersion = NewVersion(1, 4, 0) @@ -1809,6 +1814,12 @@ func UnmarshalMessage(b []byte) (Message, error) { m = &GetBlockIdsMessage{} case ContentIDBlockIds: m = &BlockIdsMessage{} + case ContentIDGetBlockSnapshot: + m = &GetBlockSnapshotMessage{} + case ContentIDMicroBlockSnapshotRequest: + m = &MicroBlockSnapshotRequestMessage{} + case ContentIDBlockSnapshot: + m = &BlockSnapshotMessage{} default: return nil, errors.Errorf( "received unknown content id byte %d 0x%x", b[HeaderContentIDPosition], b[HeaderContentIDPosition]) @@ -2044,3 +2055,157 @@ type MiningLimits struct { ClassicAmountOfTxsInBlock int MaxTxsSizeInBytes int } + +type GetBlockSnapshotMessage struct { + BlockID BlockID +} + +func (m *GetBlockSnapshotMessage) ReadFrom(r io.Reader) (int64, error) { + packet, nn, err := readPacket(r) + if err != nil { + return nn, err + } + + return nn, m.UnmarshalBinary(packet) +} + +func (m *GetBlockSnapshotMessage) WriteTo(w io.Writer) (int64, error) { + buf, err := m.MarshalBinary() + if err != nil { + return 0, err + } + nn, err := w.Write(buf) + n := int64(nn) + return n, err +} + +func (m *GetBlockSnapshotMessage) UnmarshalBinary(data []byte) error { + return parsePacket(data, ContentIDGetBlockSnapshot, "GetBlockSnapshotMessage", func(payload []byte) error { + blockID, err := NewBlockIDFromBytes(payload) + if err != nil { + return err + } + m.BlockID = blockID + return nil + }) +} + +func (m *GetBlockSnapshotMessage) MarshalBinary() ([]byte, error) { + body := m.BlockID.Bytes() + + var h Header + h.Length = maxHeaderLength + uint32(len(body)) - 4 + h.Magic = headerMagic + h.ContentID = ContentIDGetBlockSnapshot + h.PayloadLength = uint32(len(body)) + dig, err := crypto.FastHash(body) + if err != nil { + return nil, err + } + copy(h.PayloadChecksum[:], dig[:4]) + + hdr, err := h.MarshalBinary() + if err != nil { + return nil, err + } + body = append(hdr, body...) + return body, nil +} + +type BlockSnapshotMessage struct { + BlockID BlockID + Snapshots state.TransactionSnapshot +} + +func (m *BlockSnapshotMessage) ReadFrom(_ io.Reader) (n int64, err error) { + panic("implement me") +} + +func (m *BlockSnapshotMessage) WriteTo(_ io.Writer) (n int64, err error) { + panic("implement me") +} + +func (m *BlockSnapshotMessage) UnmarshalBinary(_ []byte) error { + panic("implement me") +} + +func (m *BlockSnapshotMessage) MarshalBinary() (data []byte, err error) { + panic("ads") +} + +type MicroBlockSnapshotMessage struct { + BlockID BlockID + Snapshots state.TransactionSnapshot +} + +func (m *MicroBlockSnapshotMessage) ReadFrom(_ io.Reader) (n int64, err error) { + panic("implement me") +} + +func (m *MicroBlockSnapshotMessage) WriteTo(_ io.Writer) (n int64, err error) { + panic("implement me") +} + +func (m *MicroBlockSnapshotMessage) UnmarshalBinary(_ []byte) error { + panic("implement me") +} + +func (m *MicroBlockSnapshotMessage) MarshalBinary() (data []byte, err error) { + panic("ads") +} + +type MicroBlockSnapshotRequestMessage struct { + BlockID BlockID +} + +func (m *MicroBlockSnapshotRequestMessage) ReadFrom(r io.Reader) (int64, error) { + packet, nn, err := readPacket(r) + if err != nil { + return nn, err + } + + return nn, m.UnmarshalBinary(packet) +} + +func (m *MicroBlockSnapshotRequestMessage) WriteTo(w io.Writer) (int64, error) { + buf, err := m.MarshalBinary() + if err != nil { + return 0, err + } + nn, err := w.Write(buf) + n := int64(nn) + return n, err +} + +func (m *MicroBlockSnapshotRequestMessage) UnmarshalBinary(data []byte) error { + return parsePacket(data, ContentIDMicroBlockSnapshotRequest, "MicroBlockSnapshotRequestMessage", func(payload []byte) error { + blockID, err := NewBlockIDFromBytes(payload) + if err != nil { + return err + } + m.BlockID = blockID + return nil + }) +} + +func (m *MicroBlockSnapshotRequestMessage) MarshalBinary() ([]byte, error) { + body := m.BlockID.Bytes() + + var h Header + h.Length = maxHeaderLength + uint32(len(body)) - 4 + h.Magic = headerMagic + h.ContentID = ContentIDGetBlockSnapshot + h.PayloadLength = uint32(len(body)) + dig, err := crypto.FastHash(body) + if err != nil { + return nil, err + } + copy(h.PayloadChecksum[:], dig[:4]) + + hdr, err := h.MarshalBinary() + if err != nil { + return nil, err + } + body = append(hdr, body...) + return body, nil +} From 28fab469cd6b25b5991e780b73ead36f588d87f4 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Mon, 2 Oct 2023 21:48:23 +0300 Subject: [PATCH 069/139] add snapshot storage --- pkg/grpc/generated/waves/amount.pb.go | 2 +- pkg/grpc/generated/waves/block.pb.go | 286 +- pkg/grpc/generated/waves/block_vtproto.pb.go | 644 ++- pkg/grpc/generated/waves/events/events.pb.go | 1009 +++-- .../events/grpc/blockchain_updates.pb.go | 2 +- .../events/grpc/blockchain_updates_grpc.pb.go | 2 +- .../waves/invoke_script_result.pb.go | 2 +- .../waves/node/grpc/accounts_api.pb.go | 2 +- .../waves/node/grpc/accounts_api_grpc.pb.go | 2 +- .../waves/node/grpc/assets_api.pb.go | 59 +- .../waves/node/grpc/assets_api_grpc.pb.go | 2 +- .../waves/node/grpc/blockchain_api.pb.go | 2 +- .../waves/node/grpc/blockchain_api_grpc.pb.go | 2 +- .../waves/node/grpc/blocks_api.pb.go | 168 +- .../waves/node/grpc/blocks_api_grpc.pb.go | 2 +- .../waves/node/grpc/transactions_api.pb.go | 86 +- .../node/grpc/transactions_api_grpc.pb.go | 2 +- pkg/grpc/generated/waves/order.pb.go | 16 +- pkg/grpc/generated/waves/order_vtproto.pb.go | 45 + pkg/grpc/generated/waves/recipient.pb.go | 2 +- pkg/grpc/generated/waves/reward_share.pb.go | 157 + .../waves/reward_share_vtproto.pb.go | 185 + pkg/grpc/generated/waves/transaction.pb.go | 2 +- .../waves/transaction_state_snapshot.pb.go | 1583 +++++++ .../transaction_state_snapshot_vtproto.pb.go | 3784 +++++++++++++++++ pkg/grpc/protobuf-schemas | 2 +- pkg/mock/state.go | 31 + pkg/proto/snapshot_types.go | 400 ++ pkg/proto/types.go | 8 + pkg/ride/meta/generated/dapp_meta.pb.go | 2 +- pkg/state/api.go | 9 +- pkg/state/appender.go | 215 +- pkg/state/headers_validation_test.go | 17 + pkg/state/history_storage.go | 1 + pkg/state/invoke_applier.go | 2 +- pkg/state/keys.go | 16 + pkg/state/leases.go | 20 +- pkg/state/leases_test.go | 4 +- pkg/state/snapshot_applier.go | 28 +- pkg/state/snapshot_generator.go | 158 +- pkg/state/snapshot_generator_internal_test.go | 146 +- pkg/state/snapshot_storage.go | 42 + pkg/state/snapshot_storage_test.go | 29 + pkg/state/snapshot_types.go | 214 - pkg/state/state.go | 7 + pkg/state/threadsafe_wrapper.go | 7 + pkg/state/transaction_handler.go | 4 +- pkg/state/transaction_performer.go | 72 +- pkg/state/transaction_performer_test.go | 8 +- 49 files changed, 8311 insertions(+), 1179 deletions(-) create mode 100644 pkg/grpc/generated/waves/reward_share.pb.go create mode 100644 pkg/grpc/generated/waves/reward_share_vtproto.pb.go create mode 100644 pkg/grpc/generated/waves/transaction_state_snapshot.pb.go create mode 100644 pkg/grpc/generated/waves/transaction_state_snapshot_vtproto.pb.go create mode 100644 pkg/proto/snapshot_types.go create mode 100644 pkg/state/snapshot_storage.go create mode 100644 pkg/state/snapshot_storage_test.go delete mode 100644 pkg/state/snapshot_types.go diff --git a/pkg/grpc/generated/waves/amount.pb.go b/pkg/grpc/generated/waves/amount.pb.go index e5c81b873..a80c73614 100644 --- a/pkg/grpc/generated/waves/amount.pb.go +++ b/pkg/grpc/generated/waves/amount.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.21.12 +// protoc v4.24.3 // source: waves/amount.proto package waves diff --git a/pkg/grpc/generated/waves/block.pb.go b/pkg/grpc/generated/waves/block.pb.go index 0ba51372d..0249aa7e7 100644 --- a/pkg/grpc/generated/waves/block.pb.go +++ b/pkg/grpc/generated/waves/block.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.21.12 +// protoc v4.24.3 // source: waves/block.proto package waves @@ -93,6 +93,7 @@ type MicroBlock struct { UpdatedBlockSignature []byte `protobuf:"bytes,3,opt,name=updated_block_signature,json=updatedBlockSignature,proto3" json:"updated_block_signature,omitempty"` SenderPublicKey []byte `protobuf:"bytes,4,opt,name=sender_public_key,json=senderPublicKey,proto3" json:"sender_public_key,omitempty"` Transactions []*SignedTransaction `protobuf:"bytes,5,rep,name=transactions,proto3" json:"transactions,omitempty"` + StateHash []byte `protobuf:"bytes,6,opt,name=state_hash,json=stateHash,proto3" json:"state_hash,omitempty"` } func (x *MicroBlock) Reset() { @@ -162,6 +163,13 @@ func (x *MicroBlock) GetTransactions() []*SignedTransaction { return nil } +func (x *MicroBlock) GetStateHash() []byte { + if x != nil { + return x.StateHash + } + return nil +} + type SignedMicroBlock struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -230,16 +238,18 @@ type Block_Header struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ChainId int32 `protobuf:"varint,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` - Reference []byte `protobuf:"bytes,2,opt,name=reference,proto3" json:"reference,omitempty"` - BaseTarget int64 `protobuf:"varint,3,opt,name=base_target,json=baseTarget,proto3" json:"base_target,omitempty"` - GenerationSignature []byte `protobuf:"bytes,4,opt,name=generation_signature,json=generationSignature,proto3" json:"generation_signature,omitempty"` - FeatureVotes []uint32 `protobuf:"varint,5,rep,packed,name=feature_votes,json=featureVotes,proto3" json:"feature_votes,omitempty"` - Timestamp int64 `protobuf:"varint,6,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - Version int32 `protobuf:"varint,7,opt,name=version,proto3" json:"version,omitempty"` - Generator []byte `protobuf:"bytes,8,opt,name=generator,proto3" json:"generator,omitempty"` - RewardVote int64 `protobuf:"varint,9,opt,name=reward_vote,json=rewardVote,proto3" json:"reward_vote,omitempty"` - TransactionsRoot []byte `protobuf:"bytes,10,opt,name=transactions_root,json=transactionsRoot,proto3" json:"transactions_root,omitempty"` + ChainId int32 `protobuf:"varint,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + Reference []byte `protobuf:"bytes,2,opt,name=reference,proto3" json:"reference,omitempty"` + BaseTarget int64 `protobuf:"varint,3,opt,name=base_target,json=baseTarget,proto3" json:"base_target,omitempty"` + GenerationSignature []byte `protobuf:"bytes,4,opt,name=generation_signature,json=generationSignature,proto3" json:"generation_signature,omitempty"` + FeatureVotes []uint32 `protobuf:"varint,5,rep,packed,name=feature_votes,json=featureVotes,proto3" json:"feature_votes,omitempty"` + Timestamp int64 `protobuf:"varint,6,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Version int32 `protobuf:"varint,7,opt,name=version,proto3" json:"version,omitempty"` + Generator []byte `protobuf:"bytes,8,opt,name=generator,proto3" json:"generator,omitempty"` + RewardVote int64 `protobuf:"varint,9,opt,name=reward_vote,json=rewardVote,proto3" json:"reward_vote,omitempty"` + TransactionsRoot []byte `protobuf:"bytes,10,opt,name=transactions_root,json=transactionsRoot,proto3" json:"transactions_root,omitempty"` + StateHash []byte `protobuf:"bytes,11,opt,name=state_hash,json=stateHash,proto3" json:"state_hash,omitempty"` + ChallengedHeader *Block_Header_ChallengedHeader `protobuf:"bytes,12,opt,name=challenged_header,json=challengedHeader,proto3" json:"challenged_header,omitempty"` } func (x *Block_Header) Reset() { @@ -344,13 +354,130 @@ func (x *Block_Header) GetTransactionsRoot() []byte { return nil } +func (x *Block_Header) GetStateHash() []byte { + if x != nil { + return x.StateHash + } + return nil +} + +func (x *Block_Header) GetChallengedHeader() *Block_Header_ChallengedHeader { + if x != nil { + return x.ChallengedHeader + } + return nil +} + +type Block_Header_ChallengedHeader struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + BaseTarget int64 `protobuf:"varint,1,opt,name=base_target,json=baseTarget,proto3" json:"base_target,omitempty"` + GenerationSignature []byte `protobuf:"bytes,2,opt,name=generation_signature,json=generationSignature,proto3" json:"generation_signature,omitempty"` + FeatureVotes []uint32 `protobuf:"varint,3,rep,packed,name=feature_votes,json=featureVotes,proto3" json:"feature_votes,omitempty"` + Timestamp int64 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Generator []byte `protobuf:"bytes,5,opt,name=generator,proto3" json:"generator,omitempty"` + RewardVote int64 `protobuf:"varint,6,opt,name=reward_vote,json=rewardVote,proto3" json:"reward_vote,omitempty"` + StateHash []byte `protobuf:"bytes,7,opt,name=state_hash,json=stateHash,proto3" json:"state_hash,omitempty"` + HeaderSignature []byte `protobuf:"bytes,8,opt,name=header_signature,json=headerSignature,proto3" json:"header_signature,omitempty"` +} + +func (x *Block_Header_ChallengedHeader) Reset() { + *x = Block_Header_ChallengedHeader{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_block_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Block_Header_ChallengedHeader) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Block_Header_ChallengedHeader) ProtoMessage() {} + +func (x *Block_Header_ChallengedHeader) ProtoReflect() protoreflect.Message { + mi := &file_waves_block_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Block_Header_ChallengedHeader.ProtoReflect.Descriptor instead. +func (*Block_Header_ChallengedHeader) Descriptor() ([]byte, []int) { + return file_waves_block_proto_rawDescGZIP(), []int{0, 0, 0} +} + +func (x *Block_Header_ChallengedHeader) GetBaseTarget() int64 { + if x != nil { + return x.BaseTarget + } + return 0 +} + +func (x *Block_Header_ChallengedHeader) GetGenerationSignature() []byte { + if x != nil { + return x.GenerationSignature + } + return nil +} + +func (x *Block_Header_ChallengedHeader) GetFeatureVotes() []uint32 { + if x != nil { + return x.FeatureVotes + } + return nil +} + +func (x *Block_Header_ChallengedHeader) GetTimestamp() int64 { + if x != nil { + return x.Timestamp + } + return 0 +} + +func (x *Block_Header_ChallengedHeader) GetGenerator() []byte { + if x != nil { + return x.Generator + } + return nil +} + +func (x *Block_Header_ChallengedHeader) GetRewardVote() int64 { + if x != nil { + return x.RewardVote + } + return 0 +} + +func (x *Block_Header_ChallengedHeader) GetStateHash() []byte { + if x != nil { + return x.StateHash + } + return nil +} + +func (x *Block_Header_ChallengedHeader) GetHeaderSignature() []byte { + if x != nil { + return x.HeaderSignature + } + return nil +} + var File_waves_block_proto protoreflect.FileDescriptor var file_waves_block_proto_rawDesc = []byte{ 0x0a, 0x11, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x77, 0x61, 0x76, 0x65, 0x73, 0x1a, 0x17, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0xf1, 0x03, 0x0a, 0x05, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2b, 0x0a, + 0x6f, 0x74, 0x6f, 0x22, 0x98, 0x07, 0x0a, 0x05, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2b, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, @@ -359,7 +486,7 @@ var file_waves_block_proto_rawDesc = []byte{ 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0xde, 0x02, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x85, 0x06, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, @@ -381,37 +508,66 @@ var file_waves_block_proto_rawDesc = []byte{ 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x56, 0x6f, 0x74, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0xe6, 0x01, 0x0a, 0x0a, 0x4d, 0x69, 0x63, 0x72, - 0x6f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x09, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x36, - 0x0a, 0x17, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x15, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, - 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0f, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, - 0x65, 0x79, 0x12, 0x3c, 0x0a, 0x0c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, - 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x0c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x22, 0x8a, 0x01, 0x0a, 0x10, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4d, 0x69, 0x63, 0x72, 0x6f, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x32, 0x0a, 0x0b, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x5f, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x77, 0x61, 0x76, - 0x65, 0x73, 0x2e, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x0a, 0x6d, - 0x69, 0x63, 0x72, 0x6f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, - 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x0c, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x64, 0x42, 0x65, 0x0a, - 0x20, 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, - 0x72, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, - 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, - 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, - 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0xaa, 0x02, 0x05, 0x57, - 0x61, 0x76, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x6e, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x48, 0x61, 0x73, 0x68, 0x12, 0x51, 0x0a, 0x11, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, + 0x6e, 0x67, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, + 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x10, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, + 0x67, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0xb2, 0x02, 0x0a, 0x10, 0x43, 0x68, + 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x1f, + 0x0a, 0x0b, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0a, 0x62, 0x61, 0x73, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, + 0x31, 0x0a, 0x14, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x13, 0x67, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x76, 0x6f, + 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, 0x66, 0x65, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x56, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1c, 0x0a, 0x09, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, + 0x74, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x76, 0x6f, + 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, + 0x56, 0x6f, 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x68, 0x61, + 0x73, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x48, + 0x61, 0x73, 0x68, 0x12, 0x29, 0x0a, 0x10, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x85, + 0x02, 0x0a, 0x0a, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x18, 0x0a, + 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x72, 0x65, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, + 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x15, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x2a, 0x0a, + 0x11, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, + 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, + 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x3c, 0x0a, 0x0c, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x18, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x74, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x48, 0x61, 0x73, 0x68, 0x22, 0x8a, 0x01, 0x0a, 0x10, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x32, 0x0a, 0x0b, 0x6d, + 0x69, 0x63, 0x72, 0x6f, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x52, 0x0a, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, + 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x24, 0x0a, + 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x49, 0x64, 0x42, 0x65, 0x0a, 0x20, 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, + 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, + 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x77, 0x61, 0x76, + 0x65, 0x73, 0xaa, 0x02, 0x05, 0x57, 0x61, 0x76, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -426,24 +582,26 @@ func file_waves_block_proto_rawDescGZIP() []byte { return file_waves_block_proto_rawDescData } -var file_waves_block_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_waves_block_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_waves_block_proto_goTypes = []interface{}{ - (*Block)(nil), // 0: waves.Block - (*MicroBlock)(nil), // 1: waves.MicroBlock - (*SignedMicroBlock)(nil), // 2: waves.SignedMicroBlock - (*Block_Header)(nil), // 3: waves.Block.Header - (*SignedTransaction)(nil), // 4: waves.SignedTransaction + (*Block)(nil), // 0: waves.Block + (*MicroBlock)(nil), // 1: waves.MicroBlock + (*SignedMicroBlock)(nil), // 2: waves.SignedMicroBlock + (*Block_Header)(nil), // 3: waves.Block.Header + (*Block_Header_ChallengedHeader)(nil), // 4: waves.Block.Header.ChallengedHeader + (*SignedTransaction)(nil), // 5: waves.SignedTransaction } var file_waves_block_proto_depIdxs = []int32{ 3, // 0: waves.Block.header:type_name -> waves.Block.Header - 4, // 1: waves.Block.transactions:type_name -> waves.SignedTransaction - 4, // 2: waves.MicroBlock.transactions:type_name -> waves.SignedTransaction + 5, // 1: waves.Block.transactions:type_name -> waves.SignedTransaction + 5, // 2: waves.MicroBlock.transactions:type_name -> waves.SignedTransaction 1, // 3: waves.SignedMicroBlock.micro_block:type_name -> waves.MicroBlock - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 4, // 4: waves.Block.Header.challenged_header:type_name -> waves.Block.Header.ChallengedHeader + 5, // [5:5] is the sub-list for method output_type + 5, // [5:5] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_waves_block_proto_init() } @@ -501,6 +659,18 @@ func file_waves_block_proto_init() { return nil } } + file_waves_block_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Block_Header_ChallengedHeader); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -508,7 +678,7 @@ func file_waves_block_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_waves_block_proto_rawDesc, NumEnums: 0, - NumMessages: 4, + NumMessages: 5, NumExtensions: 0, NumServices: 0, }, diff --git a/pkg/grpc/generated/waves/block_vtproto.pb.go b/pkg/grpc/generated/waves/block_vtproto.pb.go index 2fe938802..2849a6751 100644 --- a/pkg/grpc/generated/waves/block_vtproto.pb.go +++ b/pkg/grpc/generated/waves/block_vtproto.pb.go @@ -17,6 +17,102 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +func (m *Block_Header_ChallengedHeader) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Block_Header_ChallengedHeader) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *Block_Header_ChallengedHeader) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.HeaderSignature) > 0 { + i -= len(m.HeaderSignature) + copy(dAtA[i:], m.HeaderSignature) + i = encodeVarint(dAtA, i, uint64(len(m.HeaderSignature))) + i-- + dAtA[i] = 0x42 + } + if len(m.StateHash) > 0 { + i -= len(m.StateHash) + copy(dAtA[i:], m.StateHash) + i = encodeVarint(dAtA, i, uint64(len(m.StateHash))) + i-- + dAtA[i] = 0x3a + } + if m.RewardVote != 0 { + i = encodeVarint(dAtA, i, uint64(m.RewardVote)) + i-- + dAtA[i] = 0x30 + } + if len(m.Generator) > 0 { + i -= len(m.Generator) + copy(dAtA[i:], m.Generator) + i = encodeVarint(dAtA, i, uint64(len(m.Generator))) + i-- + dAtA[i] = 0x2a + } + if m.Timestamp != 0 { + i = encodeVarint(dAtA, i, uint64(m.Timestamp)) + i-- + dAtA[i] = 0x20 + } + if len(m.FeatureVotes) > 0 { + var pksize2 int + for _, num := range m.FeatureVotes { + pksize2 += sov(uint64(num)) + } + i -= pksize2 + j1 := i + for _, num := range m.FeatureVotes { + for num >= 1<<7 { + dAtA[j1] = uint8(uint64(num)&0x7f | 0x80) + num >>= 7 + j1++ + } + dAtA[j1] = uint8(num) + j1++ + } + i = encodeVarint(dAtA, i, uint64(pksize2)) + i-- + dAtA[i] = 0x1a + } + if len(m.GenerationSignature) > 0 { + i -= len(m.GenerationSignature) + copy(dAtA[i:], m.GenerationSignature) + i = encodeVarint(dAtA, i, uint64(len(m.GenerationSignature))) + i-- + dAtA[i] = 0x12 + } + if m.BaseTarget != 0 { + i = encodeVarint(dAtA, i, uint64(m.BaseTarget)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func (m *Block_Header) MarshalVTStrict() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -47,6 +143,23 @@ func (m *Block_Header) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.ChallengedHeader != nil { + size, err := m.ChallengedHeader.MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x62 + } + if len(m.StateHash) > 0 { + i -= len(m.StateHash) + copy(dAtA[i:], m.StateHash) + i = encodeVarint(dAtA, i, uint64(len(m.StateHash))) + i-- + dAtA[i] = 0x5a + } if len(m.TransactionsRoot) > 0 { i -= len(m.TransactionsRoot) copy(dAtA[i:], m.TransactionsRoot) @@ -215,6 +328,13 @@ func (m *MicroBlock) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.StateHash) > 0 { + i -= len(m.StateHash) + copy(dAtA[i:], m.StateHash) + i = encodeVarint(dAtA, i, uint64(len(m.StateHash))) + i-- + dAtA[i] = 0x32 + } if len(m.Transactions) > 0 { for iNdEx := len(m.Transactions) - 1; iNdEx >= 0; iNdEx-- { size, err := m.Transactions[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i]) @@ -313,6 +433,48 @@ func (m *SignedMicroBlock) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error return len(dAtA) - i, nil } +func (m *Block_Header_ChallengedHeader) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BaseTarget != 0 { + n += 1 + sov(uint64(m.BaseTarget)) + } + l = len(m.GenerationSignature) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if len(m.FeatureVotes) > 0 { + l = 0 + for _, e := range m.FeatureVotes { + l += sov(uint64(e)) + } + n += 1 + sov(uint64(l)) + l + } + if m.Timestamp != 0 { + n += 1 + sov(uint64(m.Timestamp)) + } + l = len(m.Generator) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.RewardVote != 0 { + n += 1 + sov(uint64(m.RewardVote)) + } + l = len(m.StateHash) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.HeaderSignature) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + func (m *Block_Header) SizeVT() (n int) { if m == nil { return 0 @@ -357,6 +519,14 @@ func (m *Block_Header) SizeVT() (n int) { if l > 0 { n += 1 + l + sov(uint64(l)) } + l = len(m.StateHash) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.ChallengedHeader != nil { + l = m.ChallengedHeader.SizeVT() + n += 1 + l + sov(uint64(l)) + } n += len(m.unknownFields) return n } @@ -412,32 +582,356 @@ func (m *MicroBlock) SizeVT() (n int) { n += 1 + l + sov(uint64(l)) } } - n += len(m.unknownFields) - return n -} + l = len(m.StateHash) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *SignedMicroBlock) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.MicroBlock != nil { + l = m.MicroBlock.SizeVT() + n += 1 + l + sov(uint64(l)) + } + l = len(m.Signature) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.TotalBlockId) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *Block_Header_ChallengedHeader) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Block_Header_ChallengedHeader: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Block_Header_ChallengedHeader: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BaseTarget", wireType) + } + m.BaseTarget = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BaseTarget |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GenerationSignature", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.GenerationSignature = append(m.GenerationSignature[:0], dAtA[iNdEx:postIndex]...) + if m.GenerationSignature == nil { + m.GenerationSignature = []byte{} + } + iNdEx = postIndex + case 3: + if wireType == 0 { + var v uint32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.FeatureVotes = append(m.FeatureVotes, v) + } else if wireType == 2 { + var packedLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + packedLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + packedLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + var elementCount int + var count int + for _, integer := range dAtA[iNdEx:postIndex] { + if integer < 128 { + count++ + } + } + elementCount = count + if elementCount != 0 && len(m.FeatureVotes) == 0 { + m.FeatureVotes = make([]uint32, 0, elementCount) + } + for iNdEx < postIndex { + var v uint32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.FeatureVotes = append(m.FeatureVotes, v) + } + } else { + return fmt.Errorf("proto: wrong wireType = %d for field FeatureVotes", wireType) + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + m.Timestamp = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Timestamp |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Generator", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Generator = append(m.Generator[:0], dAtA[iNdEx:postIndex]...) + if m.Generator == nil { + m.Generator = []byte{} + } + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardVote", wireType) + } + m.RewardVote = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.RewardVote |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StateHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.StateHash = append(m.StateHash[:0], dAtA[iNdEx:postIndex]...) + if m.StateHash == nil { + m.StateHash = []byte{} + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HeaderSignature", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.HeaderSignature = append(m.HeaderSignature[:0], dAtA[iNdEx:postIndex]...) + if m.HeaderSignature == nil { + m.HeaderSignature = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } -func (m *SignedMicroBlock) SizeVT() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.MicroBlock != nil { - l = m.MicroBlock.SizeVT() - n += 1 + l + sov(uint64(l)) - } - l = len(m.Signature) - if l > 0 { - n += 1 + l + sov(uint64(l)) - } - l = len(m.TotalBlockId) - if l > 0 { - n += 1 + l + sov(uint64(l)) + if iNdEx > l { + return io.ErrUnexpectedEOF } - n += len(m.unknownFields) - return n + return nil } - func (m *Block_Header) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -774,6 +1268,76 @@ func (m *Block_Header) UnmarshalVT(dAtA []byte) error { m.TransactionsRoot = []byte{} } iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StateHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.StateHash = append(m.StateHash[:0], dAtA[iNdEx:postIndex]...) + if m.StateHash == nil { + m.StateHash = []byte{} + } + iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChallengedHeader", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ChallengedHeader == nil { + m.ChallengedHeader = &Block_Header_ChallengedHeader{} + } + if err := m.ChallengedHeader.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -1135,6 +1699,40 @@ func (m *MicroBlock) UnmarshalVT(dAtA []byte) error { return err } iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StateHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.StateHash = append(m.StateHash[:0], dAtA[iNdEx:postIndex]...) + if m.StateHash == nil { + m.StateHash = []byte{} + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) diff --git a/pkg/grpc/generated/waves/events/events.pb.go b/pkg/grpc/generated/waves/events/events.pb.go index 1b7f9c933..357a95314 100644 --- a/pkg/grpc/generated/waves/events/events.pb.go +++ b/pkg/grpc/generated/waves/events/events.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.21.12 +// protoc v4.24.3 // source: waves/events/events.proto package events @@ -228,6 +228,8 @@ type StateUpdate struct { DataEntries []*StateUpdate_DataEntryUpdate `protobuf:"bytes,3,rep,name=data_entries,json=dataEntries,proto3" json:"data_entries,omitempty"` Assets []*StateUpdate_AssetStateUpdate `protobuf:"bytes,4,rep,name=assets,proto3" json:"assets,omitempty"` IndividualLeases []*StateUpdate_LeaseUpdate `protobuf:"bytes,5,rep,name=individual_leases,json=individualLeases,proto3" json:"individual_leases,omitempty"` + Scripts []*StateUpdate_ScriptUpdate `protobuf:"bytes,6,rep,name=scripts,proto3" json:"scripts,omitempty"` + DeletedAliases []string `protobuf:"bytes,7,rep,name=deleted_aliases,json=deletedAliases,proto3" json:"deleted_aliases,omitempty"` } func (x *StateUpdate) Reset() { @@ -297,6 +299,20 @@ func (x *StateUpdate) GetIndividualLeases() []*StateUpdate_LeaseUpdate { return nil } +func (x *StateUpdate) GetScripts() []*StateUpdate_ScriptUpdate { + if x != nil { + return x.Scripts + } + return nil +} + +func (x *StateUpdate) GetDeletedAliases() []string { + if x != nil { + return x.DeletedAliases + } + return nil +} + type TransactionMetadata struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -564,6 +580,7 @@ type BlockchainUpdated_Rollback struct { RemovedTransactionIds [][]byte `protobuf:"bytes,2,rep,name=removed_transaction_ids,json=removedTransactionIds,proto3" json:"removed_transaction_ids,omitempty"` RemovedBlocks []*waves.Block `protobuf:"bytes,3,rep,name=removed_blocks,json=removedBlocks,proto3" json:"removed_blocks,omitempty"` RollbackStateUpdate *StateUpdate `protobuf:"bytes,4,opt,name=rollback_state_update,json=rollbackStateUpdate,proto3" json:"rollback_state_update,omitempty"` + DeactivatedFeatures []int32 `protobuf:"varint,5,rep,packed,name=deactivated_features,json=deactivatedFeatures,proto3" json:"deactivated_features,omitempty"` } func (x *BlockchainUpdated_Rollback) Reset() { @@ -626,13 +643,23 @@ func (x *BlockchainUpdated_Rollback) GetRollbackStateUpdate() *StateUpdate { return nil } +func (x *BlockchainUpdated_Rollback) GetDeactivatedFeatures() []int32 { + if x != nil { + return x.DeactivatedFeatures + } + return nil +} + type BlockchainUpdated_Append_BlockAppend struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Block *waves.Block `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` - UpdatedWavesAmount int64 `protobuf:"varint,2,opt,name=updated_waves_amount,json=updatedWavesAmount,proto3" json:"updated_waves_amount,omitempty"` + Block *waves.Block `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + UpdatedWavesAmount int64 `protobuf:"varint,2,opt,name=updated_waves_amount,json=updatedWavesAmount,proto3" json:"updated_waves_amount,omitempty"` + ActivatedFeatures []int32 `protobuf:"varint,3,rep,packed,name=activated_features,json=activatedFeatures,proto3" json:"activated_features,omitempty"` + Vrf []byte `protobuf:"bytes,4,opt,name=vrf,proto3" json:"vrf,omitempty"` + RewardShares []*waves.RewardShare `protobuf:"bytes,5,rep,name=reward_shares,json=rewardShares,proto3" json:"reward_shares,omitempty"` } func (x *BlockchainUpdated_Append_BlockAppend) Reset() { @@ -681,6 +708,27 @@ func (x *BlockchainUpdated_Append_BlockAppend) GetUpdatedWavesAmount() int64 { return 0 } +func (x *BlockchainUpdated_Append_BlockAppend) GetActivatedFeatures() []int32 { + if x != nil { + return x.ActivatedFeatures + } + return nil +} + +func (x *BlockchainUpdated_Append_BlockAppend) GetVrf() []byte { + if x != nil { + return x.Vrf + } + return nil +} + +func (x *BlockchainUpdated_Append_BlockAppend) GetRewardShares() []*waves.RewardShare { + if x != nil { + return x.RewardShares + } + return nil +} + type BlockchainUpdated_Append_MicroBlockAppend struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1088,17 +1136,19 @@ type StateUpdate_AssetDetails struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - AssetId []byte `protobuf:"bytes,1,opt,name=asset_id,json=assetId,proto3" json:"asset_id,omitempty"` - Issuer []byte `protobuf:"bytes,2,opt,name=issuer,proto3" json:"issuer,omitempty"` - Decimals int32 `protobuf:"varint,3,opt,name=decimals,proto3" json:"decimals,omitempty"` - Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"` - Description string `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"` - Reissuable bool `protobuf:"varint,6,opt,name=reissuable,proto3" json:"reissuable,omitempty"` - Volume int64 `protobuf:"varint,7,opt,name=volume,proto3" json:"volume,omitempty"` - ScriptInfo *StateUpdate_AssetDetails_AssetScriptInfo `protobuf:"bytes,8,opt,name=script_info,json=scriptInfo,proto3" json:"script_info,omitempty"` - Sponsorship int64 `protobuf:"varint,9,opt,name=sponsorship,proto3" json:"sponsorship,omitempty"` - Nft bool `protobuf:"varint,10,opt,name=nft,proto3" json:"nft,omitempty"` - LastUpdated int32 `protobuf:"varint,11,opt,name=last_updated,json=lastUpdated,proto3" json:"last_updated,omitempty"` + AssetId []byte `protobuf:"bytes,1,opt,name=asset_id,json=assetId,proto3" json:"asset_id,omitempty"` + Issuer []byte `protobuf:"bytes,2,opt,name=issuer,proto3" json:"issuer,omitempty"` + Decimals int32 `protobuf:"varint,3,opt,name=decimals,proto3" json:"decimals,omitempty"` + Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"` + Description string `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"` + Reissuable bool `protobuf:"varint,6,opt,name=reissuable,proto3" json:"reissuable,omitempty"` + Volume int64 `protobuf:"varint,7,opt,name=volume,proto3" json:"volume,omitempty"` + ScriptInfo *StateUpdate_AssetDetails_AssetScriptInfo `protobuf:"bytes,8,opt,name=script_info,json=scriptInfo,proto3" json:"script_info,omitempty"` + Sponsorship int64 `protobuf:"varint,9,opt,name=sponsorship,proto3" json:"sponsorship,omitempty"` + Nft bool `protobuf:"varint,10,opt,name=nft,proto3" json:"nft,omitempty"` + LastUpdated int32 `protobuf:"varint,11,opt,name=last_updated,json=lastUpdated,proto3" json:"last_updated,omitempty"` + SequenceInBlock int32 `protobuf:"varint,12,opt,name=sequence_in_block,json=sequenceInBlock,proto3" json:"sequence_in_block,omitempty"` + IssueHeight int32 `protobuf:"varint,13,opt,name=issue_height,json=issueHeight,proto3" json:"issue_height,omitempty"` // Related to a past behavior in the blockchain when it was possible to reissue // assets so that the total volume became more then int64 max value. // This field represents accurate volume even for those assets. @@ -1216,6 +1266,20 @@ func (x *StateUpdate_AssetDetails) GetLastUpdated() int32 { return 0 } +func (x *StateUpdate_AssetDetails) GetSequenceInBlock() int32 { + if x != nil { + return x.SequenceInBlock + } + return 0 +} + +func (x *StateUpdate_AssetDetails) GetIssueHeight() int32 { + if x != nil { + return x.IssueHeight + } + return 0 +} + func (x *StateUpdate_AssetDetails) GetSafeVolume() []byte { if x != nil { return x.SafeVolume @@ -1286,6 +1350,69 @@ func (x *StateUpdate_AssetInfo) GetName() string { return "" } +type StateUpdate_ScriptUpdate struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Before []byte `protobuf:"bytes,2,opt,name=before,proto3" json:"before,omitempty"` + After []byte `protobuf:"bytes,3,opt,name=after,proto3" json:"after,omitempty"` +} + +func (x *StateUpdate_ScriptUpdate) Reset() { + *x = StateUpdate_ScriptUpdate{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_events_events_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StateUpdate_ScriptUpdate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StateUpdate_ScriptUpdate) ProtoMessage() {} + +func (x *StateUpdate_ScriptUpdate) ProtoReflect() protoreflect.Message { + mi := &file_waves_events_events_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StateUpdate_ScriptUpdate.ProtoReflect.Descriptor instead. +func (*StateUpdate_ScriptUpdate) Descriptor() ([]byte, []int) { + return file_waves_events_events_proto_rawDescGZIP(), []int{1, 7} +} + +func (x *StateUpdate_ScriptUpdate) GetAddress() []byte { + if x != nil { + return x.Address + } + return nil +} + +func (x *StateUpdate_ScriptUpdate) GetBefore() []byte { + if x != nil { + return x.Before + } + return nil +} + +func (x *StateUpdate_ScriptUpdate) GetAfter() []byte { + if x != nil { + return x.After + } + return nil +} + type StateUpdate_AssetDetails_AssetScriptInfo struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1298,7 +1425,7 @@ type StateUpdate_AssetDetails_AssetScriptInfo struct { func (x *StateUpdate_AssetDetails_AssetScriptInfo) Reset() { *x = StateUpdate_AssetDetails_AssetScriptInfo{} if protoimpl.UnsafeEnabled { - mi := &file_waves_events_events_proto_msgTypes[14] + mi := &file_waves_events_events_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1311,7 +1438,7 @@ func (x *StateUpdate_AssetDetails_AssetScriptInfo) String() string { func (*StateUpdate_AssetDetails_AssetScriptInfo) ProtoMessage() {} func (x *StateUpdate_AssetDetails_AssetScriptInfo) ProtoReflect() protoreflect.Message { - mi := &file_waves_events_events_proto_msgTypes[14] + mi := &file_waves_events_events_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1352,7 +1479,7 @@ type TransactionMetadata_TransferMetadata struct { func (x *TransactionMetadata_TransferMetadata) Reset() { *x = TransactionMetadata_TransferMetadata{} if protoimpl.UnsafeEnabled { - mi := &file_waves_events_events_proto_msgTypes[15] + mi := &file_waves_events_events_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1365,7 +1492,7 @@ func (x *TransactionMetadata_TransferMetadata) String() string { func (*TransactionMetadata_TransferMetadata) ProtoMessage() {} func (x *TransactionMetadata_TransferMetadata) ProtoReflect() protoreflect.Message { - mi := &file_waves_events_events_proto_msgTypes[15] + mi := &file_waves_events_events_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1399,7 +1526,7 @@ type TransactionMetadata_MassTransferMetadata struct { func (x *TransactionMetadata_MassTransferMetadata) Reset() { *x = TransactionMetadata_MassTransferMetadata{} if protoimpl.UnsafeEnabled { - mi := &file_waves_events_events_proto_msgTypes[16] + mi := &file_waves_events_events_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1412,7 +1539,7 @@ func (x *TransactionMetadata_MassTransferMetadata) String() string { func (*TransactionMetadata_MassTransferMetadata) ProtoMessage() {} func (x *TransactionMetadata_MassTransferMetadata) ProtoReflect() protoreflect.Message { - mi := &file_waves_events_events_proto_msgTypes[16] + mi := &file_waves_events_events_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1451,7 +1578,7 @@ type TransactionMetadata_ExchangeMetadata struct { func (x *TransactionMetadata_ExchangeMetadata) Reset() { *x = TransactionMetadata_ExchangeMetadata{} if protoimpl.UnsafeEnabled { - mi := &file_waves_events_events_proto_msgTypes[17] + mi := &file_waves_events_events_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1464,7 +1591,7 @@ func (x *TransactionMetadata_ExchangeMetadata) String() string { func (*TransactionMetadata_ExchangeMetadata) ProtoMessage() {} func (x *TransactionMetadata_ExchangeMetadata) ProtoReflect() protoreflect.Message { - mi := &file_waves_events_events_proto_msgTypes[17] + mi := &file_waves_events_events_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1516,7 +1643,7 @@ type TransactionMetadata_InvokeScriptMetadata struct { func (x *TransactionMetadata_InvokeScriptMetadata) Reset() { *x = TransactionMetadata_InvokeScriptMetadata{} if protoimpl.UnsafeEnabled { - mi := &file_waves_events_events_proto_msgTypes[18] + mi := &file_waves_events_events_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1529,7 +1656,7 @@ func (x *TransactionMetadata_InvokeScriptMetadata) String() string { func (*TransactionMetadata_InvokeScriptMetadata) ProtoMessage() {} func (x *TransactionMetadata_InvokeScriptMetadata) ProtoReflect() protoreflect.Message { - mi := &file_waves_events_events_proto_msgTypes[18] + mi := &file_waves_events_events_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1591,7 +1718,7 @@ type TransactionMetadata_LeaseMetadata struct { func (x *TransactionMetadata_LeaseMetadata) Reset() { *x = TransactionMetadata_LeaseMetadata{} if protoimpl.UnsafeEnabled { - mi := &file_waves_events_events_proto_msgTypes[19] + mi := &file_waves_events_events_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1604,7 +1731,7 @@ func (x *TransactionMetadata_LeaseMetadata) String() string { func (*TransactionMetadata_LeaseMetadata) ProtoMessage() {} func (x *TransactionMetadata_LeaseMetadata) ProtoReflect() protoreflect.Message { - mi := &file_waves_events_events_proto_msgTypes[19] + mi := &file_waves_events_events_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1639,7 +1766,7 @@ type TransactionMetadata_EthereumTransferMetadata struct { func (x *TransactionMetadata_EthereumTransferMetadata) Reset() { *x = TransactionMetadata_EthereumTransferMetadata{} if protoimpl.UnsafeEnabled { - mi := &file_waves_events_events_proto_msgTypes[20] + mi := &file_waves_events_events_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1652,7 +1779,7 @@ func (x *TransactionMetadata_EthereumTransferMetadata) String() string { func (*TransactionMetadata_EthereumTransferMetadata) ProtoMessage() {} func (x *TransactionMetadata_EthereumTransferMetadata) ProtoReflect() protoreflect.Message { - mi := &file_waves_events_events_proto_msgTypes[20] + mi := &file_waves_events_events_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1701,7 +1828,7 @@ type TransactionMetadata_EthereumMetadata struct { func (x *TransactionMetadata_EthereumMetadata) Reset() { *x = TransactionMetadata_EthereumMetadata{} if protoimpl.UnsafeEnabled { - mi := &file_waves_events_events_proto_msgTypes[21] + mi := &file_waves_events_events_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1714,7 +1841,7 @@ func (x *TransactionMetadata_EthereumMetadata) String() string { func (*TransactionMetadata_EthereumMetadata) ProtoMessage() {} func (x *TransactionMetadata_EthereumMetadata) ProtoReflect() protoreflect.Message { - mi := &file_waves_events_events_proto_msgTypes[21] + mi := &file_waves_events_events_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1807,7 +1934,7 @@ type TransactionMetadata_InvokeScriptMetadata_Argument struct { func (x *TransactionMetadata_InvokeScriptMetadata_Argument) Reset() { *x = TransactionMetadata_InvokeScriptMetadata_Argument{} if protoimpl.UnsafeEnabled { - mi := &file_waves_events_events_proto_msgTypes[22] + mi := &file_waves_events_events_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1820,7 +1947,7 @@ func (x *TransactionMetadata_InvokeScriptMetadata_Argument) String() string { func (*TransactionMetadata_InvokeScriptMetadata_Argument) ProtoMessage() {} func (x *TransactionMetadata_InvokeScriptMetadata_Argument) ProtoReflect() protoreflect.Message { - mi := &file_waves_events_events_proto_msgTypes[22] + mi := &file_waves_events_events_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1928,7 +2055,7 @@ type TransactionMetadata_InvokeScriptMetadata_Argument_List struct { func (x *TransactionMetadata_InvokeScriptMetadata_Argument_List) Reset() { *x = TransactionMetadata_InvokeScriptMetadata_Argument_List{} if protoimpl.UnsafeEnabled { - mi := &file_waves_events_events_proto_msgTypes[23] + mi := &file_waves_events_events_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1941,7 +2068,7 @@ func (x *TransactionMetadata_InvokeScriptMetadata_Argument_List) String() string func (*TransactionMetadata_InvokeScriptMetadata_Argument_List) ProtoMessage() {} func (x *TransactionMetadata_InvokeScriptMetadata_Argument_List) ProtoReflect() protoreflect.Message { - mi := &file_waves_events_events_proto_msgTypes[23] + mi := &file_waves_events_events_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1975,339 +2102,369 @@ var file_waves_events_events_proto_rawDesc = []byte{ 0x1a, 0x17, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa1, 0x0a, 0x0a, 0x11, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, - 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x40, 0x0a, 0x06, 0x61, 0x70, 0x70, - 0x65, 0x6e, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x77, 0x61, 0x76, 0x65, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x18, 0x77, 0x61, 0x76, + 0x65, 0x73, 0x2f, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xcf, 0x0b, 0x0a, 0x11, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x68, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x12, 0x40, 0x0a, 0x06, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x64, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x48, 0x00, 0x52, 0x06, 0x61, + 0x70, 0x70, 0x65, 0x6e, 0x64, 0x12, 0x46, 0x0a, 0x08, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, + 0x6b, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, + 0x6b, 0x48, 0x00, 0x52, 0x08, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x50, 0x0a, + 0x11, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x64, 0x5f, 0x61, 0x73, 0x73, 0x65, + 0x74, 0x73, 0x18, 0x15, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x10, 0x72, + 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x1a, + 0xb9, 0x06, 0x0a, 0x06, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x12, 0x4a, 0x0a, 0x05, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x6e, - 0x64, 0x48, 0x00, 0x52, 0x06, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x12, 0x46, 0x0a, 0x08, 0x72, - 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, - 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x52, - 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x08, 0x72, 0x6f, 0x6c, 0x6c, 0x62, - 0x61, 0x63, 0x6b, 0x12, 0x50, 0x0a, 0x11, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, - 0x64, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x18, 0x15, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, - 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x10, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x64, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x73, 0x1a, 0xbe, 0x05, 0x0a, 0x06, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, - 0x12, 0x4a, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x32, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, - 0x2e, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x70, 0x70, - 0x65, 0x6e, 0x64, 0x48, 0x00, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x5a, 0x0a, 0x0b, - 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x37, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, - 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x64, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x2e, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x48, 0x00, 0x52, 0x0a, 0x6d, 0x69, - 0x63, 0x72, 0x6f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0c, 0x52, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x73, 0x12, 0x56, 0x0a, 0x15, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x21, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x52, 0x14, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x3c, 0x0a, 0x0c, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x64, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x48, 0x00, 0x52, + 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x5a, 0x0a, 0x0b, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x5f, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x77, 0x61, + 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x63, 0x68, 0x61, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x41, 0x70, 0x70, + 0x65, 0x6e, 0x64, 0x2e, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x70, + 0x70, 0x65, 0x6e, 0x64, 0x48, 0x00, 0x52, 0x0a, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0e, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x56, 0x0a, 0x15, 0x74, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x77, 0x61, 0x76, + 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x14, 0x74, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x12, 0x3c, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x77, 0x61, 0x76, 0x65, + 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x12, 0x55, 0x0a, 0x19, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x0c, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, + 0x17, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x1a, 0xdd, 0x01, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x12, 0x22, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x30, 0x0a, 0x14, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x5f, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x64, 0x57, 0x61, 0x76, 0x65, 0x73, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2d, + 0x0a, 0x12, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x65, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x05, 0x52, 0x11, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x61, 0x74, 0x65, 0x64, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x10, 0x0a, + 0x03, 0x76, 0x72, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x76, 0x72, 0x66, 0x12, + 0x37, 0x0a, 0x0d, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, + 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x52, + 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x68, 0x61, 0x72, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x77, 0x61, + 0x72, 0x64, 0x53, 0x68, 0x61, 0x72, 0x65, 0x73, 0x1a, 0x88, 0x01, 0x0a, 0x10, 0x4d, 0x69, 0x63, + 0x72, 0x6f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x12, 0x38, 0x0a, + 0x0b, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x0a, 0x6d, 0x69, 0x63, + 0x72, 0x6f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x3a, 0x0a, 0x19, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x64, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, + 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x17, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x6f, 0x6f, 0x74, 0x42, 0x06, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x1a, 0xef, 0x02, 0x0a, 0x08, + 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x49, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, + 0x2e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x74, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x0c, 0x52, 0x15, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x33, 0x0a, 0x0e, 0x72, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x52, 0x0d, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, + 0x12, 0x4d, 0x0a, 0x15, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x55, 0x0a, 0x19, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x75, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x77, 0x61, 0x76, - 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x17, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x1a, 0x63, - 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x12, 0x22, 0x0a, - 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x77, - 0x61, 0x76, 0x65, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x12, 0x30, 0x0a, 0x14, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x77, 0x61, 0x76, - 0x65, 0x73, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x12, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x57, 0x61, 0x76, 0x65, 0x73, 0x41, 0x6d, 0x6f, - 0x75, 0x6e, 0x74, 0x1a, 0x88, 0x01, 0x0a, 0x10, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x12, 0x38, 0x0a, 0x0b, 0x6d, 0x69, 0x63, 0x72, - 0x6f, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, - 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4d, 0x69, 0x63, 0x72, - 0x6f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x0a, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x12, 0x3a, 0x0a, 0x19, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x17, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x42, 0x06, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x1a, 0xbc, 0x02, 0x0a, 0x08, 0x52, 0x6f, 0x6c, 0x6c, 0x62, - 0x61, 0x63, 0x6b, 0x12, 0x49, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x35, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, - 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x64, 0x2e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x2e, 0x52, 0x6f, 0x6c, 0x6c, - 0x62, 0x61, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x36, - 0x0a, 0x17, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, - 0x15, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x33, 0x0a, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, - 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, - 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x0d, 0x72, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x4d, 0x0a, 0x15, 0x72, - 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x77, 0x61, 0x76, - 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x13, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x22, 0x29, 0x0a, 0x0c, 0x52, 0x6f, - 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x42, 0x4c, - 0x4f, 0x43, 0x4b, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x4d, 0x49, 0x43, 0x52, 0x4f, 0x42, 0x4c, - 0x4f, 0x43, 0x4b, 0x10, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x22, - 0xef, 0x0e, 0x0a, 0x0b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, - 0x43, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, - 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x61, 0x6c, - 0x61, 0x6e, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x08, 0x62, 0x61, 0x6c, 0x61, - 0x6e, 0x63, 0x65, 0x73, 0x12, 0x57, 0x0a, 0x13, 0x6c, 0x65, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x5f, - 0x66, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, - 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x65, 0x61, - 0x73, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x11, 0x6c, 0x65, 0x61, 0x73, - 0x69, 0x6e, 0x67, 0x46, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x4c, 0x0a, - 0x0c, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x44, - 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x0b, - 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x06, 0x61, - 0x73, 0x73, 0x65, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x77, 0x61, + 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x13, 0x72, 0x6f, 0x6c, 0x6c, + 0x62, 0x61, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, + 0x31, 0x0a, 0x14, 0x64, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x66, + 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x05, 0x52, 0x13, 0x64, + 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x73, 0x22, 0x29, 0x0a, 0x0c, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x00, 0x12, 0x0e, 0x0a, + 0x0a, 0x4d, 0x49, 0x43, 0x52, 0x4f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x01, 0x42, 0x08, 0x0a, + 0x06, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x22, 0x81, 0x11, 0x0a, 0x0b, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x43, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x61, 0x76, 0x65, + 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x52, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x57, 0x0a, 0x13, + 0x6c, 0x65, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x61, 0x76, 0x65, + 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x65, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x52, 0x11, 0x6c, 0x65, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x46, 0x6f, 0x72, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x4c, 0x0a, 0x0c, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x65, 0x6e, + 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x12, - 0x52, 0x0a, 0x11, 0x69, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x5f, 0x6c, 0x65, - 0x61, 0x73, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x77, 0x61, 0x76, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, + 0x69, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x41, + 0x73, 0x73, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, + 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x12, 0x52, 0x0a, 0x11, 0x69, 0x6e, 0x64, 0x69, 0x76, + 0x69, 0x64, 0x75, 0x61, 0x6c, 0x5f, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x65, + 0x61, 0x73, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x10, 0x69, 0x6e, 0x64, 0x69, 0x76, + 0x69, 0x64, 0x75, 0x61, 0x6c, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x07, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x77, + 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x52, 0x07, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x12, 0x27, 0x0a, + 0x0f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, + 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x41, + 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x1a, 0x80, 0x01, 0x0a, 0x0d, 0x42, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x12, 0x30, 0x0a, 0x0c, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x61, 0x66, 0x74, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x2e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x0b, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x41, + 0x66, 0x74, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x62, + 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x61, 0x6d, 0x6f, + 0x75, 0x6e, 0x74, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x1a, 0x9d, 0x01, 0x0a, 0x0d, 0x4c, 0x65, + 0x61, 0x73, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x5f, 0x61, 0x66, 0x74, 0x65, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x69, 0x6e, 0x41, 0x66, 0x74, 0x65, 0x72, + 0x12, 0x1b, 0x0a, 0x09, 0x6f, 0x75, 0x74, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x1b, 0x0a, + 0x09, 0x69, 0x6e, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x08, 0x69, 0x6e, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x75, + 0x74, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, + 0x6f, 0x75, 0x74, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x1a, 0xa9, 0x02, 0x0a, 0x0b, 0x4c, 0x65, + 0x61, 0x73, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6c, 0x65, 0x61, + 0x73, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6c, 0x65, 0x61, + 0x73, 0x65, 0x49, 0x64, 0x12, 0x54, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x61, + 0x66, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x31, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x52, 0x10, 0x69, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x4c, 0x65, 0x61, - 0x73, 0x65, 0x73, 0x1a, 0x80, 0x01, 0x0a, 0x0d, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, - 0x30, 0x0a, 0x0c, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x41, 0x6d, - 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x0b, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x66, 0x74, 0x65, - 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x62, 0x65, 0x66, 0x6f, - 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x1a, 0x9d, 0x01, 0x0a, 0x0d, 0x4c, 0x65, 0x61, 0x73, 0x69, - 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x69, 0x6e, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x1b, 0x0a, - 0x09, 0x6f, 0x75, 0x74, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x08, 0x6f, 0x75, 0x74, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x6e, - 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x69, - 0x6e, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x5f, 0x62, - 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x6f, 0x75, 0x74, - 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x1a, 0xa9, 0x02, 0x0a, 0x0b, 0x4c, 0x65, 0x61, 0x73, 0x65, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, - 0x64, 0x12, 0x54, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x61, 0x66, 0x74, 0x65, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x31, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x2e, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x4c, - 0x65, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, - 0x16, 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, - 0x69, 0x65, 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x72, 0x65, 0x63, 0x69, - 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0d, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x13, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x27, 0x0a, 0x0b, 0x4c, 0x65, 0x61, - 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0c, 0x0a, 0x08, 0x49, 0x4e, 0x41, 0x43, - 0x54, 0x49, 0x56, 0x45, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, - 0x10, 0x01, 0x1a, 0xc2, 0x01, 0x0a, 0x0f, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x12, 0x43, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x44, 0x61, 0x74, - 0x61, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, - 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x64, 0x61, 0x74, 0x61, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x50, 0x0a, 0x11, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x61, 0x74, - 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x1a, 0x90, 0x01, 0x0a, 0x10, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x3e, 0x0a, 0x06, - 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x77, - 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x44, 0x65, 0x74, - 0x61, 0x69, 0x6c, 0x73, 0x52, 0x06, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x12, 0x3c, 0x0a, 0x05, - 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x77, 0x61, - 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x44, 0x65, 0x74, 0x61, - 0x69, 0x6c, 0x73, 0x52, 0x05, 0x61, 0x66, 0x74, 0x65, 0x72, 0x1a, 0xe7, 0x03, 0x0a, 0x0c, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x61, - 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, - 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x12, 0x1a, - 0x0a, 0x08, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x08, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, - 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x69, 0x73, 0x73, 0x75, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x72, 0x65, 0x69, 0x73, 0x73, 0x75, 0x61, 0x62, 0x6c, 0x65, - 0x12, 0x16, 0x0a, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x12, 0x57, 0x0a, 0x0b, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, - 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x44, 0x65, - 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x49, 0x6e, 0x66, - 0x6f, 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x6f, 0x72, 0x73, 0x68, 0x69, 0x70, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x6f, 0x72, 0x73, - 0x68, 0x69, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x6e, 0x66, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x03, 0x6e, 0x66, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6c, 0x61, 0x73, - 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x61, 0x66, 0x65, - 0x5f, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, - 0x61, 0x66, 0x65, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x1a, 0x49, 0x0a, 0x0f, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x69, - 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, - 0x78, 0x69, 0x74, 0x79, 0x1a, 0x4b, 0x0a, 0x09, 0x41, 0x73, 0x73, 0x65, 0x74, 0x49, 0x6e, 0x66, - 0x6f, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, - 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x18, 0x02, 0x20, + 0x65, 0x2e, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0b, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, + 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x72, + 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x6f, 0x72, 0x69, 0x67, + 0x69, 0x6e, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x13, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x27, 0x0a, 0x0b, + 0x4c, 0x65, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0c, 0x0a, 0x08, 0x49, + 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x43, 0x54, + 0x49, 0x56, 0x45, 0x10, 0x01, 0x1a, 0xc2, 0x01, 0x0a, 0x0f, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x12, 0x43, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, + 0x44, 0x61, 0x74, 0x61, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, + 0x61, 0x74, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x64, + 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x50, 0x0a, 0x11, 0x64, 0x61, 0x74, 0x61, + 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, + 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x64, 0x61, 0x74, 0x61, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x1a, 0x90, 0x01, 0x0a, 0x10, 0x41, + 0x73, 0x73, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, + 0x3e, 0x0a, 0x06, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x26, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, + 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x06, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x12, + 0x3c, 0x0a, 0x05, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, + 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x44, + 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x05, 0x61, 0x66, 0x74, 0x65, 0x72, 0x1a, 0xb6, 0x04, + 0x0a, 0x0c, 0x41, 0x73, 0x73, 0x65, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x19, + 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x73, 0x73, + 0x75, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, + 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x22, 0xb8, 0x0f, 0x0a, 0x13, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65, 0x6e, - 0x64, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0d, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x12, 0x50, 0x0a, 0x08, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x18, 0x68, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x08, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, - 0x65, 0x72, 0x12, 0x50, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x6b, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x12, 0x5d, 0x0a, 0x0d, 0x6d, 0x61, 0x73, 0x73, 0x5f, 0x74, 0x72, 0x61, - 0x6e, 0x73, 0x66, 0x65, 0x72, 0x18, 0x6f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x77, 0x61, - 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4d, - 0x61, 0x73, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0c, 0x6d, 0x61, 0x73, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x66, 0x65, 0x72, 0x12, 0x5d, 0x0a, 0x0d, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x5f, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x18, 0x74, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x77, 0x61, 0x76, - 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x49, 0x6e, - 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x48, 0x00, 0x52, 0x0c, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x12, 0x47, 0x0a, 0x05, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x75, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2f, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, - 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x48, 0x00, 0x52, 0x05, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x08, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x18, 0xad, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x69, 0x73, 0x73, 0x75, 0x61, 0x62, 0x6c, + 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x72, 0x65, 0x69, 0x73, 0x73, 0x75, 0x61, + 0x62, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x12, 0x57, 0x0a, 0x0b, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x36, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x41, 0x73, 0x73, 0x65, + 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x53, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x6f, 0x72, 0x73, + 0x68, 0x69, 0x70, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x6f, 0x72, 0x73, 0x68, 0x69, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x6e, 0x66, 0x74, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x03, 0x6e, 0x66, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, + 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, + 0x6c, 0x61, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x73, + 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, + 0x49, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x73, 0x75, 0x65, + 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x69, + 0x73, 0x73, 0x75, 0x65, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x61, + 0x66, 0x65, 0x5f, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0a, 0x73, 0x61, 0x66, 0x65, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x1a, 0x49, 0x0a, 0x0f, 0x41, + 0x73, 0x73, 0x65, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, + 0x78, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x70, + 0x6c, 0x65, 0x78, 0x69, 0x74, 0x79, 0x1a, 0x4b, 0x0a, 0x09, 0x41, 0x73, 0x73, 0x65, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x1a, 0x56, 0x0a, 0x0c, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, + 0x06, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x62, + 0x65, 0x66, 0x6f, 0x72, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x61, 0x66, 0x74, 0x65, 0x72, 0x22, 0xb8, 0x0f, 0x0a, 0x13, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x73, 0x65, 0x6e, + 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x50, 0x0a, 0x08, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x18, 0x68, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x77, + 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x48, 0x00, 0x52, 0x08, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x12, 0x50, 0x0a, 0x08, + 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x6b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x48, 0x00, 0x52, 0x08, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x1a, 0x3f, - 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x5f, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x72, - 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x1a, - 0x49, 0x0a, 0x14, 0x4d, 0x61, 0x73, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x31, 0x0a, 0x14, 0x72, 0x65, 0x63, 0x69, 0x70, - 0x69, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x13, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, - 0x73, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x1a, 0x9e, 0x01, 0x0a, 0x10, 0x45, - 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, - 0x1b, 0x0a, 0x09, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0c, 0x52, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x34, 0x0a, 0x16, - 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x14, 0x6f, 0x72, - 0x64, 0x65, 0x72, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x65, 0x73, 0x12, 0x37, 0x0a, 0x18, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x6e, 0x64, - 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0c, 0x52, 0x15, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x53, 0x65, 0x6e, 0x64, 0x65, - 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x1a, 0xed, 0x04, 0x0a, 0x14, - 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x0d, 0x64, 0x5f, 0x61, 0x70, 0x70, 0x5f, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x64, 0x41, 0x70, - 0x70, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x45, 0x0a, - 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x27, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x43, 0x61, 0x6c, 0x6c, - 0x2e, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x12, 0x29, 0x0a, 0x08, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x41, - 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x08, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, - 0x31, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x1a, 0xe6, 0x02, 0x0a, 0x08, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x12, - 0x25, 0x0a, 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, - 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, - 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0b, - 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x73, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x00, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x12, 0x25, 0x0a, 0x0d, 0x62, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0c, 0x62, 0x6f, 0x6f, 0x6c, 0x65, - 0x61, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x5a, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, + 0x61, 0x2e, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x48, 0x00, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x5d, + 0x0a, 0x0d, 0x6d, 0x61, 0x73, 0x73, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x18, + 0x6f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x41, 0x72, - 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x04, 0x6c, - 0x69, 0x73, 0x74, 0x1a, 0x5d, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x55, 0x0a, 0x05, 0x69, - 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x77, 0x61, 0x76, - 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x49, 0x6e, - 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x69, 0x74, 0x65, - 0x6d, 0x73, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x3c, 0x0a, 0x0d, 0x4c, - 0x65, 0x61, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2b, 0x0a, 0x11, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4d, 0x61, 0x73, 0x73, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, + 0x0c, 0x6d, 0x61, 0x73, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x12, 0x5d, 0x0a, + 0x0d, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x74, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0c, + 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x47, 0x0a, 0x05, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x75, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x77, 0x61, + 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4c, + 0x65, 0x61, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x05, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x08, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x18, 0xad, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x45, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x08, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x1a, 0x3f, 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x66, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, - 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x1a, 0x6e, 0x0a, 0x18, 0x45, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, - 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x10, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x25, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x1a, 0xa4, 0x02, 0x0a, 0x10, 0x45, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1c, - 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, - 0x66, 0x65, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x66, 0x65, 0x65, 0x12, 0x2a, - 0x0a, 0x11, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, - 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x73, 0x65, 0x6e, 0x64, 0x65, - 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x58, 0x0a, 0x08, 0x74, 0x72, - 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x77, - 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, - 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x08, 0x74, 0x72, 0x61, 0x6e, - 0x73, 0x66, 0x65, 0x72, 0x12, 0x50, 0x0a, 0x06, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x18, 0x0b, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x1a, 0x49, 0x0a, 0x14, 0x4d, 0x61, 0x73, + 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x12, 0x31, 0x0a, 0x14, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x5f, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, + 0x13, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x73, 0x1a, 0x9e, 0x01, 0x0a, 0x10, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x6f, 0x72, 0x64, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x6f, 0x72, + 0x64, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, + 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x14, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x53, 0x65, 0x6e, + 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x18, + 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x15, + 0x6f, 0x72, 0x64, 0x65, 0x72, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x4b, 0x65, 0x79, 0x73, 0x1a, 0xed, 0x04, 0x0a, 0x14, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, + 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x22, + 0x0a, 0x0d, 0x64, 0x5f, 0x61, 0x70, 0x70, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x64, 0x41, 0x70, 0x70, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x75, 0x6e, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x45, 0x0a, 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x61, 0x76, + 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x2e, 0x41, 0x72, 0x67, 0x75, 0x6d, + 0x65, 0x6e, 0x74, 0x52, 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x29, + 0x0a, 0x08, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x0d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x52, + 0x08, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x31, 0x0a, 0x06, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x77, 0x61, 0x76, 0x65, + 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, 0xe6, 0x02, 0x0a, + 0x08, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0d, 0x69, 0x6e, 0x74, + 0x65, 0x67, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, + 0x48, 0x00, 0x52, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x23, 0x0a, 0x0c, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0b, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x73, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x25, 0x0a, 0x0d, 0x62, 0x6f, + 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x08, 0x48, 0x00, 0x52, 0x0c, 0x62, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x5a, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x44, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x1a, 0x5d, 0x0a, + 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x55, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x06, - 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x42, 0x0a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x65, 0x0a, 0x21, - 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, - 0x6d, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, - 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, - 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, - 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x69, 0x70, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x41, 0x72, 0x67, + 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x42, 0x07, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x3c, 0x0a, 0x0d, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, + 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x10, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x1a, 0x6e, 0x0a, 0x18, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, + 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x72, 0x65, 0x63, 0x69, + 0x70, 0x69, 0x65, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x25, 0x0a, 0x06, + 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x77, + 0x61, 0x76, 0x65, 0x73, 0x2e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x06, 0x61, 0x6d, 0x6f, + 0x75, 0x6e, 0x74, 0x1a, 0xa4, 0x02, 0x0a, 0x10, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x65, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x03, 0x66, 0x65, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x65, 0x6e, 0x64, + 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x4b, 0x65, 0x79, 0x12, 0x58, 0x0a, 0x08, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x48, 0x00, 0x52, 0x08, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x12, 0x50, + 0x0a, 0x06, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, + 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x06, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, + 0x42, 0x08, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0a, 0x0a, 0x08, 0x6d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x65, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x61, + 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x5a, 0x40, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, + 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, + 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2323,7 +2480,7 @@ func file_waves_events_events_proto_rawDescGZIP() []byte { } var file_waves_events_events_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_waves_events_events_proto_msgTypes = make([]protoimpl.MessageInfo, 24) +var file_waves_events_events_proto_msgTypes = make([]protoimpl.MessageInfo, 25) var file_waves_events_events_proto_goTypes = []interface{}{ (BlockchainUpdated_Rollback_RollbackType)(0), // 0: waves.events.BlockchainUpdated.Rollback.RollbackType (StateUpdate_LeaseUpdate_LeaseStatus)(0), // 1: waves.events.StateUpdate.LeaseUpdate.LeaseStatus @@ -2341,22 +2498,24 @@ var file_waves_events_events_proto_goTypes = []interface{}{ (*StateUpdate_AssetStateUpdate)(nil), // 13: waves.events.StateUpdate.AssetStateUpdate (*StateUpdate_AssetDetails)(nil), // 14: waves.events.StateUpdate.AssetDetails (*StateUpdate_AssetInfo)(nil), // 15: waves.events.StateUpdate.AssetInfo - (*StateUpdate_AssetDetails_AssetScriptInfo)(nil), // 16: waves.events.StateUpdate.AssetDetails.AssetScriptInfo - (*TransactionMetadata_TransferMetadata)(nil), // 17: waves.events.TransactionMetadata.TransferMetadata - (*TransactionMetadata_MassTransferMetadata)(nil), // 18: waves.events.TransactionMetadata.MassTransferMetadata - (*TransactionMetadata_ExchangeMetadata)(nil), // 19: waves.events.TransactionMetadata.ExchangeMetadata - (*TransactionMetadata_InvokeScriptMetadata)(nil), // 20: waves.events.TransactionMetadata.InvokeScriptMetadata - (*TransactionMetadata_LeaseMetadata)(nil), // 21: waves.events.TransactionMetadata.LeaseMetadata - (*TransactionMetadata_EthereumTransferMetadata)(nil), // 22: waves.events.TransactionMetadata.EthereumTransferMetadata - (*TransactionMetadata_EthereumMetadata)(nil), // 23: waves.events.TransactionMetadata.EthereumMetadata - (*TransactionMetadata_InvokeScriptMetadata_Argument)(nil), // 24: waves.events.TransactionMetadata.InvokeScriptMetadata.Argument - (*TransactionMetadata_InvokeScriptMetadata_Argument_List)(nil), // 25: waves.events.TransactionMetadata.InvokeScriptMetadata.Argument.List - (*waves.Block)(nil), // 26: waves.Block - (*waves.SignedMicroBlock)(nil), // 27: waves.SignedMicroBlock - (*waves.Amount)(nil), // 28: waves.Amount - (*waves.DataTransactionData_DataEntry)(nil), // 29: waves.DataTransactionData.DataEntry - (*waves.InvokeScriptResult_Call_Argument)(nil), // 30: waves.InvokeScriptResult.Call.Argument - (*waves.InvokeScriptResult)(nil), // 31: waves.InvokeScriptResult + (*StateUpdate_ScriptUpdate)(nil), // 16: waves.events.StateUpdate.ScriptUpdate + (*StateUpdate_AssetDetails_AssetScriptInfo)(nil), // 17: waves.events.StateUpdate.AssetDetails.AssetScriptInfo + (*TransactionMetadata_TransferMetadata)(nil), // 18: waves.events.TransactionMetadata.TransferMetadata + (*TransactionMetadata_MassTransferMetadata)(nil), // 19: waves.events.TransactionMetadata.MassTransferMetadata + (*TransactionMetadata_ExchangeMetadata)(nil), // 20: waves.events.TransactionMetadata.ExchangeMetadata + (*TransactionMetadata_InvokeScriptMetadata)(nil), // 21: waves.events.TransactionMetadata.InvokeScriptMetadata + (*TransactionMetadata_LeaseMetadata)(nil), // 22: waves.events.TransactionMetadata.LeaseMetadata + (*TransactionMetadata_EthereumTransferMetadata)(nil), // 23: waves.events.TransactionMetadata.EthereumTransferMetadata + (*TransactionMetadata_EthereumMetadata)(nil), // 24: waves.events.TransactionMetadata.EthereumMetadata + (*TransactionMetadata_InvokeScriptMetadata_Argument)(nil), // 25: waves.events.TransactionMetadata.InvokeScriptMetadata.Argument + (*TransactionMetadata_InvokeScriptMetadata_Argument_List)(nil), // 26: waves.events.TransactionMetadata.InvokeScriptMetadata.Argument.List + (*waves.Block)(nil), // 27: waves.Block + (*waves.RewardShare)(nil), // 28: waves.RewardShare + (*waves.SignedMicroBlock)(nil), // 29: waves.SignedMicroBlock + (*waves.Amount)(nil), // 30: waves.Amount + (*waves.DataTransactionData_DataEntry)(nil), // 31: waves.DataTransactionData.DataEntry + (*waves.InvokeScriptResult_Call_Argument)(nil), // 32: waves.InvokeScriptResult.Call.Argument + (*waves.InvokeScriptResult)(nil), // 33: waves.InvokeScriptResult } var file_waves_events_events_proto_depIdxs = []int32{ 5, // 0: waves.events.BlockchainUpdated.append:type_name -> waves.events.BlockchainUpdated.Append @@ -2367,42 +2526,44 @@ var file_waves_events_events_proto_depIdxs = []int32{ 12, // 5: waves.events.StateUpdate.data_entries:type_name -> waves.events.StateUpdate.DataEntryUpdate 13, // 6: waves.events.StateUpdate.assets:type_name -> waves.events.StateUpdate.AssetStateUpdate 11, // 7: waves.events.StateUpdate.individual_leases:type_name -> waves.events.StateUpdate.LeaseUpdate - 17, // 8: waves.events.TransactionMetadata.transfer:type_name -> waves.events.TransactionMetadata.TransferMetadata - 19, // 9: waves.events.TransactionMetadata.exchange:type_name -> waves.events.TransactionMetadata.ExchangeMetadata - 18, // 10: waves.events.TransactionMetadata.mass_transfer:type_name -> waves.events.TransactionMetadata.MassTransferMetadata - 20, // 11: waves.events.TransactionMetadata.invoke_script:type_name -> waves.events.TransactionMetadata.InvokeScriptMetadata - 21, // 12: waves.events.TransactionMetadata.lease:type_name -> waves.events.TransactionMetadata.LeaseMetadata - 23, // 13: waves.events.TransactionMetadata.ethereum:type_name -> waves.events.TransactionMetadata.EthereumMetadata - 7, // 14: waves.events.BlockchainUpdated.Append.block:type_name -> waves.events.BlockchainUpdated.Append.BlockAppend - 8, // 15: waves.events.BlockchainUpdated.Append.micro_block:type_name -> waves.events.BlockchainUpdated.Append.MicroBlockAppend - 4, // 16: waves.events.BlockchainUpdated.Append.transactions_metadata:type_name -> waves.events.TransactionMetadata - 3, // 17: waves.events.BlockchainUpdated.Append.state_update:type_name -> waves.events.StateUpdate - 3, // 18: waves.events.BlockchainUpdated.Append.transaction_state_updates:type_name -> waves.events.StateUpdate - 0, // 19: waves.events.BlockchainUpdated.Rollback.type:type_name -> waves.events.BlockchainUpdated.Rollback.RollbackType - 26, // 20: waves.events.BlockchainUpdated.Rollback.removed_blocks:type_name -> waves.Block - 3, // 21: waves.events.BlockchainUpdated.Rollback.rollback_state_update:type_name -> waves.events.StateUpdate - 26, // 22: waves.events.BlockchainUpdated.Append.BlockAppend.block:type_name -> waves.Block - 27, // 23: waves.events.BlockchainUpdated.Append.MicroBlockAppend.micro_block:type_name -> waves.SignedMicroBlock - 28, // 24: waves.events.StateUpdate.BalanceUpdate.amount_after:type_name -> waves.Amount - 1, // 25: waves.events.StateUpdate.LeaseUpdate.status_after:type_name -> waves.events.StateUpdate.LeaseUpdate.LeaseStatus - 29, // 26: waves.events.StateUpdate.DataEntryUpdate.data_entry:type_name -> waves.DataTransactionData.DataEntry - 29, // 27: waves.events.StateUpdate.DataEntryUpdate.data_entry_before:type_name -> waves.DataTransactionData.DataEntry - 14, // 28: waves.events.StateUpdate.AssetStateUpdate.before:type_name -> waves.events.StateUpdate.AssetDetails - 14, // 29: waves.events.StateUpdate.AssetStateUpdate.after:type_name -> waves.events.StateUpdate.AssetDetails - 16, // 30: waves.events.StateUpdate.AssetDetails.script_info:type_name -> waves.events.StateUpdate.AssetDetails.AssetScriptInfo - 30, // 31: waves.events.TransactionMetadata.InvokeScriptMetadata.arguments:type_name -> waves.InvokeScriptResult.Call.Argument - 28, // 32: waves.events.TransactionMetadata.InvokeScriptMetadata.payments:type_name -> waves.Amount - 31, // 33: waves.events.TransactionMetadata.InvokeScriptMetadata.result:type_name -> waves.InvokeScriptResult - 28, // 34: waves.events.TransactionMetadata.EthereumTransferMetadata.amount:type_name -> waves.Amount - 22, // 35: waves.events.TransactionMetadata.EthereumMetadata.transfer:type_name -> waves.events.TransactionMetadata.EthereumTransferMetadata - 20, // 36: waves.events.TransactionMetadata.EthereumMetadata.invoke:type_name -> waves.events.TransactionMetadata.InvokeScriptMetadata - 25, // 37: waves.events.TransactionMetadata.InvokeScriptMetadata.Argument.list:type_name -> waves.events.TransactionMetadata.InvokeScriptMetadata.Argument.List - 24, // 38: waves.events.TransactionMetadata.InvokeScriptMetadata.Argument.List.items:type_name -> waves.events.TransactionMetadata.InvokeScriptMetadata.Argument - 39, // [39:39] is the sub-list for method output_type - 39, // [39:39] is the sub-list for method input_type - 39, // [39:39] is the sub-list for extension type_name - 39, // [39:39] is the sub-list for extension extendee - 0, // [0:39] is the sub-list for field type_name + 16, // 8: waves.events.StateUpdate.scripts:type_name -> waves.events.StateUpdate.ScriptUpdate + 18, // 9: waves.events.TransactionMetadata.transfer:type_name -> waves.events.TransactionMetadata.TransferMetadata + 20, // 10: waves.events.TransactionMetadata.exchange:type_name -> waves.events.TransactionMetadata.ExchangeMetadata + 19, // 11: waves.events.TransactionMetadata.mass_transfer:type_name -> waves.events.TransactionMetadata.MassTransferMetadata + 21, // 12: waves.events.TransactionMetadata.invoke_script:type_name -> waves.events.TransactionMetadata.InvokeScriptMetadata + 22, // 13: waves.events.TransactionMetadata.lease:type_name -> waves.events.TransactionMetadata.LeaseMetadata + 24, // 14: waves.events.TransactionMetadata.ethereum:type_name -> waves.events.TransactionMetadata.EthereumMetadata + 7, // 15: waves.events.BlockchainUpdated.Append.block:type_name -> waves.events.BlockchainUpdated.Append.BlockAppend + 8, // 16: waves.events.BlockchainUpdated.Append.micro_block:type_name -> waves.events.BlockchainUpdated.Append.MicroBlockAppend + 4, // 17: waves.events.BlockchainUpdated.Append.transactions_metadata:type_name -> waves.events.TransactionMetadata + 3, // 18: waves.events.BlockchainUpdated.Append.state_update:type_name -> waves.events.StateUpdate + 3, // 19: waves.events.BlockchainUpdated.Append.transaction_state_updates:type_name -> waves.events.StateUpdate + 0, // 20: waves.events.BlockchainUpdated.Rollback.type:type_name -> waves.events.BlockchainUpdated.Rollback.RollbackType + 27, // 21: waves.events.BlockchainUpdated.Rollback.removed_blocks:type_name -> waves.Block + 3, // 22: waves.events.BlockchainUpdated.Rollback.rollback_state_update:type_name -> waves.events.StateUpdate + 27, // 23: waves.events.BlockchainUpdated.Append.BlockAppend.block:type_name -> waves.Block + 28, // 24: waves.events.BlockchainUpdated.Append.BlockAppend.reward_shares:type_name -> waves.RewardShare + 29, // 25: waves.events.BlockchainUpdated.Append.MicroBlockAppend.micro_block:type_name -> waves.SignedMicroBlock + 30, // 26: waves.events.StateUpdate.BalanceUpdate.amount_after:type_name -> waves.Amount + 1, // 27: waves.events.StateUpdate.LeaseUpdate.status_after:type_name -> waves.events.StateUpdate.LeaseUpdate.LeaseStatus + 31, // 28: waves.events.StateUpdate.DataEntryUpdate.data_entry:type_name -> waves.DataTransactionData.DataEntry + 31, // 29: waves.events.StateUpdate.DataEntryUpdate.data_entry_before:type_name -> waves.DataTransactionData.DataEntry + 14, // 30: waves.events.StateUpdate.AssetStateUpdate.before:type_name -> waves.events.StateUpdate.AssetDetails + 14, // 31: waves.events.StateUpdate.AssetStateUpdate.after:type_name -> waves.events.StateUpdate.AssetDetails + 17, // 32: waves.events.StateUpdate.AssetDetails.script_info:type_name -> waves.events.StateUpdate.AssetDetails.AssetScriptInfo + 32, // 33: waves.events.TransactionMetadata.InvokeScriptMetadata.arguments:type_name -> waves.InvokeScriptResult.Call.Argument + 30, // 34: waves.events.TransactionMetadata.InvokeScriptMetadata.payments:type_name -> waves.Amount + 33, // 35: waves.events.TransactionMetadata.InvokeScriptMetadata.result:type_name -> waves.InvokeScriptResult + 30, // 36: waves.events.TransactionMetadata.EthereumTransferMetadata.amount:type_name -> waves.Amount + 23, // 37: waves.events.TransactionMetadata.EthereumMetadata.transfer:type_name -> waves.events.TransactionMetadata.EthereumTransferMetadata + 21, // 38: waves.events.TransactionMetadata.EthereumMetadata.invoke:type_name -> waves.events.TransactionMetadata.InvokeScriptMetadata + 26, // 39: waves.events.TransactionMetadata.InvokeScriptMetadata.Argument.list:type_name -> waves.events.TransactionMetadata.InvokeScriptMetadata.Argument.List + 25, // 40: waves.events.TransactionMetadata.InvokeScriptMetadata.Argument.List.items:type_name -> waves.events.TransactionMetadata.InvokeScriptMetadata.Argument + 41, // [41:41] is the sub-list for method output_type + 41, // [41:41] is the sub-list for method input_type + 41, // [41:41] is the sub-list for extension type_name + 41, // [41:41] is the sub-list for extension extendee + 0, // [0:41] is the sub-list for field type_name } func init() { file_waves_events_events_proto_init() } @@ -2580,7 +2741,7 @@ func file_waves_events_events_proto_init() { } } file_waves_events_events_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StateUpdate_AssetDetails_AssetScriptInfo); i { + switch v := v.(*StateUpdate_ScriptUpdate); i { case 0: return &v.state case 1: @@ -2592,7 +2753,7 @@ func file_waves_events_events_proto_init() { } } file_waves_events_events_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TransactionMetadata_TransferMetadata); i { + switch v := v.(*StateUpdate_AssetDetails_AssetScriptInfo); i { case 0: return &v.state case 1: @@ -2604,7 +2765,7 @@ func file_waves_events_events_proto_init() { } } file_waves_events_events_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TransactionMetadata_MassTransferMetadata); i { + switch v := v.(*TransactionMetadata_TransferMetadata); i { case 0: return &v.state case 1: @@ -2616,7 +2777,7 @@ func file_waves_events_events_proto_init() { } } file_waves_events_events_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TransactionMetadata_ExchangeMetadata); i { + switch v := v.(*TransactionMetadata_MassTransferMetadata); i { case 0: return &v.state case 1: @@ -2628,7 +2789,7 @@ func file_waves_events_events_proto_init() { } } file_waves_events_events_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TransactionMetadata_InvokeScriptMetadata); i { + switch v := v.(*TransactionMetadata_ExchangeMetadata); i { case 0: return &v.state case 1: @@ -2640,7 +2801,7 @@ func file_waves_events_events_proto_init() { } } file_waves_events_events_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TransactionMetadata_LeaseMetadata); i { + switch v := v.(*TransactionMetadata_InvokeScriptMetadata); i { case 0: return &v.state case 1: @@ -2652,7 +2813,7 @@ func file_waves_events_events_proto_init() { } } file_waves_events_events_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TransactionMetadata_EthereumTransferMetadata); i { + switch v := v.(*TransactionMetadata_LeaseMetadata); i { case 0: return &v.state case 1: @@ -2664,7 +2825,7 @@ func file_waves_events_events_proto_init() { } } file_waves_events_events_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TransactionMetadata_EthereumMetadata); i { + switch v := v.(*TransactionMetadata_EthereumTransferMetadata); i { case 0: return &v.state case 1: @@ -2676,7 +2837,7 @@ func file_waves_events_events_proto_init() { } } file_waves_events_events_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TransactionMetadata_InvokeScriptMetadata_Argument); i { + switch v := v.(*TransactionMetadata_EthereumMetadata); i { case 0: return &v.state case 1: @@ -2688,6 +2849,18 @@ func file_waves_events_events_proto_init() { } } file_waves_events_events_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TransactionMetadata_InvokeScriptMetadata_Argument); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_events_events_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*TransactionMetadata_InvokeScriptMetadata_Argument_List); i { case 0: return &v.state @@ -2716,11 +2889,11 @@ func file_waves_events_events_proto_init() { (*BlockchainUpdated_Append_Block)(nil), (*BlockchainUpdated_Append_MicroBlock)(nil), } - file_waves_events_events_proto_msgTypes[21].OneofWrappers = []interface{}{ + file_waves_events_events_proto_msgTypes[22].OneofWrappers = []interface{}{ (*TransactionMetadata_EthereumMetadata_Transfer)(nil), (*TransactionMetadata_EthereumMetadata_Invoke)(nil), } - file_waves_events_events_proto_msgTypes[22].OneofWrappers = []interface{}{ + file_waves_events_events_proto_msgTypes[23].OneofWrappers = []interface{}{ (*TransactionMetadata_InvokeScriptMetadata_Argument_IntegerValue)(nil), (*TransactionMetadata_InvokeScriptMetadata_Argument_BinaryValue)(nil), (*TransactionMetadata_InvokeScriptMetadata_Argument_StringValue)(nil), @@ -2733,7 +2906,7 @@ func file_waves_events_events_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_waves_events_events_proto_rawDesc, NumEnums: 2, - NumMessages: 24, + NumMessages: 25, NumExtensions: 0, NumServices: 0, }, diff --git a/pkg/grpc/generated/waves/events/grpc/blockchain_updates.pb.go b/pkg/grpc/generated/waves/events/grpc/blockchain_updates.pb.go index b452aa82b..459f8a61f 100644 --- a/pkg/grpc/generated/waves/events/grpc/blockchain_updates.pb.go +++ b/pkg/grpc/generated/waves/events/grpc/blockchain_updates.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.21.12 +// protoc v4.24.3 // source: waves/events/grpc/blockchain_updates.proto package grpc diff --git a/pkg/grpc/generated/waves/events/grpc/blockchain_updates_grpc.pb.go b/pkg/grpc/generated/waves/events/grpc/blockchain_updates_grpc.pb.go index 7891ae082..2e7157def 100644 --- a/pkg/grpc/generated/waves/events/grpc/blockchain_updates_grpc.pb.go +++ b/pkg/grpc/generated/waves/events/grpc/blockchain_updates_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v3.21.12 +// - protoc v4.24.3 // source: waves/events/grpc/blockchain_updates.proto package grpc diff --git a/pkg/grpc/generated/waves/invoke_script_result.pb.go b/pkg/grpc/generated/waves/invoke_script_result.pb.go index 941ab101e..34c927c4b 100644 --- a/pkg/grpc/generated/waves/invoke_script_result.pb.go +++ b/pkg/grpc/generated/waves/invoke_script_result.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.21.12 +// protoc v4.24.3 // source: waves/invoke_script_result.proto package waves diff --git a/pkg/grpc/generated/waves/node/grpc/accounts_api.pb.go b/pkg/grpc/generated/waves/node/grpc/accounts_api.pb.go index ac40fd41e..36d4b7186 100644 --- a/pkg/grpc/generated/waves/node/grpc/accounts_api.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/accounts_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.21.12 +// protoc v4.24.3 // source: waves/node/grpc/accounts_api.proto package grpc diff --git a/pkg/grpc/generated/waves/node/grpc/accounts_api_grpc.pb.go b/pkg/grpc/generated/waves/node/grpc/accounts_api_grpc.pb.go index f669cd797..6e5040aac 100644 --- a/pkg/grpc/generated/waves/node/grpc/accounts_api_grpc.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/accounts_api_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v3.21.12 +// - protoc v4.24.3 // source: waves/node/grpc/accounts_api.proto package grpc diff --git a/pkg/grpc/generated/waves/node/grpc/assets_api.pb.go b/pkg/grpc/generated/waves/node/grpc/assets_api.pb.go index a1da34bb1..f7d9eb0dc 100644 --- a/pkg/grpc/generated/waves/node/grpc/assets_api.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/assets_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.21.12 +// protoc v4.24.3 // source: waves/node/grpc/assets_api.proto package grpc @@ -201,6 +201,8 @@ type AssetInfoResponse struct { Sponsorship int64 `protobuf:"varint,8,opt,name=sponsorship,proto3" json:"sponsorship,omitempty"` IssueTransaction *waves.SignedTransaction `protobuf:"bytes,11,opt,name=issue_transaction,json=issueTransaction,proto3" json:"issue_transaction,omitempty"` SponsorBalance int64 `protobuf:"varint,10,opt,name=sponsor_balance,json=sponsorBalance,proto3" json:"sponsor_balance,omitempty"` + SequenceInBlock int32 `protobuf:"varint,12,opt,name=sequence_in_block,json=sequenceInBlock,proto3" json:"sequence_in_block,omitempty"` + IssueHeight int32 `protobuf:"varint,13,opt,name=issue_height,json=issueHeight,proto3" json:"issue_height,omitempty"` } func (x *AssetInfoResponse) Reset() { @@ -305,6 +307,20 @@ func (x *AssetInfoResponse) GetSponsorBalance() int64 { return 0 } +func (x *AssetInfoResponse) GetSequenceInBlock() int32 { + if x != nil { + return x.SequenceInBlock + } + return 0 +} + +func (x *AssetInfoResponse) GetIssueHeight() int32 { + if x != nil { + return x.IssueHeight + } + return 0 +} + var File_waves_node_grpc_assets_api_proto protoreflect.FileDescriptor var file_waves_node_grpc_assets_api_proto_rawDesc = []byte{ @@ -330,7 +346,7 @@ var file_waves_node_grpc_assets_api_proto_rawDesc = []byte{ 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x87, 0x03, 0x0a, + 0x65, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xd6, 0x03, 0x0a, 0x11, 0x41, 0x73, 0x73, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, @@ -355,25 +371,30 @@ var file_waves_node_grpc_assets_api_proto_rawDesc = []byte{ 0x75, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x6f, 0x72, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x6f, 0x72, 0x42, - 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x32, 0xa4, 0x01, 0x0a, 0x09, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x73, 0x41, 0x70, 0x69, 0x12, 0x4c, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, - 0x1d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, - 0x63, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, + 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0c, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x0f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x6e, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x73, 0x75, 0x65, 0x5f, 0x68, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x69, 0x73, 0x73, 0x75, 0x65, 0x48, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x32, 0xa4, 0x01, 0x0a, 0x09, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, + 0x41, 0x70, 0x69, 0x12, 0x4c, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, - 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x4e, 0x46, 0x54, 0x4c, 0x69, 0x73, 0x74, - 0x12, 0x1b, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, - 0x70, 0x63, 0x2e, 0x4e, 0x46, 0x54, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, + 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, - 0x4e, 0x46, 0x54, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, 0x73, 0x0a, - 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, - 0x72, 0x6d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5a, 0x43, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, - 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, - 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, - 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x67, 0x72, 0x70, 0x63, - 0xaa, 0x02, 0x0f, 0x57, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x47, 0x72, - 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x41, 0x73, 0x73, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x49, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x4e, 0x46, 0x54, 0x4c, 0x69, 0x73, 0x74, 0x12, + 0x1b, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x4e, 0x46, 0x54, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x77, + 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4e, + 0x46, 0x54, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, 0x73, 0x0a, 0x1a, + 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, + 0x6d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, + 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, + 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, + 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x67, 0x72, 0x70, 0x63, 0xaa, + 0x02, 0x0f, 0x57, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x47, 0x72, 0x70, + 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/grpc/generated/waves/node/grpc/assets_api_grpc.pb.go b/pkg/grpc/generated/waves/node/grpc/assets_api_grpc.pb.go index b9e98f55c..e73291aba 100644 --- a/pkg/grpc/generated/waves/node/grpc/assets_api_grpc.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/assets_api_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v3.21.12 +// - protoc v4.24.3 // source: waves/node/grpc/assets_api.proto package grpc diff --git a/pkg/grpc/generated/waves/node/grpc/blockchain_api.pb.go b/pkg/grpc/generated/waves/node/grpc/blockchain_api.pb.go index d3fb20216..237e76244 100644 --- a/pkg/grpc/generated/waves/node/grpc/blockchain_api.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/blockchain_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.21.12 +// protoc v4.24.3 // source: waves/node/grpc/blockchain_api.proto package grpc diff --git a/pkg/grpc/generated/waves/node/grpc/blockchain_api_grpc.pb.go b/pkg/grpc/generated/waves/node/grpc/blockchain_api_grpc.pb.go index 1e8162699..30c29a5a3 100644 --- a/pkg/grpc/generated/waves/node/grpc/blockchain_api_grpc.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/blockchain_api_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v3.21.12 +// - protoc v4.24.3 // source: waves/node/grpc/blockchain_api.proto package grpc diff --git a/pkg/grpc/generated/waves/node/grpc/blocks_api.pb.go b/pkg/grpc/generated/waves/node/grpc/blocks_api.pb.go index 9923a21e4..fdcb63299 100644 --- a/pkg/grpc/generated/waves/node/grpc/blocks_api.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/blocks_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.21.12 +// protoc v4.24.3 // source: waves/node/grpc/blocks_api.proto package grpc @@ -222,8 +222,10 @@ type BlockWithHeight struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Block *waves.Block `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` - Height uint32 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` + Block *waves.Block `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + Height uint32 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` + Vrf []byte `protobuf:"bytes,3,opt,name=vrf,proto3" json:"vrf,omitempty"` + RewardShares []*waves.RewardShare `protobuf:"bytes,4,rep,name=reward_shares,json=rewardShares,proto3" json:"reward_shares,omitempty"` } func (x *BlockWithHeight) Reset() { @@ -272,6 +274,20 @@ func (x *BlockWithHeight) GetHeight() uint32 { return 0 } +func (x *BlockWithHeight) GetVrf() []byte { + if x != nil { + return x.Vrf + } + return nil +} + +func (x *BlockWithHeight) GetRewardShares() []*waves.RewardShare { + if x != nil { + return x.RewardShares + } + return nil +} + var File_waves_node_grpc_blocks_api_proto protoreflect.FileDescriptor var file_waves_node_grpc_blocks_api_proto_rawDesc = []byte{ @@ -279,63 +295,69 @@ var file_waves_node_grpc_blocks_api_proto_rawDesc = []byte{ 0x63, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x1a, 0x11, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0x83, 0x01, 0x0a, 0x0c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x07, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x49, - 0x64, 0x12, 0x18, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x05, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x31, 0x0a, 0x14, 0x69, - 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x18, 0x64, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, - 0x64, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x09, - 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xf1, 0x01, 0x0a, 0x11, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x1f, 0x0a, 0x0b, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x66, 0x72, 0x6f, 0x6d, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x08, 0x74, 0x6f, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x32, 0x0a, - 0x14, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x12, 0x67, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, - 0x79, 0x12, 0x2d, 0x0a, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x10, - 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x12, 0x31, 0x0a, 0x14, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x64, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, - 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x42, 0x08, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x4d, 0x0a, - 0x0f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x57, 0x69, 0x74, 0x68, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x12, 0x22, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0c, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x05, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x32, 0xfb, 0x01, 0x0a, - 0x09, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x41, 0x70, 0x69, 0x12, 0x4b, 0x0a, 0x08, 0x47, 0x65, - 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x57, 0x69, 0x74, - 0x68, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x57, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x22, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x77, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x18, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x72, 0x65, + 0x77, 0x61, 0x72, 0x64, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, + 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x83, 0x01, + 0x0a, 0x0c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, + 0x0a, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x48, 0x00, 0x52, 0x07, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x06, 0x68, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x06, 0x68, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x31, 0x0a, 0x14, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x64, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x09, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x22, 0xf1, 0x01, 0x0a, 0x11, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x61, 0x6e, + 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x72, 0x6f, + 0x6d, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, + 0x66, 0x72, 0x6f, 0x6d, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, + 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x74, + 0x6f, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x32, 0x0a, 0x14, 0x67, 0x65, 0x6e, 0x65, 0x72, + 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x12, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x6f, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x2d, 0x0a, 0x11, 0x67, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x10, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, + 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x31, 0x0a, 0x14, 0x69, 0x6e, + 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x64, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, + 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x08, 0x0a, + 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x98, 0x01, 0x0a, 0x0f, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x57, 0x69, 0x74, 0x68, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x22, 0x0a, 0x05, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x77, 0x61, 0x76, + 0x65, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, + 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x72, 0x66, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x76, 0x72, 0x66, 0x12, 0x37, 0x0a, 0x0d, 0x72, 0x65, 0x77, + 0x61, 0x72, 0x64, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, + 0x68, 0x61, 0x72, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x68, 0x61, 0x72, + 0x65, 0x73, 0x32, 0xfb, 0x01, 0x0a, 0x09, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x41, 0x70, 0x69, + 0x12, 0x4b, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x57, 0x69, 0x74, 0x68, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x30, 0x01, - 0x12, 0x48, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, - 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x73, 0x0a, 0x1a, 0x63, 0x6f, - 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, - 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, - 0x72, 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x77, 0x61, - 0x76, 0x65, 0x73, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x67, 0x72, 0x70, 0x63, 0xaa, 0x02, 0x0f, - 0x57, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x47, 0x72, 0x70, 0x63, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x77, 0x61, + 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x57, 0x69, 0x74, 0x68, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x57, 0x0a, + 0x0d, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x22, + 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x57, 0x69, 0x74, 0x68, 0x48, 0x65, + 0x69, 0x67, 0x68, 0x74, 0x30, 0x01, 0x12, 0x48, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x42, 0x73, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5a, 0x43, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, + 0x74, 0x65, 0x64, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x67, + 0x72, 0x70, 0x63, 0xaa, 0x02, 0x0f, 0x57, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x4e, 0x6f, 0x64, 0x65, + 0x2e, 0x47, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -356,22 +378,24 @@ var file_waves_node_grpc_blocks_api_proto_goTypes = []interface{}{ (*BlockRangeRequest)(nil), // 1: waves.node.grpc.BlockRangeRequest (*BlockWithHeight)(nil), // 2: waves.node.grpc.BlockWithHeight (*waves.Block)(nil), // 3: waves.Block - (*emptypb.Empty)(nil), // 4: google.protobuf.Empty - (*wrapperspb.UInt32Value)(nil), // 5: google.protobuf.UInt32Value + (*waves.RewardShare)(nil), // 4: waves.RewardShare + (*emptypb.Empty)(nil), // 5: google.protobuf.Empty + (*wrapperspb.UInt32Value)(nil), // 6: google.protobuf.UInt32Value } var file_waves_node_grpc_blocks_api_proto_depIdxs = []int32{ 3, // 0: waves.node.grpc.BlockWithHeight.block:type_name -> waves.Block - 0, // 1: waves.node.grpc.BlocksApi.GetBlock:input_type -> waves.node.grpc.BlockRequest - 1, // 2: waves.node.grpc.BlocksApi.GetBlockRange:input_type -> waves.node.grpc.BlockRangeRequest - 4, // 3: waves.node.grpc.BlocksApi.GetCurrentHeight:input_type -> google.protobuf.Empty - 2, // 4: waves.node.grpc.BlocksApi.GetBlock:output_type -> waves.node.grpc.BlockWithHeight - 2, // 5: waves.node.grpc.BlocksApi.GetBlockRange:output_type -> waves.node.grpc.BlockWithHeight - 5, // 6: waves.node.grpc.BlocksApi.GetCurrentHeight:output_type -> google.protobuf.UInt32Value - 4, // [4:7] is the sub-list for method output_type - 1, // [1:4] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name + 4, // 1: waves.node.grpc.BlockWithHeight.reward_shares:type_name -> waves.RewardShare + 0, // 2: waves.node.grpc.BlocksApi.GetBlock:input_type -> waves.node.grpc.BlockRequest + 1, // 3: waves.node.grpc.BlocksApi.GetBlockRange:input_type -> waves.node.grpc.BlockRangeRequest + 5, // 4: waves.node.grpc.BlocksApi.GetCurrentHeight:input_type -> google.protobuf.Empty + 2, // 5: waves.node.grpc.BlocksApi.GetBlock:output_type -> waves.node.grpc.BlockWithHeight + 2, // 6: waves.node.grpc.BlocksApi.GetBlockRange:output_type -> waves.node.grpc.BlockWithHeight + 6, // 7: waves.node.grpc.BlocksApi.GetCurrentHeight:output_type -> google.protobuf.UInt32Value + 5, // [5:8] is the sub-list for method output_type + 2, // [2:5] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name } func init() { file_waves_node_grpc_blocks_api_proto_init() } diff --git a/pkg/grpc/generated/waves/node/grpc/blocks_api_grpc.pb.go b/pkg/grpc/generated/waves/node/grpc/blocks_api_grpc.pb.go index c514887ba..4fed31918 100644 --- a/pkg/grpc/generated/waves/node/grpc/blocks_api_grpc.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/blocks_api_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v3.21.12 +// - protoc v4.24.3 // source: waves/node/grpc/blocks_api.proto package grpc diff --git a/pkg/grpc/generated/waves/node/grpc/transactions_api.pb.go b/pkg/grpc/generated/waves/node/grpc/transactions_api.pb.go index 5a5f7d6b3..25541e078 100644 --- a/pkg/grpc/generated/waves/node/grpc/transactions_api.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/transactions_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.21.12 +// protoc v4.24.3 // source: waves/node/grpc/transactions_api.proto package grpc @@ -27,6 +27,7 @@ const ( ApplicationStatus_UNKNOWN ApplicationStatus = 0 ApplicationStatus_SUCCEEDED ApplicationStatus = 1 ApplicationStatus_SCRIPT_EXECUTION_FAILED ApplicationStatus = 2 + ApplicationStatus_ELIDED ApplicationStatus = 3 ) // Enum value maps for ApplicationStatus. @@ -35,11 +36,13 @@ var ( 0: "UNKNOWN", 1: "SUCCEEDED", 2: "SCRIPT_EXECUTION_FAILED", + 3: "ELIDED", } ApplicationStatus_value = map[string]int32{ "UNKNOWN": 0, "SUCCEEDED": 1, "SCRIPT_EXECUTION_FAILED": 2, + "ELIDED": 3, } ) @@ -623,54 +626,55 @@ var file_waves_node_grpc_transactions_api_proto_rawDesc = []byte{ 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2a, 0x4c, 0x0a, 0x11, + 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2a, 0x58, 0x0a, 0x11, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x55, 0x43, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x49, 0x4f, - 0x4e, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x32, 0x9f, 0x04, 0x0a, 0x0f, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x41, 0x70, 0x69, 0x12, 0x5f, - 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, - 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, - 0x6b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x73, 0x12, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, - 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, - 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, 0x30, 0x01, 0x12, 0x5d, 0x0a, 0x0b, - 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x77, 0x61, - 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x30, 0x01, 0x12, 0x5e, 0x0a, 0x0e, 0x47, - 0x65, 0x74, 0x55, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x12, 0x24, 0x2e, + 0x4e, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x4c, + 0x49, 0x44, 0x45, 0x44, 0x10, 0x03, 0x32, 0x9f, 0x04, 0x0a, 0x0f, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x41, 0x70, 0x69, 0x12, 0x5f, 0x0a, 0x0f, 0x47, 0x65, + 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x3e, 0x0a, 0x04, 0x53, - 0x69, 0x67, 0x6e, 0x12, 0x1c, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x18, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x09, 0x42, - 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x12, 0x18, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, - 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x1a, 0x18, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, - 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x73, 0x0a, 0x1a, - 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, - 0x6d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, - 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, - 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, - 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x67, 0x72, 0x70, 0x63, 0xaa, - 0x02, 0x0f, 0x57, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x47, 0x72, 0x70, - 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x6b, 0x0a, 0x0f, 0x47, + 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x24, + 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, + 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, 0x30, 0x01, 0x12, 0x5d, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x22, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, + 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x30, 0x01, 0x12, 0x5e, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x55, 0x6e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x12, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, + 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x3e, 0x0a, 0x04, 0x53, 0x69, 0x67, 0x6e, 0x12, + 0x1c, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, + 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x09, 0x42, 0x72, 0x6f, 0x61, 0x64, + 0x63, 0x61, 0x73, 0x74, 0x12, 0x18, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x18, + 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x73, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, + 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, + 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, + 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x77, 0x61, 0x76, 0x65, + 0x73, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x67, 0x72, 0x70, 0x63, 0xaa, 0x02, 0x0f, 0x57, 0x61, + 0x76, 0x65, 0x73, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x47, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/grpc/generated/waves/node/grpc/transactions_api_grpc.pb.go b/pkg/grpc/generated/waves/node/grpc/transactions_api_grpc.pb.go index 619267e38..d545421d1 100644 --- a/pkg/grpc/generated/waves/node/grpc/transactions_api_grpc.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/transactions_api_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v3.21.12 +// - protoc v4.24.3 // source: waves/node/grpc/transactions_api.proto package grpc diff --git a/pkg/grpc/generated/waves/order.pb.go b/pkg/grpc/generated/waves/order.pb.go index a9068caef..cde88dab8 100644 --- a/pkg/grpc/generated/waves/order.pb.go +++ b/pkg/grpc/generated/waves/order.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.21.12 +// protoc v4.24.3 // source: waves/order.proto package waves @@ -187,6 +187,7 @@ type Order struct { Version int32 `protobuf:"varint,11,opt,name=version,proto3" json:"version,omitempty"` Proofs [][]byte `protobuf:"bytes,12,rep,name=proofs,proto3" json:"proofs,omitempty"` PriceMode Order_PriceMode `protobuf:"varint,14,opt,name=price_mode,json=priceMode,proto3,enum=waves.Order_PriceMode" json:"price_mode,omitempty"` + Attachment []byte `protobuf:"bytes,15,opt,name=attachment,proto3" json:"attachment,omitempty"` // Types that are assignable to Sender: // // *Order_SenderPublicKey @@ -310,6 +311,13 @@ func (x *Order) GetPriceMode() Order_PriceMode { return Order_DEFAULT } +func (x *Order) GetAttachment() []byte { + if x != nil { + return x.Attachment + } + return nil +} + func (m *Order) GetSender() isOrder_Sender { if m != nil { return m.Sender @@ -358,7 +366,7 @@ var file_waves_order_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x70, 0x72, 0x69, - 0x63, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x22, 0xfa, 0x04, 0x0a, 0x05, 0x4f, 0x72, + 0x63, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x22, 0x9a, 0x05, 0x0a, 0x05, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, @@ -386,7 +394,9 @@ var file_waves_order_proto_rawDesc = []byte{ 0x0a, 0x70, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x69, 0x63, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x09, 0x70, 0x72, 0x69, 0x63, 0x65, - 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, + 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, + 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, + 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x11, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0f, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x2b, 0x0a, 0x10, 0x65, 0x69, 0x70, 0x37, 0x31, 0x32, 0x5f, 0x73, 0x69, 0x67, diff --git a/pkg/grpc/generated/waves/order_vtproto.pb.go b/pkg/grpc/generated/waves/order_vtproto.pb.go index b0e9fe4cb..a640e6b4f 100644 --- a/pkg/grpc/generated/waves/order_vtproto.pb.go +++ b/pkg/grpc/generated/waves/order_vtproto.pb.go @@ -94,6 +94,13 @@ func (m *Order) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.Attachment) > 0 { + i -= len(m.Attachment) + copy(dAtA[i:], m.Attachment) + i = encodeVarint(dAtA, i, uint64(len(m.Attachment))) + i-- + dAtA[i] = 0x7a + } if m.PriceMode != 0 { i = encodeVarint(dAtA, i, uint64(m.PriceMode)) i-- @@ -284,6 +291,10 @@ func (m *Order) SizeVT() (n int) { if m.PriceMode != 0 { n += 1 + sov(uint64(m.PriceMode)) } + l = len(m.Attachment) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } n += len(m.unknownFields) return n } @@ -812,6 +823,40 @@ func (m *Order) UnmarshalVT(dAtA []byte) error { break } } + case 15: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Attachment", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Attachment = append(m.Attachment[:0], dAtA[iNdEx:postIndex]...) + if m.Attachment == nil { + m.Attachment = []byte{} + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) diff --git a/pkg/grpc/generated/waves/recipient.pb.go b/pkg/grpc/generated/waves/recipient.pb.go index b5719c6fd..c019627e1 100644 --- a/pkg/grpc/generated/waves/recipient.pb.go +++ b/pkg/grpc/generated/waves/recipient.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.21.12 +// protoc v4.24.3 // source: waves/recipient.proto package waves diff --git a/pkg/grpc/generated/waves/reward_share.pb.go b/pkg/grpc/generated/waves/reward_share.pb.go new file mode 100644 index 000000000..25a28839c --- /dev/null +++ b/pkg/grpc/generated/waves/reward_share.pb.go @@ -0,0 +1,157 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v4.24.3 +// source: waves/reward_share.proto + +package waves + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type RewardShare struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Reward int64 `protobuf:"varint,2,opt,name=reward,proto3" json:"reward,omitempty"` +} + +func (x *RewardShare) Reset() { + *x = RewardShare{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_reward_share_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RewardShare) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RewardShare) ProtoMessage() {} + +func (x *RewardShare) ProtoReflect() protoreflect.Message { + mi := &file_waves_reward_share_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RewardShare.ProtoReflect.Descriptor instead. +func (*RewardShare) Descriptor() ([]byte, []int) { + return file_waves_reward_share_proto_rawDescGZIP(), []int{0} +} + +func (x *RewardShare) GetAddress() []byte { + if x != nil { + return x.Address + } + return nil +} + +func (x *RewardShare) GetReward() int64 { + if x != nil { + return x.Reward + } + return 0 +} + +var File_waves_reward_share_proto protoreflect.FileDescriptor + +var file_waves_reward_share_proto_rawDesc = []byte{ + 0x0a, 0x18, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x73, + 0x68, 0x61, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x77, 0x61, 0x76, 0x65, + 0x73, 0x22, 0x3f, 0x0a, 0x0b, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x68, 0x61, 0x72, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, + 0x77, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x72, 0x65, 0x77, 0x61, + 0x72, 0x64, 0x42, 0x5f, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, + 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, + 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0xaa, 0x02, 0x05, 0x57, 0x61, + 0x76, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_waves_reward_share_proto_rawDescOnce sync.Once + file_waves_reward_share_proto_rawDescData = file_waves_reward_share_proto_rawDesc +) + +func file_waves_reward_share_proto_rawDescGZIP() []byte { + file_waves_reward_share_proto_rawDescOnce.Do(func() { + file_waves_reward_share_proto_rawDescData = protoimpl.X.CompressGZIP(file_waves_reward_share_proto_rawDescData) + }) + return file_waves_reward_share_proto_rawDescData +} + +var file_waves_reward_share_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_waves_reward_share_proto_goTypes = []interface{}{ + (*RewardShare)(nil), // 0: waves.RewardShare +} +var file_waves_reward_share_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_waves_reward_share_proto_init() } +func file_waves_reward_share_proto_init() { + if File_waves_reward_share_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_waves_reward_share_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RewardShare); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_waves_reward_share_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_waves_reward_share_proto_goTypes, + DependencyIndexes: file_waves_reward_share_proto_depIdxs, + MessageInfos: file_waves_reward_share_proto_msgTypes, + }.Build() + File_waves_reward_share_proto = out.File + file_waves_reward_share_proto_rawDesc = nil + file_waves_reward_share_proto_goTypes = nil + file_waves_reward_share_proto_depIdxs = nil +} diff --git a/pkg/grpc/generated/waves/reward_share_vtproto.pb.go b/pkg/grpc/generated/waves/reward_share_vtproto.pb.go new file mode 100644 index 000000000..775c0c887 --- /dev/null +++ b/pkg/grpc/generated/waves/reward_share_vtproto.pb.go @@ -0,0 +1,185 @@ +// Code generated by protoc-gen-go-vtproto. DO NOT EDIT. +// protoc-gen-go-vtproto version: v0.4.0 +// source: waves/reward_share.proto + +package waves + +import ( + fmt "fmt" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + io "io" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +func (m *RewardShare) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RewardShare) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *RewardShare) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Reward != 0 { + i = encodeVarint(dAtA, i, uint64(m.Reward)) + i-- + dAtA[i] = 0x10 + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarint(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *RewardShare) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.Reward != 0 { + n += 1 + sov(uint64(m.Reward)) + } + n += len(m.unknownFields) + return n +} + +func (m *RewardShare) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RewardShare: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RewardShare: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = append(m.Address[:0], dAtA[iNdEx:postIndex]...) + if m.Address == nil { + m.Address = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Reward", wireType) + } + m.Reward = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Reward |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} diff --git a/pkg/grpc/generated/waves/transaction.pb.go b/pkg/grpc/generated/waves/transaction.pb.go index cb4bd0776..9a06d9268 100644 --- a/pkg/grpc/generated/waves/transaction.pb.go +++ b/pkg/grpc/generated/waves/transaction.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.21.12 +// protoc v4.24.3 // source: waves/transaction.proto package waves diff --git a/pkg/grpc/generated/waves/transaction_state_snapshot.pb.go b/pkg/grpc/generated/waves/transaction_state_snapshot.pb.go new file mode 100644 index 000000000..872f23115 --- /dev/null +++ b/pkg/grpc/generated/waves/transaction_state_snapshot.pb.go @@ -0,0 +1,1583 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v4.24.3 +// source: waves/transaction_state_snapshot.proto + +package waves + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type TransactionStatus int32 + +const ( + TransactionStatus_SUCCEEDED TransactionStatus = 0 + TransactionStatus_FAILED TransactionStatus = 1 + TransactionStatus_ELIDED TransactionStatus = 2 +) + +// Enum value maps for TransactionStatus. +var ( + TransactionStatus_name = map[int32]string{ + 0: "SUCCEEDED", + 1: "FAILED", + 2: "ELIDED", + } + TransactionStatus_value = map[string]int32{ + "SUCCEEDED": 0, + "FAILED": 1, + "ELIDED": 2, + } +) + +func (x TransactionStatus) Enum() *TransactionStatus { + p := new(TransactionStatus) + *p = x + return p +} + +func (x TransactionStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TransactionStatus) Descriptor() protoreflect.EnumDescriptor { + return file_waves_transaction_state_snapshot_proto_enumTypes[0].Descriptor() +} + +func (TransactionStatus) Type() protoreflect.EnumType { + return &file_waves_transaction_state_snapshot_proto_enumTypes[0] +} + +func (x TransactionStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TransactionStatus.Descriptor instead. +func (TransactionStatus) EnumDescriptor() ([]byte, []int) { + return file_waves_transaction_state_snapshot_proto_rawDescGZIP(), []int{0} +} + +type TransactionStateSnapshot struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Balances []*TransactionStateSnapshot_Balance `protobuf:"bytes,1,rep,name=balances,proto3" json:"balances,omitempty"` + LeaseBalances []*TransactionStateSnapshot_LeaseBalance `protobuf:"bytes,2,rep,name=lease_balances,json=leaseBalances,proto3" json:"lease_balances,omitempty"` + AssetStatics []*TransactionStateSnapshot_AssetStatic `protobuf:"bytes,3,rep,name=asset_statics,json=assetStatics,proto3" json:"asset_statics,omitempty"` + AssetVolumes []*TransactionStateSnapshot_AssetVolume `protobuf:"bytes,4,rep,name=asset_volumes,json=assetVolumes,proto3" json:"asset_volumes,omitempty"` + AssetNamesAndDescriptions []*TransactionStateSnapshot_AssetNameAndDescription `protobuf:"bytes,5,rep,name=asset_names_and_descriptions,json=assetNamesAndDescriptions,proto3" json:"asset_names_and_descriptions,omitempty"` + AssetScripts []*TransactionStateSnapshot_AssetScript `protobuf:"bytes,6,rep,name=asset_scripts,json=assetScripts,proto3" json:"asset_scripts,omitempty"` + Aliases []*TransactionStateSnapshot_Alias `protobuf:"bytes,7,rep,name=aliases,proto3" json:"aliases,omitempty"` + OrderFills []*TransactionStateSnapshot_OrderFill `protobuf:"bytes,8,rep,name=order_fills,json=orderFills,proto3" json:"order_fills,omitempty"` + LeaseStates []*TransactionStateSnapshot_LeaseState `protobuf:"bytes,9,rep,name=lease_states,json=leaseStates,proto3" json:"lease_states,omitempty"` + AccountScripts []*TransactionStateSnapshot_AccountScript `protobuf:"bytes,10,rep,name=account_scripts,json=accountScripts,proto3" json:"account_scripts,omitempty"` + AccountData []*TransactionStateSnapshot_AccountData `protobuf:"bytes,11,rep,name=account_data,json=accountData,proto3" json:"account_data,omitempty"` + Sponsorships []*TransactionStateSnapshot_Sponsorship `protobuf:"bytes,12,rep,name=sponsorships,proto3" json:"sponsorships,omitempty"` + TransactionStatus TransactionStatus `protobuf:"varint,13,opt,name=transaction_status,json=transactionStatus,proto3,enum=waves.TransactionStatus" json:"transaction_status,omitempty"` +} + +func (x *TransactionStateSnapshot) Reset() { + *x = TransactionStateSnapshot{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TransactionStateSnapshot) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransactionStateSnapshot) ProtoMessage() {} + +func (x *TransactionStateSnapshot) ProtoReflect() protoreflect.Message { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TransactionStateSnapshot.ProtoReflect.Descriptor instead. +func (*TransactionStateSnapshot) Descriptor() ([]byte, []int) { + return file_waves_transaction_state_snapshot_proto_rawDescGZIP(), []int{0} +} + +func (x *TransactionStateSnapshot) GetBalances() []*TransactionStateSnapshot_Balance { + if x != nil { + return x.Balances + } + return nil +} + +func (x *TransactionStateSnapshot) GetLeaseBalances() []*TransactionStateSnapshot_LeaseBalance { + if x != nil { + return x.LeaseBalances + } + return nil +} + +func (x *TransactionStateSnapshot) GetAssetStatics() []*TransactionStateSnapshot_AssetStatic { + if x != nil { + return x.AssetStatics + } + return nil +} + +func (x *TransactionStateSnapshot) GetAssetVolumes() []*TransactionStateSnapshot_AssetVolume { + if x != nil { + return x.AssetVolumes + } + return nil +} + +func (x *TransactionStateSnapshot) GetAssetNamesAndDescriptions() []*TransactionStateSnapshot_AssetNameAndDescription { + if x != nil { + return x.AssetNamesAndDescriptions + } + return nil +} + +func (x *TransactionStateSnapshot) GetAssetScripts() []*TransactionStateSnapshot_AssetScript { + if x != nil { + return x.AssetScripts + } + return nil +} + +func (x *TransactionStateSnapshot) GetAliases() []*TransactionStateSnapshot_Alias { + if x != nil { + return x.Aliases + } + return nil +} + +func (x *TransactionStateSnapshot) GetOrderFills() []*TransactionStateSnapshot_OrderFill { + if x != nil { + return x.OrderFills + } + return nil +} + +func (x *TransactionStateSnapshot) GetLeaseStates() []*TransactionStateSnapshot_LeaseState { + if x != nil { + return x.LeaseStates + } + return nil +} + +func (x *TransactionStateSnapshot) GetAccountScripts() []*TransactionStateSnapshot_AccountScript { + if x != nil { + return x.AccountScripts + } + return nil +} + +func (x *TransactionStateSnapshot) GetAccountData() []*TransactionStateSnapshot_AccountData { + if x != nil { + return x.AccountData + } + return nil +} + +func (x *TransactionStateSnapshot) GetSponsorships() []*TransactionStateSnapshot_Sponsorship { + if x != nil { + return x.Sponsorships + } + return nil +} + +func (x *TransactionStateSnapshot) GetTransactionStatus() TransactionStatus { + if x != nil { + return x.TransactionStatus + } + return TransactionStatus_SUCCEEDED +} + +type TransactionStateSnapshot_Balance struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Amount *Amount `protobuf:"bytes,2,opt,name=amount,proto3" json:"amount,omitempty"` +} + +func (x *TransactionStateSnapshot_Balance) Reset() { + *x = TransactionStateSnapshot_Balance{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TransactionStateSnapshot_Balance) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransactionStateSnapshot_Balance) ProtoMessage() {} + +func (x *TransactionStateSnapshot_Balance) ProtoReflect() protoreflect.Message { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TransactionStateSnapshot_Balance.ProtoReflect.Descriptor instead. +func (*TransactionStateSnapshot_Balance) Descriptor() ([]byte, []int) { + return file_waves_transaction_state_snapshot_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *TransactionStateSnapshot_Balance) GetAddress() []byte { + if x != nil { + return x.Address + } + return nil +} + +func (x *TransactionStateSnapshot_Balance) GetAmount() *Amount { + if x != nil { + return x.Amount + } + return nil +} + +type TransactionStateSnapshot_LeaseBalance struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + In int64 `protobuf:"varint,2,opt,name=in,proto3" json:"in,omitempty"` + Out int64 `protobuf:"varint,3,opt,name=out,proto3" json:"out,omitempty"` +} + +func (x *TransactionStateSnapshot_LeaseBalance) Reset() { + *x = TransactionStateSnapshot_LeaseBalance{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TransactionStateSnapshot_LeaseBalance) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransactionStateSnapshot_LeaseBalance) ProtoMessage() {} + +func (x *TransactionStateSnapshot_LeaseBalance) ProtoReflect() protoreflect.Message { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TransactionStateSnapshot_LeaseBalance.ProtoReflect.Descriptor instead. +func (*TransactionStateSnapshot_LeaseBalance) Descriptor() ([]byte, []int) { + return file_waves_transaction_state_snapshot_proto_rawDescGZIP(), []int{0, 1} +} + +func (x *TransactionStateSnapshot_LeaseBalance) GetAddress() []byte { + if x != nil { + return x.Address + } + return nil +} + +func (x *TransactionStateSnapshot_LeaseBalance) GetIn() int64 { + if x != nil { + return x.In + } + return 0 +} + +func (x *TransactionStateSnapshot_LeaseBalance) GetOut() int64 { + if x != nil { + return x.Out + } + return 0 +} + +type TransactionStateSnapshot_LeaseState struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LeaseId []byte `protobuf:"bytes,1,opt,name=lease_id,json=leaseId,proto3" json:"lease_id,omitempty"` + // Types that are assignable to Status: + // + // *TransactionStateSnapshot_LeaseState_Active_ + // *TransactionStateSnapshot_LeaseState_Cancelled_ + Status isTransactionStateSnapshot_LeaseState_Status `protobuf_oneof:"status"` + Amount int64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` + Sender []byte `protobuf:"bytes,4,opt,name=sender,proto3" json:"sender,omitempty"` + Recipient []byte `protobuf:"bytes,5,opt,name=recipient,proto3" json:"recipient,omitempty"` + OriginTransactionId []byte `protobuf:"bytes,6,opt,name=origin_transaction_id,json=originTransactionId,proto3" json:"origin_transaction_id,omitempty"` + Height int32 `protobuf:"varint,7,opt,name=height,proto3" json:"height,omitempty"` +} + +func (x *TransactionStateSnapshot_LeaseState) Reset() { + *x = TransactionStateSnapshot_LeaseState{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TransactionStateSnapshot_LeaseState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransactionStateSnapshot_LeaseState) ProtoMessage() {} + +func (x *TransactionStateSnapshot_LeaseState) ProtoReflect() protoreflect.Message { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TransactionStateSnapshot_LeaseState.ProtoReflect.Descriptor instead. +func (*TransactionStateSnapshot_LeaseState) Descriptor() ([]byte, []int) { + return file_waves_transaction_state_snapshot_proto_rawDescGZIP(), []int{0, 2} +} + +func (x *TransactionStateSnapshot_LeaseState) GetLeaseId() []byte { + if x != nil { + return x.LeaseId + } + return nil +} + +func (m *TransactionStateSnapshot_LeaseState) GetStatus() isTransactionStateSnapshot_LeaseState_Status { + if m != nil { + return m.Status + } + return nil +} + +func (x *TransactionStateSnapshot_LeaseState) GetActive() *TransactionStateSnapshot_LeaseState_Active { + if x, ok := x.GetStatus().(*TransactionStateSnapshot_LeaseState_Active_); ok { + return x.Active + } + return nil +} + +func (x *TransactionStateSnapshot_LeaseState) GetCancelled() *TransactionStateSnapshot_LeaseState_Cancelled { + if x, ok := x.GetStatus().(*TransactionStateSnapshot_LeaseState_Cancelled_); ok { + return x.Cancelled + } + return nil +} + +func (x *TransactionStateSnapshot_LeaseState) GetAmount() int64 { + if x != nil { + return x.Amount + } + return 0 +} + +func (x *TransactionStateSnapshot_LeaseState) GetSender() []byte { + if x != nil { + return x.Sender + } + return nil +} + +func (x *TransactionStateSnapshot_LeaseState) GetRecipient() []byte { + if x != nil { + return x.Recipient + } + return nil +} + +func (x *TransactionStateSnapshot_LeaseState) GetOriginTransactionId() []byte { + if x != nil { + return x.OriginTransactionId + } + return nil +} + +func (x *TransactionStateSnapshot_LeaseState) GetHeight() int32 { + if x != nil { + return x.Height + } + return 0 +} + +type isTransactionStateSnapshot_LeaseState_Status interface { + isTransactionStateSnapshot_LeaseState_Status() +} + +type TransactionStateSnapshot_LeaseState_Active_ struct { + Active *TransactionStateSnapshot_LeaseState_Active `protobuf:"bytes,21,opt,name=active,proto3,oneof"` +} + +type TransactionStateSnapshot_LeaseState_Cancelled_ struct { + Cancelled *TransactionStateSnapshot_LeaseState_Cancelled `protobuf:"bytes,22,opt,name=cancelled,proto3,oneof"` +} + +func (*TransactionStateSnapshot_LeaseState_Active_) isTransactionStateSnapshot_LeaseState_Status() {} + +func (*TransactionStateSnapshot_LeaseState_Cancelled_) isTransactionStateSnapshot_LeaseState_Status() { +} + +type TransactionStateSnapshot_AssetStatic struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AssetId []byte `protobuf:"bytes,1,opt,name=asset_id,json=assetId,proto3" json:"asset_id,omitempty"` + SourceTransactionId []byte `protobuf:"bytes,2,opt,name=source_transaction_id,json=sourceTransactionId,proto3" json:"source_transaction_id,omitempty"` + IssuerPublicKey []byte `protobuf:"bytes,3,opt,name=issuer_public_key,json=issuerPublicKey,proto3" json:"issuer_public_key,omitempty"` + Decimals int32 `protobuf:"varint,4,opt,name=decimals,proto3" json:"decimals,omitempty"` + Nft bool `protobuf:"varint,5,opt,name=nft,proto3" json:"nft,omitempty"` +} + +func (x *TransactionStateSnapshot_AssetStatic) Reset() { + *x = TransactionStateSnapshot_AssetStatic{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TransactionStateSnapshot_AssetStatic) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransactionStateSnapshot_AssetStatic) ProtoMessage() {} + +func (x *TransactionStateSnapshot_AssetStatic) ProtoReflect() protoreflect.Message { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TransactionStateSnapshot_AssetStatic.ProtoReflect.Descriptor instead. +func (*TransactionStateSnapshot_AssetStatic) Descriptor() ([]byte, []int) { + return file_waves_transaction_state_snapshot_proto_rawDescGZIP(), []int{0, 3} +} + +func (x *TransactionStateSnapshot_AssetStatic) GetAssetId() []byte { + if x != nil { + return x.AssetId + } + return nil +} + +func (x *TransactionStateSnapshot_AssetStatic) GetSourceTransactionId() []byte { + if x != nil { + return x.SourceTransactionId + } + return nil +} + +func (x *TransactionStateSnapshot_AssetStatic) GetIssuerPublicKey() []byte { + if x != nil { + return x.IssuerPublicKey + } + return nil +} + +func (x *TransactionStateSnapshot_AssetStatic) GetDecimals() int32 { + if x != nil { + return x.Decimals + } + return 0 +} + +func (x *TransactionStateSnapshot_AssetStatic) GetNft() bool { + if x != nil { + return x.Nft + } + return false +} + +type TransactionStateSnapshot_AssetVolume struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AssetId []byte `protobuf:"bytes,1,opt,name=asset_id,json=assetId,proto3" json:"asset_id,omitempty"` + Reissuable bool `protobuf:"varint,2,opt,name=reissuable,proto3" json:"reissuable,omitempty"` + Volume []byte `protobuf:"bytes,3,opt,name=volume,proto3" json:"volume,omitempty"` +} + +func (x *TransactionStateSnapshot_AssetVolume) Reset() { + *x = TransactionStateSnapshot_AssetVolume{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TransactionStateSnapshot_AssetVolume) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransactionStateSnapshot_AssetVolume) ProtoMessage() {} + +func (x *TransactionStateSnapshot_AssetVolume) ProtoReflect() protoreflect.Message { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TransactionStateSnapshot_AssetVolume.ProtoReflect.Descriptor instead. +func (*TransactionStateSnapshot_AssetVolume) Descriptor() ([]byte, []int) { + return file_waves_transaction_state_snapshot_proto_rawDescGZIP(), []int{0, 4} +} + +func (x *TransactionStateSnapshot_AssetVolume) GetAssetId() []byte { + if x != nil { + return x.AssetId + } + return nil +} + +func (x *TransactionStateSnapshot_AssetVolume) GetReissuable() bool { + if x != nil { + return x.Reissuable + } + return false +} + +func (x *TransactionStateSnapshot_AssetVolume) GetVolume() []byte { + if x != nil { + return x.Volume + } + return nil +} + +type TransactionStateSnapshot_AssetNameAndDescription struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AssetId []byte `protobuf:"bytes,1,opt,name=asset_id,json=assetId,proto3" json:"asset_id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` + LastUpdated int32 `protobuf:"varint,4,opt,name=last_updated,json=lastUpdated,proto3" json:"last_updated,omitempty"` +} + +func (x *TransactionStateSnapshot_AssetNameAndDescription) Reset() { + *x = TransactionStateSnapshot_AssetNameAndDescription{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TransactionStateSnapshot_AssetNameAndDescription) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransactionStateSnapshot_AssetNameAndDescription) ProtoMessage() {} + +func (x *TransactionStateSnapshot_AssetNameAndDescription) ProtoReflect() protoreflect.Message { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TransactionStateSnapshot_AssetNameAndDescription.ProtoReflect.Descriptor instead. +func (*TransactionStateSnapshot_AssetNameAndDescription) Descriptor() ([]byte, []int) { + return file_waves_transaction_state_snapshot_proto_rawDescGZIP(), []int{0, 5} +} + +func (x *TransactionStateSnapshot_AssetNameAndDescription) GetAssetId() []byte { + if x != nil { + return x.AssetId + } + return nil +} + +func (x *TransactionStateSnapshot_AssetNameAndDescription) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *TransactionStateSnapshot_AssetNameAndDescription) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *TransactionStateSnapshot_AssetNameAndDescription) GetLastUpdated() int32 { + if x != nil { + return x.LastUpdated + } + return 0 +} + +type TransactionStateSnapshot_AssetScript struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AssetId []byte `protobuf:"bytes,1,opt,name=asset_id,json=assetId,proto3" json:"asset_id,omitempty"` + Script []byte `protobuf:"bytes,2,opt,name=script,proto3" json:"script,omitempty"` +} + +func (x *TransactionStateSnapshot_AssetScript) Reset() { + *x = TransactionStateSnapshot_AssetScript{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TransactionStateSnapshot_AssetScript) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransactionStateSnapshot_AssetScript) ProtoMessage() {} + +func (x *TransactionStateSnapshot_AssetScript) ProtoReflect() protoreflect.Message { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TransactionStateSnapshot_AssetScript.ProtoReflect.Descriptor instead. +func (*TransactionStateSnapshot_AssetScript) Descriptor() ([]byte, []int) { + return file_waves_transaction_state_snapshot_proto_rawDescGZIP(), []int{0, 6} +} + +func (x *TransactionStateSnapshot_AssetScript) GetAssetId() []byte { + if x != nil { + return x.AssetId + } + return nil +} + +func (x *TransactionStateSnapshot_AssetScript) GetScript() []byte { + if x != nil { + return x.Script + } + return nil +} + +type TransactionStateSnapshot_Alias struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Alias string `protobuf:"bytes,2,opt,name=alias,proto3" json:"alias,omitempty"` +} + +func (x *TransactionStateSnapshot_Alias) Reset() { + *x = TransactionStateSnapshot_Alias{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TransactionStateSnapshot_Alias) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransactionStateSnapshot_Alias) ProtoMessage() {} + +func (x *TransactionStateSnapshot_Alias) ProtoReflect() protoreflect.Message { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TransactionStateSnapshot_Alias.ProtoReflect.Descriptor instead. +func (*TransactionStateSnapshot_Alias) Descriptor() ([]byte, []int) { + return file_waves_transaction_state_snapshot_proto_rawDescGZIP(), []int{0, 7} +} + +func (x *TransactionStateSnapshot_Alias) GetAddress() []byte { + if x != nil { + return x.Address + } + return nil +} + +func (x *TransactionStateSnapshot_Alias) GetAlias() string { + if x != nil { + return x.Alias + } + return "" +} + +type TransactionStateSnapshot_OrderFill struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + OrderId []byte `protobuf:"bytes,1,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` + Volume int64 `protobuf:"varint,2,opt,name=volume,proto3" json:"volume,omitempty"` + Fee int64 `protobuf:"varint,3,opt,name=fee,proto3" json:"fee,omitempty"` +} + +func (x *TransactionStateSnapshot_OrderFill) Reset() { + *x = TransactionStateSnapshot_OrderFill{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TransactionStateSnapshot_OrderFill) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransactionStateSnapshot_OrderFill) ProtoMessage() {} + +func (x *TransactionStateSnapshot_OrderFill) ProtoReflect() protoreflect.Message { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TransactionStateSnapshot_OrderFill.ProtoReflect.Descriptor instead. +func (*TransactionStateSnapshot_OrderFill) Descriptor() ([]byte, []int) { + return file_waves_transaction_state_snapshot_proto_rawDescGZIP(), []int{0, 8} +} + +func (x *TransactionStateSnapshot_OrderFill) GetOrderId() []byte { + if x != nil { + return x.OrderId + } + return nil +} + +func (x *TransactionStateSnapshot_OrderFill) GetVolume() int64 { + if x != nil { + return x.Volume + } + return 0 +} + +func (x *TransactionStateSnapshot_OrderFill) GetFee() int64 { + if x != nil { + return x.Fee + } + return 0 +} + +type TransactionStateSnapshot_AccountScript struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SenderPublicKey []byte `protobuf:"bytes,1,opt,name=sender_public_key,json=senderPublicKey,proto3" json:"sender_public_key,omitempty"` + Script []byte `protobuf:"bytes,2,opt,name=script,proto3" json:"script,omitempty"` + VerifierComplexity int64 `protobuf:"varint,3,opt,name=verifier_complexity,json=verifierComplexity,proto3" json:"verifier_complexity,omitempty"` +} + +func (x *TransactionStateSnapshot_AccountScript) Reset() { + *x = TransactionStateSnapshot_AccountScript{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TransactionStateSnapshot_AccountScript) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransactionStateSnapshot_AccountScript) ProtoMessage() {} + +func (x *TransactionStateSnapshot_AccountScript) ProtoReflect() protoreflect.Message { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TransactionStateSnapshot_AccountScript.ProtoReflect.Descriptor instead. +func (*TransactionStateSnapshot_AccountScript) Descriptor() ([]byte, []int) { + return file_waves_transaction_state_snapshot_proto_rawDescGZIP(), []int{0, 9} +} + +func (x *TransactionStateSnapshot_AccountScript) GetSenderPublicKey() []byte { + if x != nil { + return x.SenderPublicKey + } + return nil +} + +func (x *TransactionStateSnapshot_AccountScript) GetScript() []byte { + if x != nil { + return x.Script + } + return nil +} + +func (x *TransactionStateSnapshot_AccountScript) GetVerifierComplexity() int64 { + if x != nil { + return x.VerifierComplexity + } + return 0 +} + +type TransactionStateSnapshot_AccountData struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Entries []*DataTransactionData_DataEntry `protobuf:"bytes,2,rep,name=entries,proto3" json:"entries,omitempty"` +} + +func (x *TransactionStateSnapshot_AccountData) Reset() { + *x = TransactionStateSnapshot_AccountData{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TransactionStateSnapshot_AccountData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransactionStateSnapshot_AccountData) ProtoMessage() {} + +func (x *TransactionStateSnapshot_AccountData) ProtoReflect() protoreflect.Message { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TransactionStateSnapshot_AccountData.ProtoReflect.Descriptor instead. +func (*TransactionStateSnapshot_AccountData) Descriptor() ([]byte, []int) { + return file_waves_transaction_state_snapshot_proto_rawDescGZIP(), []int{0, 10} +} + +func (x *TransactionStateSnapshot_AccountData) GetAddress() []byte { + if x != nil { + return x.Address + } + return nil +} + +func (x *TransactionStateSnapshot_AccountData) GetEntries() []*DataTransactionData_DataEntry { + if x != nil { + return x.Entries + } + return nil +} + +type TransactionStateSnapshot_Sponsorship struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AssetId []byte `protobuf:"bytes,1,opt,name=asset_id,json=assetId,proto3" json:"asset_id,omitempty"` + MinFee int64 `protobuf:"varint,2,opt,name=min_fee,json=minFee,proto3" json:"min_fee,omitempty"` +} + +func (x *TransactionStateSnapshot_Sponsorship) Reset() { + *x = TransactionStateSnapshot_Sponsorship{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TransactionStateSnapshot_Sponsorship) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransactionStateSnapshot_Sponsorship) ProtoMessage() {} + +func (x *TransactionStateSnapshot_Sponsorship) ProtoReflect() protoreflect.Message { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TransactionStateSnapshot_Sponsorship.ProtoReflect.Descriptor instead. +func (*TransactionStateSnapshot_Sponsorship) Descriptor() ([]byte, []int) { + return file_waves_transaction_state_snapshot_proto_rawDescGZIP(), []int{0, 11} +} + +func (x *TransactionStateSnapshot_Sponsorship) GetAssetId() []byte { + if x != nil { + return x.AssetId + } + return nil +} + +func (x *TransactionStateSnapshot_Sponsorship) GetMinFee() int64 { + if x != nil { + return x.MinFee + } + return 0 +} + +type TransactionStateSnapshot_LeaseState_Active struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (m *TransactionStateSnapshot_LeaseState_Active) isTransactionStateSnapshot_LeaseState_Status() { + //TODO implement me + panic("implement me") +} + +func (x *TransactionStateSnapshot_LeaseState_Active) Reset() { + *x = TransactionStateSnapshot_LeaseState_Active{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TransactionStateSnapshot_LeaseState_Active) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransactionStateSnapshot_LeaseState_Active) ProtoMessage() {} + +func (x *TransactionStateSnapshot_LeaseState_Active) ProtoReflect() protoreflect.Message { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TransactionStateSnapshot_LeaseState_Active.ProtoReflect.Descriptor instead. +func (*TransactionStateSnapshot_LeaseState_Active) Descriptor() ([]byte, []int) { + return file_waves_transaction_state_snapshot_proto_rawDescGZIP(), []int{0, 2, 0} +} + +type TransactionStateSnapshot_LeaseState_Cancelled struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Height int32 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + TransactionId []byte `protobuf:"bytes,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` +} + +func (m *TransactionStateSnapshot_LeaseState_Cancelled) isTransactionStateSnapshot_LeaseState_Status() { + //TODO implement me + panic("implement me") +} + +func (x *TransactionStateSnapshot_LeaseState_Cancelled) Reset() { + *x = TransactionStateSnapshot_LeaseState_Cancelled{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TransactionStateSnapshot_LeaseState_Cancelled) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransactionStateSnapshot_LeaseState_Cancelled) ProtoMessage() {} + +func (x *TransactionStateSnapshot_LeaseState_Cancelled) ProtoReflect() protoreflect.Message { + mi := &file_waves_transaction_state_snapshot_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TransactionStateSnapshot_LeaseState_Cancelled.ProtoReflect.Descriptor instead. +func (*TransactionStateSnapshot_LeaseState_Cancelled) Descriptor() ([]byte, []int) { + return file_waves_transaction_state_snapshot_proto_rawDescGZIP(), []int{0, 2, 1} +} + +func (x *TransactionStateSnapshot_LeaseState_Cancelled) GetHeight() int32 { + if x != nil { + return x.Height + } + return 0 +} + +func (x *TransactionStateSnapshot_LeaseState_Cancelled) GetTransactionId() []byte { + if x != nil { + return x.TransactionId + } + return nil +} + +var File_waves_transaction_state_snapshot_proto protoreflect.FileDescriptor + +var file_waves_transaction_state_snapshot_proto_rawDesc = []byte{ + 0x0a, 0x26, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, + 0x6f, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x77, 0x61, 0x76, 0x65, 0x73, 0x1a, + 0x12, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xcc, 0x14, 0x0a, + 0x18, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x43, 0x0a, 0x08, 0x62, 0x61, 0x6c, + 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x61, + 0x76, 0x65, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x42, 0x61, 0x6c, + 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x53, + 0x0a, 0x0e, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, + 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x42, 0x61, 0x6c, + 0x61, 0x6e, 0x63, 0x65, 0x52, 0x0d, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x0d, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x63, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x77, 0x61, 0x76, + 0x65, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x41, 0x73, 0x73, 0x65, + 0x74, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x52, 0x0c, 0x61, 0x73, 0x73, 0x65, 0x74, 0x53, 0x74, + 0x61, 0x74, 0x69, 0x63, 0x73, 0x12, 0x50, 0x0a, 0x0d, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x76, + 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x77, + 0x61, 0x76, 0x65, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x41, 0x73, + 0x73, 0x65, 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x52, 0x0c, 0x61, 0x73, 0x73, 0x65, 0x74, + 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x12, 0x78, 0x0a, 0x1c, 0x61, 0x73, 0x73, 0x65, 0x74, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, + 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x41, + 0x73, 0x73, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x41, 0x6e, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x19, 0x61, 0x73, 0x73, 0x65, 0x74, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x41, 0x6e, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x50, 0x0a, 0x0d, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x53, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x0c, 0x61, 0x73, 0x73, 0x65, 0x74, 0x53, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x73, 0x12, 0x3f, 0x0a, 0x07, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x52, 0x07, 0x61, 0x6c, 0x69, + 0x61, 0x73, 0x65, 0x73, 0x12, 0x4a, 0x0a, 0x0b, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x66, 0x69, + 0x6c, 0x6c, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x61, 0x76, 0x65, + 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, + 0x46, 0x69, 0x6c, 0x6c, 0x52, 0x0a, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x6c, 0x73, + 0x12, 0x4d, 0x0a, 0x0c, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, + 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, + 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x52, 0x0b, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x12, + 0x56, 0x0a, 0x0f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x0e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x12, 0x4e, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, + 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x41, + 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x4f, 0x0a, 0x0c, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x6f, 0x72, 0x73, 0x68, 0x69, 0x70, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, + 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x53, + 0x70, 0x6f, 0x6e, 0x73, 0x6f, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x0c, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x6f, 0x72, 0x73, 0x68, 0x69, 0x70, 0x73, 0x12, 0x47, 0x0a, 0x12, 0x74, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0d, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x11, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x1a, 0x4a, 0x0a, 0x07, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x25, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x41, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x1a, 0x4a, 0x0a, + 0x0c, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6f, 0x75, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x6f, 0x75, 0x74, 0x1a, 0xc4, 0x03, 0x0a, 0x0a, 0x4c, 0x65, + 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6c, 0x65, 0x61, 0x73, + 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6c, 0x65, 0x61, 0x73, + 0x65, 0x49, 0x64, 0x12, 0x4b, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x18, 0x15, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, + 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, + 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x48, 0x00, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, + 0x12, 0x54, 0x0a, 0x09, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x18, 0x16, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, + 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, + 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x48, 0x00, 0x52, 0x09, 0x63, 0x61, 0x6e, + 0x63, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, + 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, + 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, + 0x69, 0x65, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f, 0x74, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x13, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x1a, 0x08, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x1a, 0x4a, 0x0a, 0x09, 0x43, 0x61, + 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, + 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x42, 0x08, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x1a, 0xb6, 0x01, 0x0a, 0x0b, 0x41, 0x73, 0x73, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, + 0x12, 0x19, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x13, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, + 0x2a, 0x0a, 0x11, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, + 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x69, 0x73, 0x73, 0x75, + 0x65, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x64, + 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x64, + 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6e, 0x66, 0x74, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x6e, 0x66, 0x74, 0x1a, 0x60, 0x0a, 0x0b, 0x41, 0x73, 0x73, + 0x65, 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, + 0x74, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x69, 0x73, 0x73, 0x75, 0x61, 0x62, 0x6c, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x72, 0x65, 0x69, 0x73, 0x73, 0x75, 0x61, + 0x62, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x1a, 0x8d, 0x01, 0x0a, 0x17, + 0x41, 0x73, 0x73, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x41, 0x6e, 0x64, 0x44, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, + 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, + 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, + 0x6c, 0x61, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x1a, 0x40, 0x0a, 0x0b, 0x41, + 0x73, 0x73, 0x65, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x73, + 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x73, + 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x1a, 0x37, 0x0a, + 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x12, 0x14, 0x0a, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x1a, 0x50, 0x0a, 0x09, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x46, + 0x69, 0x6c, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, + 0x0a, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, + 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x65, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x03, 0x66, 0x65, 0x65, 0x1a, 0x84, 0x01, 0x0a, 0x0d, 0x41, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x65, + 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x2f, + 0x0a, 0x13, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, + 0x65, 0x78, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x76, 0x65, 0x72, + 0x69, 0x66, 0x69, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x74, 0x79, 0x1a, + 0x67, 0x0a, 0x0b, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x18, + 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x3e, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, + 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x61, 0x76, 0x65, + 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x1a, 0x41, 0x0a, 0x0b, 0x53, 0x70, 0x6f, 0x6e, + 0x73, 0x6f, 0x72, 0x73, 0x68, 0x69, 0x70, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, + 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x69, 0x6e, 0x5f, 0x66, 0x65, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x06, 0x6d, 0x69, 0x6e, 0x46, 0x65, 0x65, 0x2a, 0x3a, 0x0a, 0x11, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x55, 0x43, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x00, 0x12, + 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x45, + 0x4c, 0x49, 0x44, 0x45, 0x44, 0x10, 0x02, 0x42, 0x68, 0x0a, 0x23, 0x63, 0x6f, 0x6d, 0x2e, 0x77, + 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5a, 0x39, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, + 0x74, 0x65, 0x64, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0xaa, 0x02, 0x05, 0x57, 0x61, 0x76, 0x65, + 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_waves_transaction_state_snapshot_proto_rawDescOnce sync.Once + file_waves_transaction_state_snapshot_proto_rawDescData = file_waves_transaction_state_snapshot_proto_rawDesc +) + +func file_waves_transaction_state_snapshot_proto_rawDescGZIP() []byte { + file_waves_transaction_state_snapshot_proto_rawDescOnce.Do(func() { + file_waves_transaction_state_snapshot_proto_rawDescData = protoimpl.X.CompressGZIP(file_waves_transaction_state_snapshot_proto_rawDescData) + }) + return file_waves_transaction_state_snapshot_proto_rawDescData +} + +var file_waves_transaction_state_snapshot_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_waves_transaction_state_snapshot_proto_msgTypes = make([]protoimpl.MessageInfo, 15) +var file_waves_transaction_state_snapshot_proto_goTypes = []interface{}{ + (TransactionStatus)(0), // 0: waves.TransactionStatus + (*TransactionStateSnapshot)(nil), // 1: waves.TransactionStateSnapshot + (*TransactionStateSnapshot_Balance)(nil), // 2: waves.TransactionStateSnapshot.Balance + (*TransactionStateSnapshot_LeaseBalance)(nil), // 3: waves.TransactionStateSnapshot.LeaseBalance + (*TransactionStateSnapshot_LeaseState)(nil), // 4: waves.TransactionStateSnapshot.LeaseState + (*TransactionStateSnapshot_AssetStatic)(nil), // 5: waves.TransactionStateSnapshot.AssetStatic + (*TransactionStateSnapshot_AssetVolume)(nil), // 6: waves.TransactionStateSnapshot.AssetVolume + (*TransactionStateSnapshot_AssetNameAndDescription)(nil), // 7: waves.TransactionStateSnapshot.AssetNameAndDescription + (*TransactionStateSnapshot_AssetScript)(nil), // 8: waves.TransactionStateSnapshot.AssetScript + (*TransactionStateSnapshot_Alias)(nil), // 9: waves.TransactionStateSnapshot.Alias + (*TransactionStateSnapshot_OrderFill)(nil), // 10: waves.TransactionStateSnapshot.OrderFill + (*TransactionStateSnapshot_AccountScript)(nil), // 11: waves.TransactionStateSnapshot.AccountScript + (*TransactionStateSnapshot_AccountData)(nil), // 12: waves.TransactionStateSnapshot.AccountData + (*TransactionStateSnapshot_Sponsorship)(nil), // 13: waves.TransactionStateSnapshot.Sponsorship + (*TransactionStateSnapshot_LeaseState_Active)(nil), // 14: waves.TransactionStateSnapshot.LeaseState.Active + (*TransactionStateSnapshot_LeaseState_Cancelled)(nil), // 15: waves.TransactionStateSnapshot.LeaseState.Cancelled + (*Amount)(nil), // 16: waves.Amount + (*DataTransactionData_DataEntry)(nil), // 17: waves.DataTransactionData.DataEntry +} +var file_waves_transaction_state_snapshot_proto_depIdxs = []int32{ + 2, // 0: waves.TransactionStateSnapshot.balances:type_name -> waves.TransactionStateSnapshot.Balance + 3, // 1: waves.TransactionStateSnapshot.lease_balances:type_name -> waves.TransactionStateSnapshot.LeaseBalance + 5, // 2: waves.TransactionStateSnapshot.asset_statics:type_name -> waves.TransactionStateSnapshot.AssetStatic + 6, // 3: waves.TransactionStateSnapshot.asset_volumes:type_name -> waves.TransactionStateSnapshot.AssetVolume + 7, // 4: waves.TransactionStateSnapshot.asset_names_and_descriptions:type_name -> waves.TransactionStateSnapshot.AssetNameAndDescription + 8, // 5: waves.TransactionStateSnapshot.asset_scripts:type_name -> waves.TransactionStateSnapshot.AssetScript + 9, // 6: waves.TransactionStateSnapshot.aliases:type_name -> waves.TransactionStateSnapshot.Alias + 10, // 7: waves.TransactionStateSnapshot.order_fills:type_name -> waves.TransactionStateSnapshot.OrderFill + 4, // 8: waves.TransactionStateSnapshot.lease_states:type_name -> waves.TransactionStateSnapshot.LeaseState + 11, // 9: waves.TransactionStateSnapshot.account_scripts:type_name -> waves.TransactionStateSnapshot.AccountScript + 12, // 10: waves.TransactionStateSnapshot.account_data:type_name -> waves.TransactionStateSnapshot.AccountData + 13, // 11: waves.TransactionStateSnapshot.sponsorships:type_name -> waves.TransactionStateSnapshot.Sponsorship + 0, // 12: waves.TransactionStateSnapshot.transaction_status:type_name -> waves.TransactionStatus + 16, // 13: waves.TransactionStateSnapshot.Balance.amount:type_name -> waves.Amount + 14, // 14: waves.TransactionStateSnapshot.LeaseState.active:type_name -> waves.TransactionStateSnapshot.LeaseState.Active + 15, // 15: waves.TransactionStateSnapshot.LeaseState.cancelled:type_name -> waves.TransactionStateSnapshot.LeaseState.Cancelled + 17, // 16: waves.TransactionStateSnapshot.AccountData.entries:type_name -> waves.DataTransactionData.DataEntry + 17, // [17:17] is the sub-list for method output_type + 17, // [17:17] is the sub-list for method input_type + 17, // [17:17] is the sub-list for extension type_name + 17, // [17:17] is the sub-list for extension extendee + 0, // [0:17] is the sub-list for field type_name +} + +func init() { file_waves_transaction_state_snapshot_proto_init() } +func file_waves_transaction_state_snapshot_proto_init() { + if File_waves_transaction_state_snapshot_proto != nil { + return + } + file_waves_amount_proto_init() + file_waves_transaction_proto_init() + if !protoimpl.UnsafeEnabled { + file_waves_transaction_state_snapshot_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TransactionStateSnapshot); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_transaction_state_snapshot_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TransactionStateSnapshot_Balance); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_transaction_state_snapshot_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TransactionStateSnapshot_LeaseBalance); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_transaction_state_snapshot_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TransactionStateSnapshot_LeaseState); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_transaction_state_snapshot_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TransactionStateSnapshot_AssetStatic); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_transaction_state_snapshot_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TransactionStateSnapshot_AssetVolume); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_transaction_state_snapshot_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TransactionStateSnapshot_AssetNameAndDescription); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_transaction_state_snapshot_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TransactionStateSnapshot_AssetScript); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_transaction_state_snapshot_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TransactionStateSnapshot_Alias); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_transaction_state_snapshot_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TransactionStateSnapshot_OrderFill); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_transaction_state_snapshot_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TransactionStateSnapshot_AccountScript); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_transaction_state_snapshot_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TransactionStateSnapshot_AccountData); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_transaction_state_snapshot_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TransactionStateSnapshot_Sponsorship); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_transaction_state_snapshot_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TransactionStateSnapshot_LeaseState_Active); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_transaction_state_snapshot_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TransactionStateSnapshot_LeaseState_Cancelled); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_waves_transaction_state_snapshot_proto_msgTypes[3].OneofWrappers = []interface{}{ + (*TransactionStateSnapshot_LeaseState_Active_)(nil), + (*TransactionStateSnapshot_LeaseState_Cancelled_)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_waves_transaction_state_snapshot_proto_rawDesc, + NumEnums: 1, + NumMessages: 15, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_waves_transaction_state_snapshot_proto_goTypes, + DependencyIndexes: file_waves_transaction_state_snapshot_proto_depIdxs, + EnumInfos: file_waves_transaction_state_snapshot_proto_enumTypes, + MessageInfos: file_waves_transaction_state_snapshot_proto_msgTypes, + }.Build() + File_waves_transaction_state_snapshot_proto = out.File + file_waves_transaction_state_snapshot_proto_rawDesc = nil + file_waves_transaction_state_snapshot_proto_goTypes = nil + file_waves_transaction_state_snapshot_proto_depIdxs = nil +} diff --git a/pkg/grpc/generated/waves/transaction_state_snapshot_vtproto.pb.go b/pkg/grpc/generated/waves/transaction_state_snapshot_vtproto.pb.go new file mode 100644 index 000000000..553911335 --- /dev/null +++ b/pkg/grpc/generated/waves/transaction_state_snapshot_vtproto.pb.go @@ -0,0 +1,3784 @@ +// Code generated by protoc-gen-go-vtproto. DO NOT EDIT. +// protoc-gen-go-vtproto version: v0.4.0 +// source: waves/transaction_state_snapshot.proto + +package waves + +import ( + fmt "fmt" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + io "io" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +func (m *TransactionStateSnapshot_Balance) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TransactionStateSnapshot_Balance) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *TransactionStateSnapshot_Balance) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Amount != nil { + size, err := m.Amount.MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarint(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *TransactionStateSnapshot_LeaseBalance) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TransactionStateSnapshot_LeaseBalance) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *TransactionStateSnapshot_LeaseBalance) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Out != 0 { + i = encodeVarint(dAtA, i, uint64(m.Out)) + i-- + dAtA[i] = 0x18 + } + if m.In != 0 { + i = encodeVarint(dAtA, i, uint64(m.In)) + i-- + dAtA[i] = 0x10 + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarint(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *TransactionStateSnapshot_LeaseState_Active) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TransactionStateSnapshot_LeaseState_Active) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *TransactionStateSnapshot_LeaseState_Active) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + return len(dAtA) - i, nil +} + +func (m *TransactionStateSnapshot_LeaseState_Cancelled) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TransactionStateSnapshot_LeaseState_Cancelled) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *TransactionStateSnapshot_LeaseState_Cancelled) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.TransactionId) > 0 { + i -= len(m.TransactionId) + copy(dAtA[i:], m.TransactionId) + i = encodeVarint(dAtA, i, uint64(len(m.TransactionId))) + i-- + dAtA[i] = 0x12 + } + if m.Height != 0 { + i = encodeVarint(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *TransactionStateSnapshot_LeaseState) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TransactionStateSnapshot_LeaseState) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *TransactionStateSnapshot_LeaseState) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if msg, ok := m.Status.(*TransactionStateSnapshot_LeaseState_Cancelled_); ok { + size, err := msg.MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + } + if msg, ok := m.Status.(*TransactionStateSnapshot_LeaseState_Active_); ok { + size, err := msg.MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + } + if m.Height != 0 { + i = encodeVarint(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x38 + } + if len(m.OriginTransactionId) > 0 { + i -= len(m.OriginTransactionId) + copy(dAtA[i:], m.OriginTransactionId) + i = encodeVarint(dAtA, i, uint64(len(m.OriginTransactionId))) + i-- + dAtA[i] = 0x32 + } + if len(m.Recipient) > 0 { + i -= len(m.Recipient) + copy(dAtA[i:], m.Recipient) + i = encodeVarint(dAtA, i, uint64(len(m.Recipient))) + i-- + dAtA[i] = 0x2a + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarint(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0x22 + } + if m.Amount != 0 { + i = encodeVarint(dAtA, i, uint64(m.Amount)) + i-- + dAtA[i] = 0x18 + } + if len(m.LeaseId) > 0 { + i -= len(m.LeaseId) + copy(dAtA[i:], m.LeaseId) + i = encodeVarint(dAtA, i, uint64(len(m.LeaseId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *TransactionStateSnapshot_LeaseState_Active_) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *TransactionStateSnapshot_LeaseState_Active_) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Active != nil { + size, err := m.Active.MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xaa + } + return len(dAtA) - i, nil +} +func (m *TransactionStateSnapshot_LeaseState_Cancelled_) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *TransactionStateSnapshot_LeaseState_Cancelled_) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Cancelled != nil { + size, err := m.Cancelled.MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xb2 + } + return len(dAtA) - i, nil +} +func (m *TransactionStateSnapshot_AssetStatic) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TransactionStateSnapshot_AssetStatic) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *TransactionStateSnapshot_AssetStatic) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Nft { + i-- + if m.Nft { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x28 + } + if m.Decimals != 0 { + i = encodeVarint(dAtA, i, uint64(m.Decimals)) + i-- + dAtA[i] = 0x20 + } + if len(m.IssuerPublicKey) > 0 { + i -= len(m.IssuerPublicKey) + copy(dAtA[i:], m.IssuerPublicKey) + i = encodeVarint(dAtA, i, uint64(len(m.IssuerPublicKey))) + i-- + dAtA[i] = 0x1a + } + if len(m.SourceTransactionId) > 0 { + i -= len(m.SourceTransactionId) + copy(dAtA[i:], m.SourceTransactionId) + i = encodeVarint(dAtA, i, uint64(len(m.SourceTransactionId))) + i-- + dAtA[i] = 0x12 + } + if len(m.AssetId) > 0 { + i -= len(m.AssetId) + copy(dAtA[i:], m.AssetId) + i = encodeVarint(dAtA, i, uint64(len(m.AssetId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *TransactionStateSnapshot_AssetVolume) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TransactionStateSnapshot_AssetVolume) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *TransactionStateSnapshot_AssetVolume) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Volume) > 0 { + i -= len(m.Volume) + copy(dAtA[i:], m.Volume) + i = encodeVarint(dAtA, i, uint64(len(m.Volume))) + i-- + dAtA[i] = 0x1a + } + if m.Reissuable { + i-- + if m.Reissuable { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } + if len(m.AssetId) > 0 { + i -= len(m.AssetId) + copy(dAtA[i:], m.AssetId) + i = encodeVarint(dAtA, i, uint64(len(m.AssetId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *TransactionStateSnapshot_AssetNameAndDescription) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TransactionStateSnapshot_AssetNameAndDescription) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *TransactionStateSnapshot_AssetNameAndDescription) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.LastUpdated != 0 { + i = encodeVarint(dAtA, i, uint64(m.LastUpdated)) + i-- + dAtA[i] = 0x20 + } + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarint(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x1a + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarint(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0x12 + } + if len(m.AssetId) > 0 { + i -= len(m.AssetId) + copy(dAtA[i:], m.AssetId) + i = encodeVarint(dAtA, i, uint64(len(m.AssetId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *TransactionStateSnapshot_AssetScript) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TransactionStateSnapshot_AssetScript) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *TransactionStateSnapshot_AssetScript) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Script) > 0 { + i -= len(m.Script) + copy(dAtA[i:], m.Script) + i = encodeVarint(dAtA, i, uint64(len(m.Script))) + i-- + dAtA[i] = 0x12 + } + if len(m.AssetId) > 0 { + i -= len(m.AssetId) + copy(dAtA[i:], m.AssetId) + i = encodeVarint(dAtA, i, uint64(len(m.AssetId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *TransactionStateSnapshot_Alias) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TransactionStateSnapshot_Alias) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *TransactionStateSnapshot_Alias) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Alias) > 0 { + i -= len(m.Alias) + copy(dAtA[i:], m.Alias) + i = encodeVarint(dAtA, i, uint64(len(m.Alias))) + i-- + dAtA[i] = 0x12 + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarint(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *TransactionStateSnapshot_OrderFill) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TransactionStateSnapshot_OrderFill) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *TransactionStateSnapshot_OrderFill) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Fee != 0 { + i = encodeVarint(dAtA, i, uint64(m.Fee)) + i-- + dAtA[i] = 0x18 + } + if m.Volume != 0 { + i = encodeVarint(dAtA, i, uint64(m.Volume)) + i-- + dAtA[i] = 0x10 + } + if len(m.OrderId) > 0 { + i -= len(m.OrderId) + copy(dAtA[i:], m.OrderId) + i = encodeVarint(dAtA, i, uint64(len(m.OrderId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *TransactionStateSnapshot_AccountScript) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TransactionStateSnapshot_AccountScript) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *TransactionStateSnapshot_AccountScript) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.VerifierComplexity != 0 { + i = encodeVarint(dAtA, i, uint64(m.VerifierComplexity)) + i-- + dAtA[i] = 0x18 + } + if len(m.Script) > 0 { + i -= len(m.Script) + copy(dAtA[i:], m.Script) + i = encodeVarint(dAtA, i, uint64(len(m.Script))) + i-- + dAtA[i] = 0x12 + } + if len(m.SenderPublicKey) > 0 { + i -= len(m.SenderPublicKey) + copy(dAtA[i:], m.SenderPublicKey) + i = encodeVarint(dAtA, i, uint64(len(m.SenderPublicKey))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *TransactionStateSnapshot_AccountData) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TransactionStateSnapshot_AccountData) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *TransactionStateSnapshot_AccountData) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Entries) > 0 { + for iNdEx := len(m.Entries) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Entries[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + } + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarint(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *TransactionStateSnapshot_Sponsorship) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TransactionStateSnapshot_Sponsorship) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *TransactionStateSnapshot_Sponsorship) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.MinFee != 0 { + i = encodeVarint(dAtA, i, uint64(m.MinFee)) + i-- + dAtA[i] = 0x10 + } + if len(m.AssetId) > 0 { + i -= len(m.AssetId) + copy(dAtA[i:], m.AssetId) + i = encodeVarint(dAtA, i, uint64(len(m.AssetId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *TransactionStateSnapshot) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TransactionStateSnapshot) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *TransactionStateSnapshot) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.TransactionStatus != 0 { + i = encodeVarint(dAtA, i, uint64(m.TransactionStatus)) + i-- + dAtA[i] = 0x68 + } + if len(m.Sponsorships) > 0 { + for iNdEx := len(m.Sponsorships) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Sponsorships[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x62 + } + } + if len(m.AccountData) > 0 { + for iNdEx := len(m.AccountData) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.AccountData[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x5a + } + } + if len(m.AccountScripts) > 0 { + for iNdEx := len(m.AccountScripts) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.AccountScripts[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x52 + } + } + if len(m.LeaseStates) > 0 { + for iNdEx := len(m.LeaseStates) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.LeaseStates[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x4a + } + } + if len(m.OrderFills) > 0 { + for iNdEx := len(m.OrderFills) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.OrderFills[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x42 + } + } + if len(m.Aliases) > 0 { + for iNdEx := len(m.Aliases) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Aliases[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x3a + } + } + if len(m.AssetScripts) > 0 { + for iNdEx := len(m.AssetScripts) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.AssetScripts[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x32 + } + } + if len(m.AssetNamesAndDescriptions) > 0 { + for iNdEx := len(m.AssetNamesAndDescriptions) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.AssetNamesAndDescriptions[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x2a + } + } + if len(m.AssetVolumes) > 0 { + for iNdEx := len(m.AssetVolumes) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.AssetVolumes[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } + } + if len(m.AssetStatics) > 0 { + for iNdEx := len(m.AssetStatics) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.AssetStatics[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x1a + } + } + if len(m.LeaseBalances) > 0 { + for iNdEx := len(m.LeaseBalances) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.LeaseBalances[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + } + } + if len(m.Balances) > 0 { + for iNdEx := len(m.Balances) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Balances[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *TransactionStateSnapshot_Balance) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.Amount != nil { + l = m.Amount.SizeVT() + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *TransactionStateSnapshot_LeaseBalance) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.In != 0 { + n += 1 + sov(uint64(m.In)) + } + if m.Out != 0 { + n += 1 + sov(uint64(m.Out)) + } + n += len(m.unknownFields) + return n +} + +func (m *TransactionStateSnapshot_LeaseState_Active) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += len(m.unknownFields) + return n +} + +func (m *TransactionStateSnapshot_LeaseState_Cancelled) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sov(uint64(m.Height)) + } + l = len(m.TransactionId) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *TransactionStateSnapshot_LeaseState) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.LeaseId) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.Amount != 0 { + n += 1 + sov(uint64(m.Amount)) + } + l = len(m.Sender) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.Recipient) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.OriginTransactionId) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.Height != 0 { + n += 1 + sov(uint64(m.Height)) + } + if vtmsg, ok := m.Status.(interface{ SizeVT() int }); ok { + n += vtmsg.SizeVT() + } + n += len(m.unknownFields) + return n +} + +func (m *TransactionStateSnapshot_LeaseState_Active_) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Active != nil { + l = m.Active.SizeVT() + n += 2 + l + sov(uint64(l)) + } + return n +} +func (m *TransactionStateSnapshot_LeaseState_Cancelled_) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Cancelled != nil { + l = m.Cancelled.SizeVT() + n += 2 + l + sov(uint64(l)) + } + return n +} +func (m *TransactionStateSnapshot_AssetStatic) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.AssetId) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.SourceTransactionId) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.IssuerPublicKey) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.Decimals != 0 { + n += 1 + sov(uint64(m.Decimals)) + } + if m.Nft { + n += 2 + } + n += len(m.unknownFields) + return n +} + +func (m *TransactionStateSnapshot_AssetVolume) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.AssetId) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.Reissuable { + n += 2 + } + l = len(m.Volume) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *TransactionStateSnapshot_AssetNameAndDescription) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.AssetId) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.Name) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.LastUpdated != 0 { + n += 1 + sov(uint64(m.LastUpdated)) + } + n += len(m.unknownFields) + return n +} + +func (m *TransactionStateSnapshot_AssetScript) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.AssetId) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.Script) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *TransactionStateSnapshot_Alias) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.Alias) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *TransactionStateSnapshot_OrderFill) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.OrderId) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.Volume != 0 { + n += 1 + sov(uint64(m.Volume)) + } + if m.Fee != 0 { + n += 1 + sov(uint64(m.Fee)) + } + n += len(m.unknownFields) + return n +} + +func (m *TransactionStateSnapshot_AccountScript) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.SenderPublicKey) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.Script) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.VerifierComplexity != 0 { + n += 1 + sov(uint64(m.VerifierComplexity)) + } + n += len(m.unknownFields) + return n +} + +func (m *TransactionStateSnapshot_AccountData) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if len(m.Entries) > 0 { + for _, e := range m.Entries { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + n += len(m.unknownFields) + return n +} + +func (m *TransactionStateSnapshot_Sponsorship) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.AssetId) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.MinFee != 0 { + n += 1 + sov(uint64(m.MinFee)) + } + n += len(m.unknownFields) + return n +} + +func (m *TransactionStateSnapshot) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Balances) > 0 { + for _, e := range m.Balances { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + if len(m.LeaseBalances) > 0 { + for _, e := range m.LeaseBalances { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + if len(m.AssetStatics) > 0 { + for _, e := range m.AssetStatics { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + if len(m.AssetVolumes) > 0 { + for _, e := range m.AssetVolumes { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + if len(m.AssetNamesAndDescriptions) > 0 { + for _, e := range m.AssetNamesAndDescriptions { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + if len(m.AssetScripts) > 0 { + for _, e := range m.AssetScripts { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + if len(m.Aliases) > 0 { + for _, e := range m.Aliases { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + if len(m.OrderFills) > 0 { + for _, e := range m.OrderFills { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + if len(m.LeaseStates) > 0 { + for _, e := range m.LeaseStates { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + if len(m.AccountScripts) > 0 { + for _, e := range m.AccountScripts { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + if len(m.AccountData) > 0 { + for _, e := range m.AccountData { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + if len(m.Sponsorships) > 0 { + for _, e := range m.Sponsorships { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + if m.TransactionStatus != 0 { + n += 1 + sov(uint64(m.TransactionStatus)) + } + n += len(m.unknownFields) + return n +} + +func (m *TransactionStateSnapshot_Balance) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TransactionStateSnapshot_Balance: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TransactionStateSnapshot_Balance: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = append(m.Address[:0], dAtA[iNdEx:postIndex]...) + if m.Address == nil { + m.Address = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Amount == nil { + m.Amount = &Amount{} + } + if err := m.Amount.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TransactionStateSnapshot_LeaseBalance) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TransactionStateSnapshot_LeaseBalance: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TransactionStateSnapshot_LeaseBalance: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = append(m.Address[:0], dAtA[iNdEx:postIndex]...) + if m.Address == nil { + m.Address = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field In", wireType) + } + m.In = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.In |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Out", wireType) + } + m.Out = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Out |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TransactionStateSnapshot_LeaseState_Active) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TransactionStateSnapshot_LeaseState_Active: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TransactionStateSnapshot_LeaseState_Active: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TransactionStateSnapshot_LeaseState_Cancelled) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TransactionStateSnapshot_LeaseState_Cancelled: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TransactionStateSnapshot_LeaseState_Cancelled: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TransactionId", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TransactionId = append(m.TransactionId[:0], dAtA[iNdEx:postIndex]...) + if m.TransactionId == nil { + m.TransactionId = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TransactionStateSnapshot_LeaseState) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TransactionStateSnapshot_LeaseState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TransactionStateSnapshot_LeaseState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LeaseId", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.LeaseId = append(m.LeaseId[:0], dAtA[iNdEx:postIndex]...) + if m.LeaseId == nil { + m.LeaseId = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + m.Amount = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Amount |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = append(m.Sender[:0], dAtA[iNdEx:postIndex]...) + if m.Sender == nil { + m.Sender = []byte{} + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Recipient", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Recipient = append(m.Recipient[:0], dAtA[iNdEx:postIndex]...) + if m.Recipient == nil { + m.Recipient = []byte{} + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OriginTransactionId", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.OriginTransactionId = append(m.OriginTransactionId[:0], dAtA[iNdEx:postIndex]...) + if m.OriginTransactionId == nil { + m.OriginTransactionId = []byte{} + } + iNdEx = postIndex + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 21: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Active", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if oneof, ok := m.Status.(*TransactionStateSnapshot_LeaseState_Active_); ok { + if err := oneof.Active.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + } else { + v := &TransactionStateSnapshot_LeaseState_Active{} + if err := v.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Status = &TransactionStateSnapshot_LeaseState_Active_{Active: v} + } + iNdEx = postIndex + case 22: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Cancelled", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if oneof, ok := m.Status.(*TransactionStateSnapshot_LeaseState_Cancelled_); ok { + if err := oneof.Cancelled.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + } else { + v := &TransactionStateSnapshot_LeaseState_Cancelled{} + if err := v.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Status = &TransactionStateSnapshot_LeaseState_Cancelled_{Cancelled: v} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TransactionStateSnapshot_AssetStatic) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TransactionStateSnapshot_AssetStatic: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TransactionStateSnapshot_AssetStatic: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetId", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetId = append(m.AssetId[:0], dAtA[iNdEx:postIndex]...) + if m.AssetId == nil { + m.AssetId = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SourceTransactionId", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SourceTransactionId = append(m.SourceTransactionId[:0], dAtA[iNdEx:postIndex]...) + if m.SourceTransactionId == nil { + m.SourceTransactionId = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IssuerPublicKey", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.IssuerPublicKey = append(m.IssuerPublicKey[:0], dAtA[iNdEx:postIndex]...) + if m.IssuerPublicKey == nil { + m.IssuerPublicKey = []byte{} + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Decimals", wireType) + } + m.Decimals = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Decimals |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Nft", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Nft = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TransactionStateSnapshot_AssetVolume) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TransactionStateSnapshot_AssetVolume: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TransactionStateSnapshot_AssetVolume: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetId", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetId = append(m.AssetId[:0], dAtA[iNdEx:postIndex]...) + if m.AssetId == nil { + m.AssetId = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Reissuable", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Reissuable = bool(v != 0) + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Volume", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Volume = append(m.Volume[:0], dAtA[iNdEx:postIndex]...) + if m.Volume == nil { + m.Volume = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TransactionStateSnapshot_AssetNameAndDescription) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TransactionStateSnapshot_AssetNameAndDescription: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TransactionStateSnapshot_AssetNameAndDescription: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetId", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetId = append(m.AssetId[:0], dAtA[iNdEx:postIndex]...) + if m.AssetId == nil { + m.AssetId = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastUpdated", wireType) + } + m.LastUpdated = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastUpdated |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TransactionStateSnapshot_AssetScript) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TransactionStateSnapshot_AssetScript: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TransactionStateSnapshot_AssetScript: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetId", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetId = append(m.AssetId[:0], dAtA[iNdEx:postIndex]...) + if m.AssetId == nil { + m.AssetId = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Script", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Script = append(m.Script[:0], dAtA[iNdEx:postIndex]...) + if m.Script == nil { + m.Script = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TransactionStateSnapshot_Alias) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TransactionStateSnapshot_Alias: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TransactionStateSnapshot_Alias: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = append(m.Address[:0], dAtA[iNdEx:postIndex]...) + if m.Address == nil { + m.Address = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Alias", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Alias = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TransactionStateSnapshot_OrderFill) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TransactionStateSnapshot_OrderFill: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TransactionStateSnapshot_OrderFill: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OrderId", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.OrderId = append(m.OrderId[:0], dAtA[iNdEx:postIndex]...) + if m.OrderId == nil { + m.OrderId = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Volume", wireType) + } + m.Volume = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Volume |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Fee", wireType) + } + m.Fee = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Fee |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TransactionStateSnapshot_AccountScript) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TransactionStateSnapshot_AccountScript: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TransactionStateSnapshot_AccountScript: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SenderPublicKey", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SenderPublicKey = append(m.SenderPublicKey[:0], dAtA[iNdEx:postIndex]...) + if m.SenderPublicKey == nil { + m.SenderPublicKey = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Script", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Script = append(m.Script[:0], dAtA[iNdEx:postIndex]...) + if m.Script == nil { + m.Script = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field VerifierComplexity", wireType) + } + m.VerifierComplexity = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.VerifierComplexity |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TransactionStateSnapshot_AccountData) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TransactionStateSnapshot_AccountData: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TransactionStateSnapshot_AccountData: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = append(m.Address[:0], dAtA[iNdEx:postIndex]...) + if m.Address == nil { + m.Address = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Entries", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Entries = append(m.Entries, &DataTransactionData_DataEntry{}) + if err := m.Entries[len(m.Entries)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TransactionStateSnapshot_Sponsorship) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TransactionStateSnapshot_Sponsorship: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TransactionStateSnapshot_Sponsorship: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetId", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetId = append(m.AssetId[:0], dAtA[iNdEx:postIndex]...) + if m.AssetId == nil { + m.AssetId = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MinFee", wireType) + } + m.MinFee = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MinFee |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TransactionStateSnapshot) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TransactionStateSnapshot: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TransactionStateSnapshot: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Balances", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Balances = append(m.Balances, &TransactionStateSnapshot_Balance{}) + if err := m.Balances[len(m.Balances)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LeaseBalances", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.LeaseBalances = append(m.LeaseBalances, &TransactionStateSnapshot_LeaseBalance{}) + if err := m.LeaseBalances[len(m.LeaseBalances)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetStatics", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetStatics = append(m.AssetStatics, &TransactionStateSnapshot_AssetStatic{}) + if err := m.AssetStatics[len(m.AssetStatics)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetVolumes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetVolumes = append(m.AssetVolumes, &TransactionStateSnapshot_AssetVolume{}) + if err := m.AssetVolumes[len(m.AssetVolumes)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetNamesAndDescriptions", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetNamesAndDescriptions = append(m.AssetNamesAndDescriptions, &TransactionStateSnapshot_AssetNameAndDescription{}) + if err := m.AssetNamesAndDescriptions[len(m.AssetNamesAndDescriptions)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetScripts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetScripts = append(m.AssetScripts, &TransactionStateSnapshot_AssetScript{}) + if err := m.AssetScripts[len(m.AssetScripts)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Aliases", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Aliases = append(m.Aliases, &TransactionStateSnapshot_Alias{}) + if err := m.Aliases[len(m.Aliases)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OrderFills", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.OrderFills = append(m.OrderFills, &TransactionStateSnapshot_OrderFill{}) + if err := m.OrderFills[len(m.OrderFills)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LeaseStates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.LeaseStates = append(m.LeaseStates, &TransactionStateSnapshot_LeaseState{}) + if err := m.LeaseStates[len(m.LeaseStates)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AccountScripts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AccountScripts = append(m.AccountScripts, &TransactionStateSnapshot_AccountScript{}) + if err := m.AccountScripts[len(m.AccountScripts)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AccountData", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AccountData = append(m.AccountData, &TransactionStateSnapshot_AccountData{}) + if err := m.AccountData[len(m.AccountData)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sponsorships", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sponsorships = append(m.Sponsorships, &TransactionStateSnapshot_Sponsorship{}) + if err := m.Sponsorships[len(m.Sponsorships)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 13: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TransactionStatus", wireType) + } + m.TransactionStatus = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TransactionStatus |= TransactionStatus(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} diff --git a/pkg/grpc/protobuf-schemas b/pkg/grpc/protobuf-schemas index a59b344b3..111a6641e 160000 --- a/pkg/grpc/protobuf-schemas +++ b/pkg/grpc/protobuf-schemas @@ -1 +1 @@ -Subproject commit a59b344b360e6cff03bd0e42e1cbb2c033bbca66 +Subproject commit 111a6641e4bf281d36750b7665b01284864d654a diff --git a/pkg/mock/state.go b/pkg/mock/state.go index 77faed293..be36d72d8 100644 --- a/pkg/mock/state.go +++ b/pkg/mock/state.go @@ -10,6 +10,7 @@ import ( gomock "github.com/golang/mock/gomock" crypto "github.com/wavesplatform/gowaves/pkg/crypto" + waves "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" proto "github.com/wavesplatform/gowaves/pkg/proto" ast "github.com/wavesplatform/gowaves/pkg/ride/ast" settings "github.com/wavesplatform/gowaves/pkg/settings" @@ -868,6 +869,21 @@ func (mr *MockStateInfoMockRecorder) ShouldPersistAddressTransactions() *gomock. return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShouldPersistAddressTransactions", reflect.TypeOf((*MockStateInfo)(nil).ShouldPersistAddressTransactions)) } +// SnapshotsAtHeight mocks base method. +func (m *MockStateInfo) SnapshotsAtHeight(height proto.Height) (*waves.TransactionStateSnapshot, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SnapshotsAtHeight", height) + ret0, _ := ret[0].(*waves.TransactionStateSnapshot) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SnapshotsAtHeight indicates an expected call of SnapshotsAtHeight. +func (mr *MockStateInfoMockRecorder) SnapshotsAtHeight(height interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SnapshotsAtHeight", reflect.TypeOf((*MockStateInfo)(nil).SnapshotsAtHeight), height) +} + // StateHashAtHeight mocks base method. func (m *MockStateInfo) StateHashAtHeight(height uint64) (*proto.StateHash, error) { m.ctrl.T.Helper() @@ -2175,6 +2191,21 @@ func (mr *MockStateMockRecorder) ShouldPersistAddressTransactions() *gomock.Call return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShouldPersistAddressTransactions", reflect.TypeOf((*MockState)(nil).ShouldPersistAddressTransactions)) } +// SnapshotsAtHeight mocks base method. +func (m *MockState) SnapshotsAtHeight(height proto.Height) (*waves.TransactionStateSnapshot, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SnapshotsAtHeight", height) + ret0, _ := ret[0].(*waves.TransactionStateSnapshot) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SnapshotsAtHeight indicates an expected call of SnapshotsAtHeight. +func (mr *MockStateMockRecorder) SnapshotsAtHeight(height interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SnapshotsAtHeight", reflect.TypeOf((*MockState)(nil).SnapshotsAtHeight), height) +} + // StartProvidingExtendedApi mocks base method. func (m *MockState) StartProvidingExtendedApi() error { m.ctrl.T.Helper() diff --git a/pkg/proto/snapshot_types.go b/pkg/proto/snapshot_types.go new file mode 100644 index 000000000..7516188fa --- /dev/null +++ b/pkg/proto/snapshot_types.go @@ -0,0 +1,400 @@ +package proto + +import ( + "math/big" + + "github.com/pkg/errors" + + "github.com/wavesplatform/gowaves/pkg/crypto" + g "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" +) + +type TransactionSnapshot []AtomicSnapshot + +func (ts TransactionSnapshot) Apply(a SnapshotApplier) error { + for _, atomicSnapshot := range ts { + if !atomicSnapshot.IsGeneratedByTxDiff() { + err := atomicSnapshot.Apply(a) + if err != nil { + return errors.Wrap(err, "failed to apply transaction snapshot") + } + } + } + return nil +} + +func (ts TransactionSnapshot) ToProtobuf() *g.TransactionStateSnapshot { + var res g.TransactionStateSnapshot + for _, atomicSnapshot := range ts { + atomicSnapshot.AppendToProtobuf(&res) + } + return &res +} + +type AtomicSnapshot interface { + Apply(SnapshotApplier) error + /* is temporarily used to mark snapshots generated by tx diff that shouldn't be applied, + because balances diffs are applied later in the block. */ + IsGeneratedByTxDiff() bool + AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) +} + +type WavesBalanceSnapshot struct { + Address WavesAddress + Balance uint64 +} + +func (s WavesBalanceSnapshot) IsGeneratedByTxDiff() bool { + return true +} + +func (s WavesBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyWavesBalance(s) } + +func (s WavesBalanceSnapshot) ToProtobuf() *g.TransactionStateSnapshot_Balance { + return &g.TransactionStateSnapshot_Balance{ + Address: s.Address.Body(), + Amount: &g.Amount{ + AssetId: nil, + Amount: int64(s.Balance), + }, + } +} + +func (s WavesBalanceSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { + txSnapshots.Balances = append(txSnapshots.Balances, s.ToProtobuf()) +} + +type AssetBalanceSnapshot struct { + Address WavesAddress + AssetID crypto.Digest + Balance uint64 +} + +func (s AssetBalanceSnapshot) IsGeneratedByTxDiff() bool { + return true +} + +func (s AssetBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetBalance(s) } + +func (s AssetBalanceSnapshot) ToProtobuf() *g.TransactionStateSnapshot_Balance { + return &g.TransactionStateSnapshot_Balance{ + Address: s.Address.Body(), + Amount: &g.Amount{ + AssetId: s.AssetID.Bytes(), + Amount: int64(s.Balance), + }, + } +} + +func (s AssetBalanceSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { + txSnapshots.Balances = append(txSnapshots.Balances, s.ToProtobuf()) +} + +type DataEntriesSnapshot struct { // AccountData in pb + Address WavesAddress + DataEntries []DataEntry +} + +func (s DataEntriesSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s DataEntriesSnapshot) Apply(a SnapshotApplier) error { return a.ApplyDataEntries(s) } + +func (s DataEntriesSnapshot) ToProtobuf() *g.TransactionStateSnapshot_AccountData { + entries := make([]*g.DataTransactionData_DataEntry, 0, len(s.DataEntries)) + for _, e := range s.DataEntries { + entries = append(entries, e.ToProtobuf()) + } + return &g.TransactionStateSnapshot_AccountData{ + Address: s.Address.Body(), + Entries: entries, + } +} + +func (s DataEntriesSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { + txSnapshots.AccountData = append(txSnapshots.AccountData, s.ToProtobuf()) +} + +type AccountScriptSnapshot struct { + SenderPublicKey crypto.PublicKey + Script Script + VerifierComplexity uint64 +} + +func (s AccountScriptSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s AccountScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAccountScript(s) } + +func (s AccountScriptSnapshot) ToProtobuf() *g.TransactionStateSnapshot_AccountScript { + return &g.TransactionStateSnapshot_AccountScript{ + SenderPublicKey: s.SenderPublicKey.Bytes(), + Script: s.Script, + VerifierComplexity: int64(s.VerifierComplexity), + } +} + +func (s AccountScriptSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { + txSnapshots.AccountScripts = append(txSnapshots.AccountScripts, s.ToProtobuf()) +} + +type AssetScriptSnapshot struct { + AssetID crypto.Digest + Script Script + SenderPK crypto.PublicKey // should be removed later + Complexity uint64 +} + +func (s AssetScriptSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s AssetScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetScript(s) } + +func (s AssetScriptSnapshot) ToProtobuf() *g.TransactionStateSnapshot_AssetScript { + return &g.TransactionStateSnapshot_AssetScript{ + AssetId: s.AssetID.Bytes(), + Script: s.Script, + } +} + +func (s AssetScriptSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { + txSnapshots.AssetScripts = append(txSnapshots.AssetScripts, s.ToProtobuf()) +} + +type LeaseBalanceSnapshot struct { + Address WavesAddress + LeaseIn uint64 + LeaseOut uint64 +} + +func (s LeaseBalanceSnapshot) IsGeneratedByTxDiff() bool { + return true +} + +func (s LeaseBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseBalance(s) } + +func (s LeaseBalanceSnapshot) ToProtobuf() *g.TransactionStateSnapshot_LeaseBalance { + return &g.TransactionStateSnapshot_LeaseBalance{ + Address: s.Address.Body(), + In: int64(s.LeaseIn), + Out: int64(s.LeaseOut), + } +} + +func (s LeaseBalanceSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { + txSnapshots.LeaseBalances = append(txSnapshots.LeaseBalances, s.ToProtobuf()) +} + +type LeaseStateStatus struct { + Value LeaseStatus // can be only LeaseActive or LeaseCanceled + CancelHeight Height + CancelTransactionID *crypto.Digest +} + +type LeaseStateSnapshot struct { + LeaseID crypto.Digest + Status LeaseStateStatus + Amount uint64 + Sender WavesAddress + Recipient WavesAddress + OriginTransactionID *crypto.Digest + Height Height +} + +func (s LeaseStateSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s LeaseStateSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseState(s) } + +func (s LeaseStateSnapshot) ToProtobuf() *g.TransactionStateSnapshot_LeaseState { + res := &g.TransactionStateSnapshot_LeaseState{ + LeaseId: s.LeaseID.Bytes(), + Status: nil, + Amount: int64(s.Amount), + Sender: s.Sender.Body(), + Recipient: s.Recipient.Body(), + OriginTransactionId: s.OriginTransactionID.Bytes(), + Height: int32(s.Height), + } + switch s.Status.Value { + case LeaseActive: + res.Status = &g.TransactionStateSnapshot_LeaseState_Active{} + case LeaseCanceled: + res.Status = &g.TransactionStateSnapshot_LeaseState_Cancelled{ + Height: int32(s.Status.CancelHeight), + TransactionId: s.Status.CancelTransactionID.Bytes(), + } + } + return res +} + +func (s LeaseStateSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { + txSnapshots.LeaseStates = append(txSnapshots.LeaseStates, s.ToProtobuf()) +} + +type SponsorshipSnapshot struct { + AssetID crypto.Digest + MinSponsoredFee uint64 +} + +func (s SponsorshipSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s SponsorshipSnapshot) Apply(a SnapshotApplier) error { return a.ApplySponsorship(s) } + +func (s SponsorshipSnapshot) ToProtobuf() *g.TransactionStateSnapshot_Sponsorship { + return &g.TransactionStateSnapshot_Sponsorship{ + AssetId: s.AssetID.Bytes(), + MinFee: int64(s.MinSponsoredFee), + } +} + +func (s SponsorshipSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { + txSnapshots.Sponsorships = append(txSnapshots.Sponsorships, s.ToProtobuf()) +} + +type AliasSnapshot struct { + Address WavesAddress + Alias Alias +} + +func (s AliasSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s AliasSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAlias(s) } + +func (s AliasSnapshot) ToProtobuf() *g.TransactionStateSnapshot_Alias { + return &g.TransactionStateSnapshot_Alias{ + Address: s.Address.Body(), + Alias: s.Alias.Alias, + } +} + +func (s AliasSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { + txSnapshots.Aliases = append(txSnapshots.Aliases, s.ToProtobuf()) +} + +// FilledVolumeFeeSnapshot Filled Volume and Fee. +type FilledVolumeFeeSnapshot struct { // OrderFill + OrderID crypto.Digest + FilledVolume uint64 + FilledFee uint64 +} + +func (s FilledVolumeFeeSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s FilledVolumeFeeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyFilledVolumeAndFee(s) } + +func (s FilledVolumeFeeSnapshot) ToProtobuf() *g.TransactionStateSnapshot_OrderFill { + return &g.TransactionStateSnapshot_OrderFill{ + OrderId: s.OrderID.Bytes(), + Volume: int64(s.FilledVolume), + Fee: int64(s.FilledFee), + } +} + +func (s FilledVolumeFeeSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { + txSnapshots.OrderFills = append(txSnapshots.OrderFills, s.ToProtobuf()) +} + +type StaticAssetInfoSnapshot struct { + AssetID crypto.Digest + SourceTransactionID crypto.Digest + IssuerPublicKey crypto.PublicKey + Decimals uint8 + IsNFT bool +} + +func (s StaticAssetInfoSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s StaticAssetInfoSnapshot) Apply(a SnapshotApplier) error { return a.ApplyStaticAssetInfo(s) } + +func (s StaticAssetInfoSnapshot) ToProtobuf() *g.TransactionStateSnapshot_AssetStatic { + return &g.TransactionStateSnapshot_AssetStatic{ + AssetId: s.AssetID.Bytes(), + SourceTransactionId: s.SourceTransactionID.Bytes(), + IssuerPublicKey: s.IssuerPublicKey.Bytes(), + Decimals: int32(s.Decimals), + Nft: s.IsNFT, + } +} + +func (s StaticAssetInfoSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { + txSnapshots.AssetStatics = append(txSnapshots.AssetStatics, s.ToProtobuf()) +} + +type AssetVolumeSnapshot struct { // AssetVolume in pb + AssetID crypto.Digest + TotalQuantity big.Int // volume in protobuf + IsReissuable bool +} + +func (s AssetVolumeSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s AssetVolumeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetVolume(s) } + +func (s AssetVolumeSnapshot) ToProtobuf() *g.TransactionStateSnapshot_AssetVolume { + return &g.TransactionStateSnapshot_AssetVolume{ + AssetId: s.AssetID.Bytes(), + Reissuable: s.IsReissuable, + Volume: s.TotalQuantity.Bytes(), + } +} + +func (s AssetVolumeSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { + txSnapshots.AssetVolumes = append(txSnapshots.AssetVolumes, s.ToProtobuf()) +} + +type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb + AssetID crypto.Digest + AssetName string + AssetDescription string + ChangeHeight Height // last_updated in pb +} + +func (s AssetDescriptionSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s AssetDescriptionSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetDescription(s) } + +func (s AssetDescriptionSnapshot) ToProtobuf() *g.TransactionStateSnapshot_AssetNameAndDescription { + return &g.TransactionStateSnapshot_AssetNameAndDescription{ + AssetId: s.AssetID.Bytes(), + Name: s.AssetName, + Description: s.AssetDescription, + LastUpdated: int32(s.ChangeHeight), + } +} + +func (s AssetDescriptionSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { + txSnapshots.AssetNamesAndDescriptions = append(txSnapshots.AssetNamesAndDescriptions, s.ToProtobuf()) +} + +type SnapshotApplier interface { + ApplyWavesBalance(snapshot WavesBalanceSnapshot) error + ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) error + ApplyAssetBalance(snapshot AssetBalanceSnapshot) error + ApplyAlias(snapshot AliasSnapshot) error + ApplyStaticAssetInfo(snapshot StaticAssetInfoSnapshot) error + ApplyAssetDescription(snapshot AssetDescriptionSnapshot) error + ApplyAssetVolume(snapshot AssetVolumeSnapshot) error + ApplyAssetScript(snapshot AssetScriptSnapshot) error + ApplySponsorship(snapshot SponsorshipSnapshot) error + ApplyAccountScript(snapshot AccountScriptSnapshot) error + ApplyFilledVolumeAndFee(snapshot FilledVolumeFeeSnapshot) error + ApplyDataEntries(snapshot DataEntriesSnapshot) error + ApplyLeaseState(snapshot LeaseStateSnapshot) error +} diff --git a/pkg/proto/types.go b/pkg/proto/types.go index 5a3b5aa9a..016d1bba8 100644 --- a/pkg/proto/types.go +++ b/pkg/proto/types.go @@ -4295,3 +4295,11 @@ func (s StateHashDebug) GetStateHash() *StateHash { } return sh } + +type LeaseStatus byte + +const ( + LeaseActive LeaseStatus = iota + LeaseCanceled + //TODO: LeaseExpired (for future use) +) diff --git a/pkg/ride/meta/generated/dapp_meta.pb.go b/pkg/ride/meta/generated/dapp_meta.pb.go index 51c7ccd15..c18ab0294 100644 --- a/pkg/ride/meta/generated/dapp_meta.pb.go +++ b/pkg/ride/meta/generated/dapp_meta.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.21.12 +// protoc v4.24.3 // source: waves/lang/dapp_meta.proto package generated diff --git a/pkg/state/api.go b/pkg/state/api.go index 983f09472..f9c6a331c 100644 --- a/pkg/state/api.go +++ b/pkg/state/api.go @@ -4,14 +4,14 @@ import ( "math/big" "runtime" - "github.com/wavesplatform/gowaves/pkg/crypto" - "github.com/wavesplatform/gowaves/pkg/ride/ast" - "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/crypto" + g "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" "github.com/wavesplatform/gowaves/pkg/keyvalue" "github.com/wavesplatform/gowaves/pkg/libs/ntptime" "github.com/wavesplatform/gowaves/pkg/proto" + "github.com/wavesplatform/gowaves/pkg/ride/ast" "github.com/wavesplatform/gowaves/pkg/settings" "github.com/wavesplatform/gowaves/pkg/types" ) @@ -137,6 +137,9 @@ type StateInfo interface { RewardAtHeight(height proto.Height) (uint64, error) RewardVotes(height proto.Height) (proto.RewardVotes, error) TotalWavesAmount(height proto.Height) (uint64, error) + + // Snapshots + SnapshotsAtHeight(height proto.Height) (*g.TransactionStateSnapshot, error) } // StateModifier contains all the methods needed to modify node's state. diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 142dc1550..4c906884b 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -327,7 +327,7 @@ func (a *txAppender) commitTxApplication( tx proto.Transaction, params *appendTxParams, invocationRes *invocationResult, - applicationRes *applicationResult) (TransactionSnapshot, error) { + applicationRes *applicationResult) (proto.TransactionSnapshot, error) { // Add transaction ID to recent IDs. txID, err := tx.GetID(a.settings.AddressSchemeCharacter) if err != nil { @@ -344,7 +344,7 @@ func (a *txAppender) commitTxApplication( } currentMinerAddress := proto.MustAddressFromPublicKey(a.settings.AddressSchemeCharacter, params.currentMinerPK) - var snapshot TransactionSnapshot + var snapshot proto.TransactionSnapshot if applicationRes.status { // We only perform tx in case it has not failed. performerInfo := &performerInfo{ @@ -421,7 +421,7 @@ type appendTxParams struct { currentMinerPK crypto.PublicKey snapshotGenerator *snapshotGenerator - snapshotApplier SnapshotApplier + snapshotApplier proto.SnapshotApplier } func (a *txAppender) handleInvokeOrExchangeTransaction( @@ -452,7 +452,96 @@ func (a *txAppender) handleDefaultTransaction(tx proto.Transaction, params *appe return newApplicationResult(true, txScriptsRuns, txChanges, checkerData), nil } -func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) error { +func (a *txAppender) handleEthTx( + tx proto.Transaction, + params *appendTxParams, + accountHasVerifierScript bool, + senderAddr proto.Address, +) (*applicationResult, *invocationResult, bool, error) { + var applicationRes *applicationResult + var invocationRes *invocationResult + needToValidateBalanceDiff := false + ethTx, ok := tx.(*proto.EthereumTransaction) + if !ok { + return nil, nil, false, errors.New("failed to cast interface transaction to ethereum transaction structure") + } + kind, errResolveTx := a.ethTxKindResolver.ResolveTxKind(ethTx, params.blockRewardDistributionActivated) + if errResolveTx != nil { + return nil, nil, false, errors.Wrap(errResolveTx, "failed to guess ethereum transaction kind") + } + ethTx.TxKind = kind + var err error + switch ethTx.TxKind.(type) { + case *proto.EthereumTransferWavesTxKind, *proto.EthereumTransferAssetsErc20TxKind: + applicationRes, err = a.handleDefaultTransaction(tx, params, accountHasVerifierScript) + if err != nil { + return nil, nil, false, errors.Wrapf(err, + "failed to handle ethereum transaction (type %s) with id %s, on height %d", + ethTx.TxKind.String(), ethTx.ID.String(), params.checkerInfo.height+1) + } + // In UTX balances are always validated. + needToValidateBalanceDiff = params.validatingUtx + case *proto.EthereumInvokeScriptTxKind: + fallibleInfo := &fallibleValidationParams{ + appendTxParams: params, + senderScripted: accountHasVerifierScript, + senderAddress: senderAddr, + } + invocationRes, applicationRes, err = a.handleInvokeOrExchangeTransaction(tx, fallibleInfo) + if err != nil { + return nil, nil, false, errors.Wrapf(err, + "failed to handle ethereum invoke script transaction (type %s) with id %s, on height %d", + ethTx.TxKind.String(), ethTx.ID.String(), params.checkerInfo.height+1) + } + } + return applicationRes, invocationRes, needToValidateBalanceDiff, nil +} + +func (a *txAppender) handleTxAndScripts( + tx proto.Transaction, + params *appendTxParams, + accountHasVerifierScript bool, + senderAddr proto.Address, +) (*applicationResult, *invocationResult, bool, error) { + var applicationRes *applicationResult + var invocationRes *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, + } + var err error + invocationRes, applicationRes, err = a.handleInvokeOrExchangeTransaction(tx, fallibleInfo) + if err != nil { + return nil, nil, false, errors.Wrap(err, "failed to handle invoke or exchange transaction") + } + // Exchange and Invoke balances are validated in UTX when acceptFailed is false. + // When acceptFailed is true, balances are validated inside handleFallible(). + needToValidateBalanceDiff = params.validatingUtx && !params.acceptFailed + case proto.EthereumMetamaskTransaction: + return a.handleEthTx(tx, params, accountHasVerifierScript, senderAddr) + default: + var err error + applicationRes, err = a.handleDefaultTransaction(tx, params, accountHasVerifierScript) + if err != nil { + id, idErr := tx.GetID(a.settings.AddressSchemeCharacter) + if idErr != nil { + return nil, nil, false, errors.Wrap(err, "failed to generate transaction ID") + } + return nil, nil, false, errors.Wrapf(err, "failed to handle transaction '%s'", base58.Encode(id)) + } + // In UTX balances are always validated. + needToValidateBalanceDiff = params.validatingUtx + } + return applicationRes, invocationRes, needToValidateBalanceDiff, nil +} + +func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) (proto.TransactionSnapshot, error) { defer func() { a.sc.resetRecentTxComplexity() a.stor.dropUncertain() @@ -464,113 +553,59 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro blockID := params.checkerInfo.blockID // Check that Protobuf transactions are accepted. if err := a.checkProtobufVersion(tx, params.blockV5Activated); err != nil { - return err + return nil, err } // Check transaction for duplication of its ID. if err := a.checkDuplicateTxIds(tx, a.recentTxIds, params.block.Timestamp); err != nil { - return errs.Extend(err, "check duplicate tx ids") + return nil, errs.Extend(err, "check duplicate tx ids") } // Verify tx signature and internal data correctness. senderAddr, err := tx.GetSender(a.settings.AddressSchemeCharacter) if err != nil { - return errs.Extend(err, "failed to get sender addr by pk") + return nil, errs.Extend(err, "failed to get sender addr by pk") } // senderWavesAddr needs only for newestAccountHasVerifier check senderWavesAddr, err := senderAddr.ToWavesAddress(a.settings.AddressSchemeCharacter) if err != nil { - return errors.Wrapf(err, "failed to transform (%T) address type to WavesAddress type", senderAddr) + return nil, errors.Wrapf(err, "failed to transform (%T) address type to WavesAddress type", senderAddr) } accountHasVerifierScript, err := a.stor.scriptsStorage.newestAccountHasVerifier(senderWavesAddr) if err != nil { - return errs.Extend(err, "account has verifier") + return nil, errs.Extend(err, "account has verifier") } - if err := a.verifyWavesTxSigAndData(tx, params, accountHasVerifierScript); err != nil { - return errs.Extend(err, "tx signature or data verification failed") + if err = a.verifyWavesTxSigAndData(tx, params, accountHasVerifierScript); err != nil { + return nil, errs.Extend(err, "tx signature or data verification failed") } // 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} - invocationResult, applicationRes, err = a.handleInvokeOrExchangeTransaction(tx, fallibleInfo) - if err != nil { - return errors.Wrap(err, "failed to handle invoke or exchange transaction") - } - // Exchange and Invoke balances are validated in UTX when acceptFailed is false. - // When acceptFailed is true, balances are validated inside handleFallible(). - needToValidateBalanceDiff = params.validatingUtx && !params.acceptFailed - case proto.EthereumMetamaskTransaction: - ethTx, ok := tx.(*proto.EthereumTransaction) - if !ok { - return errors.New("failed to cast interface transaction to ethereum transaction structure") - } - kind, err := a.ethTxKindResolver.ResolveTxKind(ethTx, params.blockRewardDistributionActivated) - if err != nil { - return errors.Wrap(err, "failed to guess ethereum transaction kind") - } - ethTx.TxKind = kind - - switch ethTx.TxKind.(type) { - case *proto.EthereumTransferWavesTxKind, *proto.EthereumTransferAssetsErc20TxKind: - applicationRes, err = a.handleDefaultTransaction(tx, params, accountHasVerifierScript) - if err != nil { - return errors.Wrapf(err, "failed to handle ethereum transaction (type %s) with id %s, on height %d", - ethTx.TxKind.String(), ethTx.ID.String(), params.checkerInfo.height+1) - } - // In UTX balances are always validated. - needToValidateBalanceDiff = params.validatingUtx - case *proto.EthereumInvokeScriptTxKind: - fallibleInfo := &fallibleValidationParams{ - appendTxParams: params, - senderScripted: accountHasVerifierScript, - senderAddress: senderAddr, - } - invocationResult, applicationRes, err = a.handleInvokeOrExchangeTransaction(tx, fallibleInfo) - if err != nil { - return errors.Wrapf(err, "failed to handle ethereum invoke script transaction (type %s) with id %s, on height %d", - ethTx.TxKind.String(), ethTx.ID.String(), params.checkerInfo.height+1) - } - } - default: - applicationRes, err = a.handleDefaultTransaction(tx, params, accountHasVerifierScript) - if err != nil { - id, idErr := tx.GetID(a.settings.AddressSchemeCharacter) - if idErr != nil { - return errors.Wrap(err, "failed to generate transaction ID") - } - return errors.Wrapf(err, "failed to handle transaction '%s'", base58.Encode(id)) - } - // In UTX balances are always validated. - needToValidateBalanceDiff = params.validatingUtx + applicationRes, invocationRes, needToValidateBalanceDiff, err := + a.handleTxAndScripts(tx, params, accountHasVerifierScript, senderAddr) + if err != nil { + return nil, err } if needToValidateBalanceDiff { // Validate balance diff for negative balances. - if err := a.diffApplier.validateTxDiff(applicationRes.changes.diff, a.diffStor); err != nil { - return errs.Extend(err, "validate transaction diff") + if err = a.diffApplier.validateTxDiff(applicationRes.changes.diff, a.diffStor); err != nil { + return nil, errs.Extend(err, "validate transaction diff") } } // Check complexity limits and scripts runs limits. if err := a.checkScriptsLimits(a.totalScriptsRuns+applicationRes.totalScriptsRuns, blockID); err != nil { - return errs.Extend(errors.Errorf("%s: %v", blockID.String(), err), "check scripts limits") + return nil, errs.Extend(errors.Errorf("%s: %v", blockID.String(), err), "check scripts limits") } // Perform state changes, save balance changes, write tx to storage. txID, err := tx.GetID(a.settings.AddressSchemeCharacter) if err != nil { - return errs.Extend(err, "get transaction id") + return nil, errs.Extend(err, "get transaction id") } // invocationResult may be empty if it was not an Invoke Transaction - snapshot, err := a.commitTxApplication(tx, params, invocationResult, applicationRes) + snapshot, err := a.commitTxApplication(tx, params, invocationRes, 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 + return nil, err } // a temporary dummy for linters if len(snapshot) > snapshotLimit { @@ -578,28 +613,28 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro } // Store additional data for API: transaction by address. if !params.validatingUtx && a.buildApiData { - if err := a.saveTransactionIdByAddresses(applicationRes.changes.addresses(), txID, blockID); err != nil { - return errs.Extend(err, "save transaction id by addresses") + if err = a.saveTransactionIdByAddresses(applicationRes.changes.addresses(), txID, blockID); err != nil { + return nil, errs.Extend(err, "save transaction id by addresses") } } - return nil + return snapshot, nil } // rewards and 60% of the fee to the previous miner. -func (a *txAppender) createInitialBlockSnapshot(minerAndRewardDiff txDiff) (TransactionSnapshot, error) { +func (a *txAppender) createInitialBlockSnapshot(minerAndRewardDiff txDiff) (proto.TransactionSnapshot, error) { addrWavesBalanceDiff, _, err := balanceDiffFromTxDiff(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 + var snapshot proto.TransactionSnapshot for wavesAddress, diffAmount := range addrWavesBalanceDiff { var fullBalance balanceProfile 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{ + newBalance := &proto.WavesBalanceSnapshot{ Address: wavesAddress, Balance: uint64(int64(fullBalance.balance) + diffAmount.balance), } @@ -703,7 +738,7 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { return err } // Check and append transactions. - + var blockSnapshots proto.TransactionSnapshot for _, tx := range params.transactions { appendTxArgs := &appendTxParams{ chans: params.chans, @@ -723,16 +758,18 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { snapshotGenerator: &snapshotGenerator, snapshotApplier: &snapshotApplier, } - if err := a.appendTx(tx, appendTxArgs); err != nil { - return err + txSnapshots, errAppendTx := a.appendTx(tx, appendTxArgs) + if errAppendTx != nil { + return errAppendTx } + blockSnapshots = append(blockSnapshots, txSnapshots...) } - // Save fee distribution of this block. - // This will be needed for createMinerAndRewardDiff() of next block due to NG. - if err := a.blockDiffer.saveCurFeeDistr(params.block); err != nil { + if err = a.stor.snapshots.saveSnapshots(params.block.BlockID(), params.height, blockSnapshots); err != nil { return err } - return nil + // Save fee distribution of this block. + // This will be needed for createMinerAndRewardDiff() of next block due to NG. + return a.blockDiffer.saveCurFeeDistr(params.block) } // used only in tests now. All diffs are applied in snapshotApplier. @@ -1005,7 +1042,7 @@ func (a *txAppender) validateNextTx(tx proto.Transaction, currentTimestamp, pare snapshotGenerator: &snapshotGenerator, snapshotApplier: &snapshotApplier, } - err = a.appendTx(tx, appendTxArgs) + _, err = a.appendTx(tx, appendTxArgs) if err != nil { return proto.NewInfoMsg(err) } diff --git a/pkg/state/headers_validation_test.go b/pkg/state/headers_validation_test.go index 75c343e14..9aa5421a3 100644 --- a/pkg/state/headers_validation_test.go +++ b/pkg/state/headers_validation_test.go @@ -141,3 +141,20 @@ func TestHeadersValidation(t *testing.T) { err = st.RollbackToHeight(1) assert.NoError(t, err, "failed to rollback state") } + +func TestSnapshots(t *testing.T) { + blocks, err := readBlocksFromTestPath(blocksNumber) + if err != nil { + t.Fatalf("Can not read blocks from blockchain file: %v\n", err) + } + var ( + sets = settings.MainNetSettings + scheme = sets.AddressSchemeCharacter + st = newTestState(t, true, stateParams(), sets) + ) + + err = applyBlocks(t, blocks, st, scheme) + assert.NoError(t, err, "failed to apply correct blocks") + err = st.RollbackToHeight(1) + assert.NoError(t, err, "failed to rollback state") +} diff --git a/pkg/state/history_storage.go b/pkg/state/history_storage.go index 5419336c2..3448a36ed 100644 --- a/pkg/state/history_storage.go +++ b/pkg/state/history_storage.go @@ -41,6 +41,7 @@ const ( stateHash hitSource feeDistr + snapshots ) type blockchainEntityProperties struct { diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index 42d680510..46b14616b 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -664,7 +664,7 @@ func (ia *invokeApplier) fallibleValidation(tx proto.Transaction, info *addlInvo Recipient: recipientAddress, Amount: uint64(a.Amount), Height: info.blockInfo.Height, - Status: LeaseActive, + Status: proto.LeaseActive, } ia.stor.leases.addLeasingUncertain(a.ID, l) diff --git a/pkg/state/keys.go b/pkg/state/keys.go index 0601df181..97ea22f38 100644 --- a/pkg/state/keys.go +++ b/pkg/state/keys.go @@ -25,6 +25,7 @@ const ( approvedFeaturesKeySize = 1 + 2 votesFeaturesKeySize = 1 + 2 invokeResultKeySize = 1 + crypto.DigestSize + snapshotKeySize = 1 + 8 ) // Primary prefixes for storage keys @@ -123,6 +124,8 @@ const ( // Hit source data. hitSourceKeyPrefix + + snapshotsKeyPrefix ) var ( @@ -180,6 +183,8 @@ func prefixByEntity(entity blockchainEntity) ([]byte, error) { return []byte{blocksInfoKeyPrefix}, nil case rewardChanges: return []byte{rewardChangesKeyPrefix}, nil + case snapshots: + return []byte{snapshotsKeyPrefix}, nil default: return nil, errors.New("bad entity type") } @@ -685,3 +690,14 @@ func (k *hitSourceKey) bytes() []byte { binary.BigEndian.PutUint64(buf[1:], k.height) return buf } + +type snapshotsKey struct { + height uint64 +} + +func (k *snapshotsKey) bytes() []byte { + buf := make([]byte, snapshotKeySize) + buf[0] = snapshotsKeyPrefix + binary.BigEndian.PutUint64(buf[1:], k.height) + return buf +} diff --git a/pkg/state/leases.go b/pkg/state/leases.go index cf754da6f..dca931269 100644 --- a/pkg/state/leases.go +++ b/pkg/state/leases.go @@ -13,14 +13,6 @@ import ( "github.com/wavesplatform/gowaves/pkg/proto" ) -type LeaseStatus byte - -const ( - LeaseActive LeaseStatus = iota - LeaseCanceled - //TODO: LeaseExpired (for future use) -) - type leaseRecordForStateHashes struct { id *crypto.Digest active byte @@ -46,14 +38,14 @@ type leasing struct { Recipient proto.WavesAddress `cbor:"1,keyasint"` Amount uint64 `cbor:"2,keyasint"` Height uint64 `cbor:"3,keyasint"` - Status LeaseStatus `cbor:"4,keyasint"` + Status proto.LeaseStatus `cbor:"4,keyasint"` OriginTransactionID *crypto.Digest `cbor:"5,keyasint,omitempty"` CancelHeight uint64 `cbor:"7,keyasint,omitempty"` CancelTransactionID *crypto.Digest `cbor:"8,keyasint,omitempty"` } func (l *leasing) isActive() bool { - return l.Status == LeaseActive + return l.Status == proto.LeaseActive } func (l *leasing) marshalBinary() ([]byte, error) { @@ -114,7 +106,7 @@ func (l *leases) cancelLeases(bySenders map[proto.WavesAddress]struct{}, blockID return errors.Wrap(err, "failed to unmarshal lease key") } zap.S().Infof("State: cancelling lease %s", k.leaseID.String()) - record.Status = LeaseCanceled + record.Status = proto.LeaseCanceled if err := l.addLeasing(k.leaseID, record, blockID); err != nil { return errors.Wrap(err, "failed to save lease to storage") } @@ -137,7 +129,7 @@ func (l *leases) cancelLeasesToDisabledAliases(scheme proto.Scheme, height proto return nil, errors.Wrapf(err, "failed to get newest leasing info by id %q", leaseID.String()) } zap.S().Infof("State: canceling lease %s", leaseID) - record.Status = LeaseCanceled + record.Status = proto.LeaseCanceled record.CancelHeight = height if err := l.addLeasing(leaseID, record, blockID); err != nil { return nil, errors.Wrapf(err, "failed to save leasing %q to storage", leaseID) @@ -270,7 +262,7 @@ func (l *leases) cancelLeasing(id crypto.Digest, blockID proto.BlockID, height u if err != nil { return errors.Errorf("failed to get leasing info: %v", err) } - leasing.Status = LeaseCanceled + leasing.Status = proto.LeaseCanceled leasing.CancelHeight = height leasing.CancelTransactionID = txID return l.addLeasing(id, leasing, blockID) @@ -281,7 +273,7 @@ func (l *leases) cancelLeasingUncertain(id crypto.Digest, height uint64, txID *c if err != nil { return errors.Errorf("failed to get leasing info: %v", err) } - leasing.Status = LeaseCanceled + leasing.Status = proto.LeaseCanceled leasing.CancelTransactionID = txID leasing.CancelHeight = height l.addLeasingUncertain(id, leasing) diff --git a/pkg/state/leases_test.go b/pkg/state/leases_test.go index 57c02be7b..7222f3658 100644 --- a/pkg/state/leases_test.go +++ b/pkg/state/leases_test.go @@ -30,7 +30,7 @@ func createLease(t *testing.T, sender string, id crypto.Digest) *leasing { Recipient: recipientAddr, Sender: senderAddr, Amount: 10, - Status: LeaseActive, + Status: proto.LeaseActive, } } @@ -155,7 +155,7 @@ func TestCancelLeasing(t *testing.T) { assert.NoError(t, err, "failed to add leasing") err = to.leases.cancelLeasing(leaseID, blockID0, to.stor.rw.height, &txID) assert.NoError(t, err, "failed to cancel leasing") - r.Status = LeaseCanceled + r.Status = proto.LeaseCanceled r.CancelHeight = 1 r.CancelTransactionID = &txID to.stor.flush(t) diff --git a/pkg/state/snapshot_applier.go b/pkg/state/snapshot_applier.go index 5375925ed..02d9726b3 100644 --- a/pkg/state/snapshot_applier.go +++ b/pkg/state/snapshot_applier.go @@ -44,7 +44,7 @@ func newSnapshotApplierStorages(stor *blockchainEntitiesStorage) snapshotApplier } } -var _ = SnapshotApplier((*blockSnapshotsApplier)(nil)) +var _ = proto.SnapshotApplier((*blockSnapshotsApplier)(nil)) type blockSnapshotsApplierInfo struct { ci *checkerInfo @@ -83,7 +83,7 @@ func (s blockSnapshotsApplierInfo) StateActionsCounter() *proto.StateActionsCoun return s.stateActionsCounter } -func (a *blockSnapshotsApplier) ApplyWavesBalance(snapshot WavesBalanceSnapshot) error { +func (a *blockSnapshotsApplier) ApplyWavesBalance(snapshot proto.WavesBalanceSnapshot) error { addrID := snapshot.Address.ID() profile, err := a.stor.balances.wavesBalance(addrID) if err != nil { @@ -98,7 +98,7 @@ func (a *blockSnapshotsApplier) ApplyWavesBalance(snapshot WavesBalanceSnapshot) return nil } -func (a *blockSnapshotsApplier) ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) error { +func (a *blockSnapshotsApplier) ApplyLeaseBalance(snapshot proto.LeaseBalanceSnapshot) error { addrID := snapshot.Address.ID() var err error profile, err := a.stor.balances.wavesBalance(addrID) @@ -115,17 +115,17 @@ func (a *blockSnapshotsApplier) ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) return nil } -func (a *blockSnapshotsApplier) ApplyAssetBalance(snapshot AssetBalanceSnapshot) error { +func (a *blockSnapshotsApplier) ApplyAssetBalance(snapshot proto.AssetBalanceSnapshot) error { addrID := snapshot.Address.ID() assetID := proto.AssetIDFromDigest(snapshot.AssetID) return a.stor.balances.setAssetBalance(addrID, assetID, snapshot.Balance, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyAlias(snapshot AliasSnapshot) error { +func (a *blockSnapshotsApplier) ApplyAlias(snapshot proto.AliasSnapshot) error { return a.stor.aliases.createAlias(snapshot.Alias.Alias, snapshot.Address, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyStaticAssetInfo(snapshot StaticAssetInfoSnapshot) error { +func (a *blockSnapshotsApplier) ApplyStaticAssetInfo(snapshot proto.StaticAssetInfoSnapshot) error { assetID := proto.AssetIDFromDigest(snapshot.AssetID) assetFullInfo := &assetInfo{ assetConstInfo: assetConstInfo{ @@ -140,7 +140,7 @@ func (a *blockSnapshotsApplier) ApplyStaticAssetInfo(snapshot StaticAssetInfoSna return a.stor.assets.issueAsset(assetID, assetFullInfo, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyAssetDescription(snapshot AssetDescriptionSnapshot) error { +func (a *blockSnapshotsApplier) ApplyAssetDescription(snapshot proto.AssetDescriptionSnapshot) error { change := &assetInfoChange{ newName: snapshot.AssetName, newDescription: snapshot.AssetDescription, @@ -149,7 +149,7 @@ func (a *blockSnapshotsApplier) ApplyAssetDescription(snapshot AssetDescriptionS return a.stor.assets.updateAssetInfo(snapshot.AssetID, change, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyAssetVolume(snapshot AssetVolumeSnapshot) error { +func (a *blockSnapshotsApplier) ApplyAssetVolume(snapshot proto.AssetVolumeSnapshot) error { assetID := proto.AssetIDFromDigest(snapshot.AssetID) assetFullInfo, err := a.stor.assets.newestAssetInfo(assetID) if err != nil { @@ -160,7 +160,7 @@ func (a *blockSnapshotsApplier) ApplyAssetVolume(snapshot AssetVolumeSnapshot) e return a.stor.assets.storeAssetInfo(assetID, assetFullInfo, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyAssetScript(snapshot AssetScriptSnapshot) error { +func (a *blockSnapshotsApplier) ApplyAssetScript(snapshot proto.AssetScriptSnapshot) error { // estimation := ride.TreeEstimation{ // Estimation: int(snapshot.Complexity), // Verifier: int(snapshot.Complexity), @@ -180,11 +180,11 @@ func (a *blockSnapshotsApplier) ApplyAssetScript(snapshot AssetScriptSnapshot) e return a.stor.scriptsStorage.setAssetScript(snapshot.AssetID, snapshot.Script, snapshot.SenderPK, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplySponsorship(snapshot SponsorshipSnapshot) error { +func (a *blockSnapshotsApplier) ApplySponsorship(snapshot proto.SponsorshipSnapshot) error { return a.stor.sponsoredAssets.sponsorAsset(snapshot.AssetID, snapshot.MinSponsoredFee, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyAccountScript(snapshot AccountScriptSnapshot) error { +func (a *blockSnapshotsApplier) ApplyAccountScript(snapshot proto.AccountScriptSnapshot) error { addr, err := proto.NewAddressFromPublicKey(a.info.Scheme(), snapshot.SenderPublicKey) if err != nil { return errors.Wrapf(err, "failed to create address from scheme %d and PK %q", @@ -208,12 +208,12 @@ func (a *blockSnapshotsApplier) ApplyAccountScript(snapshot AccountScriptSnapsho return a.stor.scriptsStorage.setAccountScript(addr, snapshot.Script, snapshot.SenderPublicKey, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyFilledVolumeAndFee(snapshot FilledVolumeFeeSnapshot) error { +func (a *blockSnapshotsApplier) ApplyFilledVolumeAndFee(snapshot proto.FilledVolumeFeeSnapshot) error { return a.stor.ordersVolumes.storeFilled(snapshot.OrderID.Bytes(), snapshot.FilledVolume, snapshot.FilledFee, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyDataEntries(snapshot DataEntriesSnapshot) error { +func (a *blockSnapshotsApplier) ApplyDataEntries(snapshot proto.DataEntriesSnapshot) error { blockID := a.info.BlockID() for _, entry := range snapshot.DataEntries { if err := a.stor.accountsDataStor.appendEntry(snapshot.Address, entry, blockID); err != nil { @@ -223,7 +223,7 @@ func (a *blockSnapshotsApplier) ApplyDataEntries(snapshot DataEntriesSnapshot) e return nil } -func (a *blockSnapshotsApplier) ApplyLeaseState(snapshot LeaseStateSnapshot) error { +func (a *blockSnapshotsApplier) ApplyLeaseState(snapshot proto.LeaseStateSnapshot) error { l := &leasing{ Sender: snapshot.Sender, Recipient: snapshot.Recipient, diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index 95e6aa958..8f671b3b1 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -81,15 +81,15 @@ func (assetDiff addressAssetBalanceDiff) appendOnlySender( } } -func (sg *snapshotGenerator) generateSnapshotForGenesisTx(balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForGenesisTx(balanceChanges txDiff) (proto.TransactionSnapshot, error) { return sg.generateBalancesSnapshot(balanceChanges) } -func (sg *snapshotGenerator) generateSnapshotForPaymentTx(balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForPaymentTx(balanceChanges txDiff) (proto.TransactionSnapshot, error) { return sg.generateBalancesSnapshot(balanceChanges) } -func (sg *snapshotGenerator) generateSnapshotForTransferTx(balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForTransferTx(balanceChanges txDiff) (proto.TransactionSnapshot, error) { return sg.generateBalancesSnapshot(balanceChanges) } @@ -100,21 +100,21 @@ type scriptInformation struct { func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, txID crypto.Digest, senderPK crypto.PublicKey, assetInfo assetInfo, balanceChanges txDiff, - scriptInformation *scriptInformation) (TransactionSnapshot, error) { - var snapshot TransactionSnapshot + scriptInformation *scriptInformation) (proto.TransactionSnapshot, error) { + var snapshot proto.TransactionSnapshot addrWavesBalanceDiff, addrAssetBalanceDiff, err := balanceDiffFromTxDiff(balanceChanges, sg.scheme) 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 + var specialAssetSnapshot *proto.AssetBalanceSnapshot for key, diffAmount := range addrAssetBalanceDiff { if key.asset == proto.AssetIDFromDigest(assetID) { // remove the element from the array delete(addrAssetBalanceDiff, key) - specialAssetSnapshot = &AssetBalanceSnapshot{ + specialAssetSnapshot = &proto.AssetBalanceSnapshot{ Address: key.address, AssetID: assetID, Balance: uint64(diffAmount), @@ -122,7 +122,7 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t } } - issueStaticInfoSnapshot := &StaticAssetInfoSnapshot{ + issueStaticInfoSnapshot := &proto.StaticAssetInfoSnapshot{ AssetID: assetID, IssuerPublicKey: senderPK, SourceTransactionID: txID, @@ -130,14 +130,14 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t IsNFT: assetInfo.isNFT(), } - assetDescription := &AssetDescriptionSnapshot{ + assetDescription := &proto.AssetDescriptionSnapshot{ AssetID: assetID, AssetName: assetInfo.name, AssetDescription: assetInfo.description, ChangeHeight: assetInfo.lastNameDescChangeHeight, } - assetReissuability := &AssetVolumeSnapshot{ + assetReissuability := &proto.AssetVolumeSnapshot{ AssetID: assetID, IsReissuable: assetInfo.reissuable, TotalQuantity: assetInfo.quantity, @@ -146,7 +146,7 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) if scriptInformation != nil { - assetScriptSnapshot := &AssetScriptSnapshot{ + assetScriptSnapshot := &proto.AssetScriptSnapshot{ AssetID: assetID, Script: scriptInformation.script, Complexity: uint64(scriptInformation.complexity), @@ -174,7 +174,7 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t } func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, - change assetReissueChange, balanceChanges txDiff) (TransactionSnapshot, error) { + change assetReissueChange, balanceChanges txDiff) (proto.TransactionSnapshot, error) { quantityDiff := big.NewInt(change.diff) assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) if err != nil { @@ -186,7 +186,7 @@ func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } - assetReissuability := &AssetVolumeSnapshot{ + assetReissuability := &proto.AssetVolumeSnapshot{ AssetID: assetID, TotalQuantity: *resQuantity, IsReissuable: change.reissuable, @@ -196,7 +196,7 @@ func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, } func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, change assetBurnChange, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { quantityDiff := big.NewInt(change.diff) assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) if err != nil { @@ -208,7 +208,7 @@ func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, ch if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } - assetReissuability := &AssetVolumeSnapshot{ + assetReissuability := &proto.AssetVolumeSnapshot{ AssetID: assetID, TotalQuantity: *resQuantity, IsReissuable: assetInfo.reissuable, @@ -219,7 +219,7 @@ func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, ch func (sg *snapshotGenerator) generateSnapshotForExchangeTx(sellOrder proto.Order, sellFee uint64, buyOrder proto.Order, buyFee uint64, volume uint64, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") @@ -247,7 +247,7 @@ func (sg *snapshotGenerator) generateSnapshotForExchangeTx(sellOrder proto.Order } func (sg *snapshotGenerator) generateSnapshotForLeaseTx(lease leasing, leaseID crypto.Digest, - originalTxID crypto.Digest, balanceChanges txDiff) (TransactionSnapshot, error) { + originalTxID crypto.Digest, balanceChanges txDiff) (proto.TransactionSnapshot, error) { var err error snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { @@ -266,7 +266,7 @@ func (sg *snapshotGenerator) generateSnapshotForLeaseTx(lease leasing, leaseID c func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Digest, oldLease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, - cancelHeight uint64, balanceChanges txDiff) (TransactionSnapshot, error) { + cancelHeight uint64, balanceChanges txDiff) (proto.TransactionSnapshot, error) { var err error snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { @@ -278,8 +278,8 @@ func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Diges if err != nil { return nil, errors.Wrap(err, "failed to generate snapshots for a lease transaction") } - leaseStatusSnapshot.Status = LeaseStateStatus{ - Value: LeaseCanceled, + leaseStatusSnapshot.Status = proto.LeaseStateStatus{ + Value: proto.LeaseCanceled, CancelHeight: cancelHeight, CancelTransactionID: txID, } @@ -289,12 +289,12 @@ func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Diges } func (sg *snapshotGenerator) generateSnapshotForCreateAliasTx(senderAddress proto.WavesAddress, alias proto.Alias, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - aliasSnapshot := &AliasSnapshot{ + aliasSnapshot := &proto.AliasSnapshot{ Address: senderAddress, Alias: alias, } @@ -302,17 +302,19 @@ func (sg *snapshotGenerator) generateSnapshotForCreateAliasTx(senderAddress prot return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForMassTransferTx(balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForMassTransferTx( + balanceChanges txDiff, +) (proto.TransactionSnapshot, error) { return sg.generateBalancesSnapshot(balanceChanges) } func (sg *snapshotGenerator) generateSnapshotForDataTx(senderAddress proto.WavesAddress, entries []proto.DataEntry, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - dataEntriesSnapshot := &DataEntriesSnapshot{ + dataEntriesSnapshot := &proto.DataEntriesSnapshot{ Address: senderAddress, DataEntries: entries, } @@ -321,12 +323,12 @@ func (sg *snapshotGenerator) generateSnapshotForDataTx(senderAddress proto.Waves } func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Digest, - minAssetFee uint64, balanceChanges txDiff) (TransactionSnapshot, error) { + minAssetFee uint64, balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - sponsorshipSnapshot := &SponsorshipSnapshot{ + sponsorshipSnapshot := &proto.SponsorshipSnapshot{ AssetID: assetID, MinSponsoredFee: minAssetFee, } @@ -335,12 +337,12 @@ func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Dig } func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.PublicKey, script proto.Script, - complexity int, balanceChanges txDiff) (TransactionSnapshot, error) { + complexity int, balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - sponsorshipSnapshot := &AccountScriptSnapshot{ + sponsorshipSnapshot := &proto.AccountScriptSnapshot{ SenderPublicKey: senderPK, Script: script, VerifierComplexity: uint64(complexity), @@ -350,13 +352,13 @@ func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.Publ } func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, - complexity int, senderPK crypto.PublicKey, balanceChanges txDiff) (TransactionSnapshot, error) { + complexity int, senderPK crypto.PublicKey, balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - sponsorshipSnapshot := &AssetScriptSnapshot{ + sponsorshipSnapshot := &proto.AssetScriptSnapshot{ AssetID: assetID, Script: script, Complexity: uint64(complexity), @@ -368,29 +370,29 @@ func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto. func (sg *snapshotGenerator) generateSnapshotForInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff, - txPublicKey crypto.PublicKey) (TransactionSnapshot, error) { + txPublicKey crypto.PublicKey) (proto.TransactionSnapshot, error) { return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges, txPublicKey) } func (sg *snapshotGenerator) generateSnapshotForInvokeExpressionTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff, - txPublicKey crypto.PublicKey) (TransactionSnapshot, error) { + txPublicKey crypto.PublicKey) (proto.TransactionSnapshot, error) { return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges, txPublicKey) } func (sg *snapshotGenerator) generateSnapshotForEthereumInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff, - txPublicKey crypto.PublicKey) (TransactionSnapshot, error) { + txPublicKey crypto.PublicKey) (proto.TransactionSnapshot, error) { return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges, txPublicKey) } func (sg *snapshotGenerator) generateSnapshotForUpdateAssetInfoTx(assetID crypto.Digest, assetName string, - assetDescription string, changeHeight proto.Height, balanceChanges txDiff) (TransactionSnapshot, error) { + assetDescription string, changeHeight proto.Height, balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - sponsorshipSnapshot := &AssetDescriptionSnapshot{ + sponsorshipSnapshot := &proto.AssetDescriptionSnapshot{ AssetID: assetID, AssetName: assetName, AssetDescription: assetDescription, @@ -462,8 +464,8 @@ func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( info *performerInfo, txID crypto.Digest, assetBalanceDiff addressAssetBalanceDiff, - senderPK crypto.PublicKey) ([]AtomicSnapshot, error) { - var atomicSnapshots []AtomicSnapshot + senderPK crypto.PublicKey) ([]proto.AtomicSnapshot, error) { + var atomicSnapshots []proto.AtomicSnapshot assetInf := assetInfo{ assetConstInfo: assetConstInfo{ tail: proto.DigestTail(action.ID), @@ -480,7 +482,7 @@ func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( }, } - issueStaticInfoSnapshot := &StaticAssetInfoSnapshot{ + issueStaticInfoSnapshot := &proto.StaticAssetInfoSnapshot{ AssetID: action.ID, IssuerPublicKey: senderPK, SourceTransactionID: txID, @@ -488,14 +490,14 @@ func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( IsNFT: assetInf.isNFT(), } - assetDescription := &AssetDescriptionSnapshot{ + assetDescription := &proto.AssetDescriptionSnapshot{ AssetID: action.ID, AssetName: assetInf.name, AssetDescription: assetInf.description, ChangeHeight: assetInf.lastNameDescChangeHeight, } - assetReissuability := &AssetVolumeSnapshot{ + assetReissuability := &proto.AssetVolumeSnapshot{ AssetID: action.ID, IsReissuable: assetInf.reissuable, TotalQuantity: assetInf.quantity, @@ -511,7 +513,7 @@ func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( } } if scriptInfo != nil { - assetScriptSnapshot := &AssetScriptSnapshot{ + assetScriptSnapshot := &proto.AssetScriptSnapshot{ AssetID: action.ID, Script: scriptInfo.script, Complexity: uint64(scriptInfo.complexity), @@ -531,15 +533,15 @@ func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( func (sg *snapshotGenerator) atomicActionsFromReissueAction( action proto.ReissueScriptAction, assetBalanceDiff addressAssetBalanceDiff, - issuer proto.WavesAddress) ([]AtomicSnapshot, error) { - var atomicSnapshots []AtomicSnapshot + issuer proto.WavesAddress) ([]proto.AtomicSnapshot, error) { + var atomicSnapshots []proto.AtomicSnapshot assetInf, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(action.AssetID)) if err != nil { return nil, err } quantityDiff := big.NewInt(action.Quantity) resQuantity := assetInf.quantity.Add(&assetInf.quantity, quantityDiff) - assetReissuability := &AssetVolumeSnapshot{ + assetReissuability := &proto.AssetVolumeSnapshot{ AssetID: action.AssetID, TotalQuantity: *resQuantity, IsReissuable: action.Reissuable, @@ -552,8 +554,8 @@ func (sg *snapshotGenerator) atomicActionsFromReissueAction( func (sg *snapshotGenerator) atomicActionsFromBurnAction( action proto.BurnScriptAction, assetBalanceDiff addressAssetBalanceDiff, - issuer proto.WavesAddress) ([]AtomicSnapshot, error) { - var atomicSnapshots []AtomicSnapshot + issuer proto.WavesAddress) ([]proto.AtomicSnapshot, error) { + var atomicSnapshots []proto.AtomicSnapshot var assetInf *assetInfo assetInf, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(action.AssetID)) if err != nil { @@ -561,7 +563,7 @@ func (sg *snapshotGenerator) atomicActionsFromBurnAction( } quantityDiff := big.NewInt(action.Quantity) resQuantity := assetInf.quantity.Sub(&assetInf.quantity, quantityDiff) - assetReissuability := &AssetVolumeSnapshot{ + assetReissuability := &proto.AssetVolumeSnapshot{ AssetID: action.AssetID, TotalQuantity: *resQuantity, IsReissuable: assetInf.reissuable, @@ -575,8 +577,8 @@ func (sg *snapshotGenerator) atomicActionsFromLeaseAction( action proto.LeaseScriptAction, info *performerInfo, txID crypto.Digest, - sender proto.WavesAddress) ([]AtomicSnapshot, error) { - var atomicSnapshots []AtomicSnapshot + sender proto.WavesAddress) ([]proto.AtomicSnapshot, error) { + var atomicSnapshots []proto.AtomicSnapshot var err error var recipientAddr proto.WavesAddress @@ -593,7 +595,7 @@ func (sg *snapshotGenerator) atomicActionsFromLeaseAction( Recipient: recipientAddr, Amount: uint64(action.Amount), Height: info.height, - Status: LeaseActive, + Status: proto.LeaseActive, } var amount = int64(l.Amount) leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := @@ -610,8 +612,8 @@ func (sg *snapshotGenerator) atomicActionsFromLeaseAction( func (sg *snapshotGenerator) atomicSnapshotsFromLeaseCancelAction( action proto.LeaseCancelScriptAction, - txID crypto.Digest) ([]AtomicSnapshot, error) { - var atomicSnapshots []AtomicSnapshot + txID crypto.Digest) ([]proto.AtomicSnapshot, error) { + var atomicSnapshots []proto.AtomicSnapshot // TODO what if the leasing is not in the stor yet? lease and leaseCancel in the same contract? leasingInfo, err := sg.stor.leases.leasingInfo(action.LeaseID) if err != nil { @@ -641,8 +643,8 @@ func (sg *snapshotGenerator) collectBalanceAndSnapshotFromAction( txID crypto.Digest, senderAddress proto.WavesAddress, senderPK crypto.PublicKey, -) ([]AtomicSnapshot, error) { - var atomicSnapshots []AtomicSnapshot +) ([]proto.AtomicSnapshot, error) { + var atomicSnapshots []proto.AtomicSnapshot switch a := action.(type) { case *proto.DataEntryScriptAction: // snapshots store data entries in a different format, so we convert the actions to this format @@ -661,7 +663,7 @@ func (sg *snapshotGenerator) collectBalanceAndSnapshotFromAction( return nil, err } case *proto.SponsorshipScriptAction: - sponsorshipSnapshot := &SponsorshipSnapshot{ + sponsorshipSnapshot := &proto.SponsorshipSnapshot{ AssetID: a.AssetID, MinSponsoredFee: uint64(a.MinFee), } @@ -727,9 +729,9 @@ func (sg *snapshotGenerator) atomicSnapshotsFromScriptActions( blockHeight uint64, info *performerInfo, txID crypto.Digest, - txPublicKey crypto.PublicKey) ([]AtomicSnapshot, error) { + txPublicKey crypto.PublicKey) ([]proto.AtomicSnapshot, error) { var dataEntries = make(SenderDataEntries) - var atomicSnapshots []AtomicSnapshot + var atomicSnapshots []proto.AtomicSnapshot for _, action := range actions { senderAddress, senderPK, err := senderFromScriptAction(action, txPublicKey, sg.scheme) if err != nil { @@ -745,7 +747,7 @@ func (sg *snapshotGenerator) atomicSnapshotsFromScriptActions( } for address, entries := range dataEntries { - dataEntrySnapshot := &DataEntriesSnapshot{Address: address, DataEntries: entries} + dataEntrySnapshot := &proto.DataEntriesSnapshot{Address: address, DataEntries: entries} atomicSnapshots = append(atomicSnapshots, dataEntrySnapshot) } return atomicSnapshots, nil @@ -755,16 +757,16 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, - balanceChanges txDiff, txPublicKey crypto.PublicKey) (TransactionSnapshot, error) { + balanceChanges txDiff, txPublicKey crypto.PublicKey) (proto.TransactionSnapshot, error) { blockHeight := info.height + 1 addrWavesBalanceDiff, addrAssetBalanceDiff, err := balanceDiffFromTxDiff(balanceChanges, sg.scheme) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") } - var snapshot TransactionSnapshot + var snapshot proto.TransactionSnapshot if invocationRes != nil { - var atomicSnapshots []AtomicSnapshot + var atomicSnapshots []proto.AtomicSnapshot atomicSnapshots, err = sg.atomicSnapshotsFromScriptActions( invocationRes.actions, addrWavesBalanceDiff, addrAssetBalanceDiff, blockHeight, info, txID, @@ -795,10 +797,10 @@ func (sg *snapshotGenerator) generateLeaseAtomicSnapshots(leaseID crypto.Digest, l leasing, originalTxID crypto.Digest, senderAddress proto.WavesAddress, receiverAddress proto.WavesAddress, - amount int64) (*LeaseStateSnapshot, *LeaseBalanceSnapshot, *LeaseBalanceSnapshot, error) { - leaseStatusSnapshot := &LeaseStateSnapshot{ + amount int64) (*proto.LeaseStateSnapshot, *proto.LeaseBalanceSnapshot, *proto.LeaseBalanceSnapshot, error) { + leaseStatusSnapshot := &proto.LeaseStateSnapshot{ LeaseID: leaseID, - Status: LeaseStateStatus{ + Status: proto.LeaseStateStatus{ Value: l.Status, }, Amount: l.Amount, @@ -812,7 +814,7 @@ func (sg *snapshotGenerator) generateLeaseAtomicSnapshots(leaseID crypto.Digest, if err != nil { return nil, nil, nil, errors.Wrap(err, "failed to receive sender's waves balance") } - senderLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ + senderLeaseBalanceSnapshot := &proto.LeaseBalanceSnapshot{ Address: senderAddress, LeaseIn: uint64(senderBalanceProfile.leaseIn), LeaseOut: uint64(senderBalanceProfile.leaseOut + amount), @@ -822,7 +824,7 @@ func (sg *snapshotGenerator) generateLeaseAtomicSnapshots(leaseID crypto.Digest, if err != nil { return nil, nil, nil, errors.Wrap(err, "failed to receive recipient's waves balance") } - recipientLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ + recipientLeaseBalanceSnapshot := &proto.LeaseBalanceSnapshot{ Address: receiverAddress, LeaseIn: uint64(receiverBalanceProfile.leaseIn + amount), LeaseOut: uint64(receiverBalanceProfile.leaseOut), @@ -832,7 +834,7 @@ func (sg *snapshotGenerator) generateLeaseAtomicSnapshots(leaseID crypto.Digest, } func (sg *snapshotGenerator) generateOrderAtomicSnapshot(orderID []byte, - volume uint64, fee uint64) (*FilledVolumeFeeSnapshot, error) { + volume uint64, fee uint64) (*proto.FilledVolumeFeeSnapshot, error) { newestFilledAmount, newestFilledFee, err := sg.stor.ordersVolumes.newestFilled(orderID) if err != nil { return nil, err @@ -842,7 +844,7 @@ func (sg *snapshotGenerator) generateOrderAtomicSnapshot(orderID []byte, return nil, errors.Wrap(err, "failed to construct digest from order id bytes") } // TODO must be added to newest filled amounts and fee - orderSnapshot := &FilledVolumeFeeSnapshot{ + orderSnapshot := &proto.FilledVolumeFeeSnapshot{ OrderID: orderIDDigset, FilledFee: newestFilledFee + fee, FilledVolume: newestFilledAmount + volume, @@ -850,8 +852,8 @@ func (sg *snapshotGenerator) generateOrderAtomicSnapshot(orderID []byte, return orderSnapshot, nil } -func (sg *snapshotGenerator) generateBalancesSnapshot(balanceChanges txDiff) (TransactionSnapshot, error) { - var transactionSnapshot TransactionSnapshot +func (sg *snapshotGenerator) generateBalancesSnapshot(balanceChanges txDiff) (proto.TransactionSnapshot, error) { + var transactionSnapshot proto.TransactionSnapshot addrWavesBalanceDiff, addrAssetBalanceDiff, err := balanceDiffFromTxDiff(balanceChanges, sg.scheme) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") @@ -871,7 +873,7 @@ func (sg *snapshotGenerator) generateBalancesSnapshot(balanceChanges txDiff) (Tr } func (sg *snapshotGenerator) generateBalancesAtomicSnapshots(addrWavesBalanceDiff addressWavesBalanceDiff, - addrAssetBalanceDiff addressAssetBalanceDiff) ([]WavesBalanceSnapshot, []AssetBalanceSnapshot, error) { + addrAssetBalanceDiff addressAssetBalanceDiff) ([]proto.WavesBalanceSnapshot, []proto.AssetBalanceSnapshot, error) { wavesBalanceSnapshot, err := sg.wavesBalanceSnapshotFromBalanceDiff(addrWavesBalanceDiff) if err != nil { return nil, nil, errors.Wrap(err, "failed to construct waves balance snapshot") @@ -927,8 +929,8 @@ func balanceDiffFromTxDiff(diff txDiff, scheme proto.Scheme) (addressWavesBalanc // from txDiff and fees. no validation needed at this point. func (sg *snapshotGenerator) wavesBalanceSnapshotFromBalanceDiff( - diff addressWavesBalanceDiff) ([]WavesBalanceSnapshot, error) { - var wavesBalances []WavesBalanceSnapshot + diff addressWavesBalanceDiff) ([]proto.WavesBalanceSnapshot, error) { + var wavesBalances []proto.WavesBalanceSnapshot // add miner address to the diff for wavesAddress, diffAmount := range diff { @@ -936,7 +938,7 @@ func (sg *snapshotGenerator) wavesBalanceSnapshotFromBalanceDiff( if err != nil { return nil, errors.Wrap(err, "failed to receive sender's waves balance") } - newBalance := WavesBalanceSnapshot{ + newBalance := proto.WavesBalanceSnapshot{ Address: wavesAddress, Balance: uint64(int64(fullBalance.balance) + diffAmount.balance), } @@ -946,8 +948,8 @@ func (sg *snapshotGenerator) wavesBalanceSnapshotFromBalanceDiff( } func (sg *snapshotGenerator) assetBalanceSnapshotFromBalanceDiff( - diff addressAssetBalanceDiff) ([]AssetBalanceSnapshot, error) { - var assetBalances []AssetBalanceSnapshot + diff addressAssetBalanceDiff) ([]proto.AssetBalanceSnapshot, error) { + var assetBalances []proto.AssetBalanceSnapshot // add miner address to the diff for key, diffAmount := range diff { @@ -960,7 +962,7 @@ func (sg *snapshotGenerator) assetBalanceSnapshotFromBalanceDiff( return nil, errors.Wrap(err, "failed to get newest asset info") } - newBalance := AssetBalanceSnapshot{ + newBalance := proto.AssetBalanceSnapshot{ Address: key.address, AssetID: key.asset.Digest(assetInfo.tail), Balance: uint64(int64(balance) + diffAmount), diff --git a/pkg/state/snapshot_generator_internal_test.go b/pkg/state/snapshot_generator_internal_test.go index a1d610c20..63fecff77 100644 --- a/pkg/state/snapshot_generator_internal_test.go +++ b/pkg/state/snapshot_generator_internal_test.go @@ -79,16 +79,16 @@ func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { transactionSnapshot, err := to.tp.performTransferWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform transfer tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.issuerInfo.addr, Balance: 299700000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.recipientInfo.addr, Balance: 200000, }, @@ -138,33 +138,33 @@ func TestDefaultIssueTransactionSnapshot(t *testing.T) { defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform issue tx") - expectedSnapshot := TransactionSnapshot{ - &StaticAssetInfoSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.StaticAssetInfoSnapshot{ AssetID: *tx.ID, SourceTransactionID: *tx.ID, IssuerPublicKey: testGlobal.issuerInfo.pk, Decimals: defaultDecimals, IsNFT: false}, - &AssetDescriptionSnapshot{ + &proto.AssetDescriptionSnapshot{ AssetID: *tx.ID, AssetName: "asset0", AssetDescription: "description", ChangeHeight: 1, }, - &AssetVolumeSnapshot{ + &proto.AssetVolumeSnapshot{ AssetID: *tx.ID, TotalQuantity: *big.NewInt(int64(defaultQuantity)), IsReissuable: true, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.issuerInfo.addr, Balance: 299900000, }, - &AssetBalanceSnapshot{ + &proto.AssetBalanceSnapshot{ Address: testGlobal.issuerInfo.addr, AssetID: *tx.ID, Balance: 1000, @@ -222,21 +222,21 @@ func TestDefaultReissueSnapshot(t *testing.T) { defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform reissue tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.issuerInfo.addr, Balance: 299900000, }, - &AssetBalanceSnapshot{ + &proto.AssetBalanceSnapshot{ Address: testGlobal.issuerInfo.addr, AssetID: testGlobal.asset0.assetID, Balance: 1050, }, - &AssetVolumeSnapshot{ + &proto.AssetVolumeSnapshot{ AssetID: testGlobal.asset0.assetID, TotalQuantity: *big.NewInt(int64(defaultQuantity + 50)), IsReissuable: false, @@ -293,21 +293,21 @@ func TestDefaultBurnSnapshot(t *testing.T) { defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.issuerInfo.addr, Balance: 299900000, }, - &AssetBalanceSnapshot{ + &proto.AssetBalanceSnapshot{ Address: testGlobal.issuerInfo.addr, AssetID: testGlobal.asset0.assetID, Balance: 950, }, - &AssetVolumeSnapshot{ + &proto.AssetVolumeSnapshot{ AssetID: testGlobal.asset0.assetID, TotalQuantity: *big.NewInt(int64(defaultQuantity - 100)), IsReissuable: false, @@ -393,49 +393,49 @@ func TestDefaultExchangeTransaction(t *testing.T) { nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.senderInfo.addr, Balance: 299999999, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.recipientInfo.addr, Balance: 599999998, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.matcherInfo.addr, Balance: 899900003, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &AssetBalanceSnapshot{ + &proto.AssetBalanceSnapshot{ Address: testGlobal.senderInfo.addr, AssetID: testGlobal.asset0.assetID, Balance: 10, }, - &AssetBalanceSnapshot{ + &proto.AssetBalanceSnapshot{ Address: testGlobal.recipientInfo.addr, AssetID: testGlobal.asset0.assetID, Balance: 590, }, - &AssetBalanceSnapshot{ + &proto.AssetBalanceSnapshot{ Address: testGlobal.senderInfo.addr, AssetID: testGlobal.asset1.assetID, Balance: 400, }, - &AssetBalanceSnapshot{ + &proto.AssetBalanceSnapshot{ Address: testGlobal.recipientInfo.addr, AssetID: testGlobal.asset1.assetID, Balance: 100, }, - &FilledVolumeFeeSnapshot{ + &proto.FilledVolumeFeeSnapshot{ OrderID: *bo.ID, FilledVolume: 10, FilledFee: 1, }, - &FilledVolumeFeeSnapshot{ + &proto.FilledVolumeFeeSnapshot{ OrderID: *so.ID, FilledVolume: 10, FilledFee: 2, @@ -485,19 +485,19 @@ func TestDefaultLeaseSnapshot(t *testing.T) { nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.senderInfo.addr, Balance: 299900000, }, - &LeaseStateSnapshot{ + &proto.LeaseStateSnapshot{ LeaseID: *tx.ID, - Status: LeaseStateStatus{ - Value: LeaseActive, + Status: proto.LeaseStateStatus{ + Value: proto.LeaseActive, }, Amount: 50, Sender: testGlobal.senderInfo.addr, @@ -505,12 +505,12 @@ func TestDefaultLeaseSnapshot(t *testing.T) { OriginTransactionID: tx.ID, Height: 0, }, - &LeaseBalanceSnapshot{ + &proto.LeaseBalanceSnapshot{ Address: testGlobal.senderInfo.addr, LeaseIn: 0, LeaseOut: 50, }, - &LeaseBalanceSnapshot{ + &proto.LeaseBalanceSnapshot{ Address: testGlobal.recipientInfo.addr, LeaseIn: 50, LeaseOut: 0, @@ -551,7 +551,7 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { Recipient: testGlobal.recipientInfo.addr, Amount: 50, Height: 1, - Status: LeaseActive, + Status: proto.LeaseActive, OriginTransactionID: &leaseID, } err := to.stor.entities.leases.addLeasing(leaseID, leasing, blockID0) @@ -576,19 +576,19 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.senderInfo.addr, Balance: 299900000, }, - &LeaseStateSnapshot{ + &proto.LeaseStateSnapshot{ LeaseID: leaseID, - Status: LeaseStateStatus{ - Value: LeaseCanceled, + Status: proto.LeaseStateStatus{ + Value: proto.LeaseCanceled, CancelHeight: 0, CancelTransactionID: tx.ID, }, @@ -598,12 +598,12 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { OriginTransactionID: &leaseID, Height: 1, }, - &LeaseBalanceSnapshot{ + &proto.LeaseBalanceSnapshot{ Address: testGlobal.senderInfo.addr, LeaseIn: 0, LeaseOut: 0, }, - &LeaseBalanceSnapshot{ + &proto.LeaseBalanceSnapshot{ Address: testGlobal.recipientInfo.addr, LeaseIn: 0, LeaseOut: 0, @@ -651,16 +651,16 @@ func TestDefaultCreateAliasSnapshot(t *testing.T) { nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.senderInfo.addr, Balance: 299900000, }, - &AliasSnapshot{ + &proto.AliasSnapshot{ Address: testGlobal.senderInfo.addr, Alias: *proto.NewAlias(proto.TestNetScheme, "aliasForSender"), }, @@ -716,16 +716,16 @@ func TestDefaultDataSnapshot(t *testing.T) { nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.senderInfo.addr, Balance: 299900000, }, - &DataEntriesSnapshot{ + &proto.DataEntriesSnapshot{ Address: testGlobal.senderInfo.addr, DataEntries: []proto.DataEntry{&proto.StringDataEntry{Key: "key_str", Value: "value_str"}, &proto.IntegerDataEntry{Key: "key_int", Value: 2}}, @@ -775,16 +775,16 @@ func TestDefaultSponsorshipSnapshot(t *testing.T) { defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.senderInfo.addr, Balance: 299900000, }, - &SponsorshipSnapshot{ + &proto.SponsorshipSnapshot{ AssetID: testGlobal.asset0.assetID, MinSponsoredFee: 500000, }, @@ -840,16 +840,16 @@ func TestDefaultSetScriptSnapshot(t *testing.T) { defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.senderInfo.addr, Balance: 299900000, }, - &AccountScriptSnapshot{ + &proto.AccountScriptSnapshot{ SenderPublicKey: testGlobal.senderInfo.pk, Script: testGlobal.scriptBytes, VerifierComplexity: 340, @@ -915,16 +915,16 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.T) { defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.senderInfo.addr, Balance: 299900000, }, - &AssetScriptSnapshot{ + &proto.AssetScriptSnapshot{ AssetID: testGlobal.asset0.assetID, Script: testGlobal.scriptBytes, Complexity: 340, @@ -1039,16 +1039,16 @@ func TestDefaultInvokeScriptSnapshot(t *testing.T) { invocationResult, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform invoke script tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 200000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.senderInfo.addr, Balance: 299500000, }, - &DataEntriesSnapshot{ + &proto.DataEntriesSnapshot{ Address: testGlobal.recipientInfo.addr, DataEntries: []proto.DataEntry{ &proto.BooleanDataEntry{Key: "bool", Value: true}, diff --git a/pkg/state/snapshot_storage.go b/pkg/state/snapshot_storage.go new file mode 100644 index 000000000..cbdc1aa54 --- /dev/null +++ b/pkg/state/snapshot_storage.go @@ -0,0 +1,42 @@ +package state + +import ( + protobuf "google.golang.org/protobuf/proto" + + g "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" + "github.com/wavesplatform/gowaves/pkg/proto" +) + +type snapshotsAtHeight struct { + hs *historyStorage +} + +func newSnapshotsAtHeight(hs *historyStorage) *snapshotsAtHeight { + return &snapshotsAtHeight{hs: hs} +} + +func (s *snapshotsAtHeight) saveSnapshots( + blockID proto.BlockID, + blockHeight uint64, + txSnapshots proto.TransactionSnapshot, +) error { + key := snapshotsKey{height: blockHeight} + recordBytes, err := protobuf.Marshal(txSnapshots.ToProtobuf()) + if err != nil { + return err + } + return s.hs.addNewEntry(snapshots, key.bytes(), recordBytes, blockID) +} + +func (s *snapshotsAtHeight) shapshots(height uint64) (*g.TransactionStateSnapshot, error) { + key := snapshotsKey{height: height} + snapshotsBytes, err := s.hs.newestTopEntryData(key.bytes()) + if err != nil { + return nil, err + } + var res g.TransactionStateSnapshot + if err = protobuf.Unmarshal(snapshotsBytes, &res); err != nil { + return nil, err + } + return &res, nil +} diff --git a/pkg/state/snapshot_storage_test.go b/pkg/state/snapshot_storage_test.go new file mode 100644 index 000000000..d2f13f00f --- /dev/null +++ b/pkg/state/snapshot_storage_test.go @@ -0,0 +1,29 @@ +package state + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/wavesplatform/gowaves/pkg/proto" +) + +func TestSaveSnapshots(t *testing.T) { + storage := createStorageObjects(t, true) + snapshotStor := newSnapshotsAtHeight(storage.hs) + ids := genRandBlockIds(t, 1) + snapshots := proto.TransactionSnapshot{ + proto.WavesBalanceSnapshot{Address: *generateRandomRecipient(t).Address(), Balance: 100}, + proto.WavesBalanceSnapshot{Address: *generateRandomRecipient(t).Address(), Balance: 100}, + proto.WavesBalanceSnapshot{Address: *generateRandomRecipient(t).Address(), Balance: 100}, + proto.WavesBalanceSnapshot{Address: *generateRandomRecipient(t).Address(), Balance: 100}, + } + storage.addBlock(t, ids[0]) + err := snapshotStor.saveSnapshots(ids[0], 10, snapshots) + assert.NoError(t, err) + + fromStorage, err := snapshotStor.shapshots(10) + assert.NoError(t, err) + + assert.Equal(t, len(fromStorage.Balances), len(snapshots)) +} diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go deleted file mode 100644 index bed1c253f..000000000 --- a/pkg/state/snapshot_types.go +++ /dev/null @@ -1,214 +0,0 @@ -package state - -import ( - "math/big" - - "github.com/pkg/errors" - - "github.com/wavesplatform/gowaves/pkg/crypto" - "github.com/wavesplatform/gowaves/pkg/proto" -) - -type TransactionSnapshot []AtomicSnapshot - -func (ts TransactionSnapshot) Apply(a SnapshotApplier) error { - for _, atomicSnapshot := range ts { - if !atomicSnapshot.IsGeneratedByTxDiff() { - err := atomicSnapshot.Apply(a) - if err != nil { - return errors.Wrap(err, "failed to apply transaction snapshot") - } - } - } - return nil -} - -type AtomicSnapshot interface { - Apply(SnapshotApplier) error - /* is temporarily used to mark snapshots generated by tx diff that shouldn't be applied, - because balances diffs are applied later in the block. */ - IsGeneratedByTxDiff() bool -} - -type WavesBalanceSnapshot struct { - Address proto.WavesAddress - Balance uint64 -} - -func (s WavesBalanceSnapshot) IsGeneratedByTxDiff() bool { - return true -} - -func (s WavesBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyWavesBalance(s) } - -type AssetBalanceSnapshot struct { - Address proto.WavesAddress - AssetID crypto.Digest - Balance uint64 -} - -func (s AssetBalanceSnapshot) IsGeneratedByTxDiff() bool { - return true -} - -func (s AssetBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetBalance(s) } - -type DataEntriesSnapshot struct { // AccountData in pb - Address proto.WavesAddress - DataEntries []proto.DataEntry -} - -func (s DataEntriesSnapshot) IsGeneratedByTxDiff() bool { - return false -} - -func (s DataEntriesSnapshot) Apply(a SnapshotApplier) error { return a.ApplyDataEntries(s) } - -type AccountScriptSnapshot struct { - SenderPublicKey crypto.PublicKey - Script proto.Script - VerifierComplexity uint64 -} - -func (s AccountScriptSnapshot) IsGeneratedByTxDiff() bool { - return false -} - -func (s AccountScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAccountScript(s) } - -type AssetScriptSnapshot struct { - AssetID crypto.Digest - Script proto.Script - SenderPK crypto.PublicKey // should be removed later - Complexity uint64 -} - -func (s AssetScriptSnapshot) IsGeneratedByTxDiff() bool { - return false -} - -func (s AssetScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetScript(s) } - -type LeaseBalanceSnapshot struct { - Address proto.WavesAddress - LeaseIn uint64 - LeaseOut uint64 -} - -func (s LeaseBalanceSnapshot) IsGeneratedByTxDiff() bool { - return true -} - -func (s LeaseBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseBalance(s) } - -type LeaseStateStatus struct { - Value LeaseStatus // can be only LeaseActive or LeaseCanceled - CancelHeight proto.Height - CancelTransactionID *crypto.Digest -} - -type LeaseStateSnapshot struct { - LeaseID crypto.Digest - Status LeaseStateStatus - Amount uint64 - Sender proto.WavesAddress - Recipient proto.WavesAddress - OriginTransactionID *crypto.Digest - Height proto.Height -} - -func (s LeaseStateSnapshot) IsGeneratedByTxDiff() bool { - return false -} - -func (s LeaseStateSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseState(s) } - -type SponsorshipSnapshot struct { - AssetID crypto.Digest - MinSponsoredFee uint64 -} - -func (s SponsorshipSnapshot) IsGeneratedByTxDiff() bool { - return false -} - -func (s SponsorshipSnapshot) Apply(a SnapshotApplier) error { return a.ApplySponsorship(s) } - -type AliasSnapshot struct { - Address proto.WavesAddress - Alias proto.Alias -} - -func (s AliasSnapshot) IsGeneratedByTxDiff() bool { - return false -} - -func (s AliasSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAlias(s) } - -// FilledVolumeFeeSnapshot Filled Volume and Fee. -type FilledVolumeFeeSnapshot struct { // OrderFill - OrderID crypto.Digest - FilledVolume uint64 - FilledFee uint64 -} - -func (s FilledVolumeFeeSnapshot) IsGeneratedByTxDiff() bool { - return false -} - -func (s FilledVolumeFeeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyFilledVolumeAndFee(s) } - -type StaticAssetInfoSnapshot struct { - AssetID crypto.Digest - SourceTransactionID crypto.Digest - IssuerPublicKey crypto.PublicKey - Decimals uint8 - IsNFT bool -} - -func (s StaticAssetInfoSnapshot) IsGeneratedByTxDiff() bool { - return false -} - -func (s StaticAssetInfoSnapshot) Apply(a SnapshotApplier) error { return a.ApplyStaticAssetInfo(s) } - -type AssetVolumeSnapshot struct { // AssetVolume in pb - AssetID crypto.Digest - TotalQuantity big.Int // volume in protobuf - IsReissuable bool -} - -func (s AssetVolumeSnapshot) IsGeneratedByTxDiff() bool { - return false -} - -func (s AssetVolumeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetVolume(s) } - -type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb - AssetID crypto.Digest - AssetName string - AssetDescription string - ChangeHeight proto.Height // last_updated in pb -} - -func (s AssetDescriptionSnapshot) IsGeneratedByTxDiff() bool { - return false -} - -func (s AssetDescriptionSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetDescription(s) } - -type SnapshotApplier interface { - ApplyWavesBalance(snapshot WavesBalanceSnapshot) error - ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) error - ApplyAssetBalance(snapshot AssetBalanceSnapshot) error - ApplyAlias(snapshot AliasSnapshot) error - ApplyStaticAssetInfo(snapshot StaticAssetInfoSnapshot) error - ApplyAssetDescription(snapshot AssetDescriptionSnapshot) error - ApplyAssetVolume(snapshot AssetVolumeSnapshot) error - ApplyAssetScript(snapshot AssetScriptSnapshot) error - ApplySponsorship(snapshot SponsorshipSnapshot) error - ApplyAccountScript(snapshot AccountScriptSnapshot) error - ApplyFilledVolumeAndFee(snapshot FilledVolumeFeeSnapshot) error - ApplyDataEntries(snapshot DataEntriesSnapshot) error - ApplyLeaseState(snapshot LeaseStateSnapshot) error -} diff --git a/pkg/state/state.go b/pkg/state/state.go index 3f2aa1899..ed593ece3 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -18,6 +18,7 @@ import ( "github.com/wavesplatform/gowaves/pkg/consensus" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/errs" + g "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" "github.com/wavesplatform/gowaves/pkg/keyvalue" "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/ride/ast" @@ -61,6 +62,7 @@ type blockchainEntitiesStorage struct { invokeResults *invokeResults stateHashes *stateHashes hitSources *hitSources + snapshots *snapshotsAtHeight calculateHashes bool } @@ -93,6 +95,7 @@ func newBlockchainEntitiesStorage(hs *historyStorage, sets *settings.BlockchainS newInvokeResults(hs), newStateHashes(hs), newHitSources(hs), + newSnapshotsAtHeight(hs), calcHashes, }, nil } @@ -2562,6 +2565,10 @@ func (s *stateManager) TotalWavesAmount(height proto.Height) (uint64, error) { return amount, nil } +func (s *stateManager) SnapshotsAtHeight(height proto.Height) (*g.TransactionStateSnapshot, error) { + return s.stor.snapshots.shapshots(height) +} + func (s *stateManager) Close() error { if err := s.atx.close(); err != nil { return wrapErr(ClosureError, err) diff --git a/pkg/state/threadsafe_wrapper.go b/pkg/state/threadsafe_wrapper.go index ff5968e02..1b77d111a 100644 --- a/pkg/state/threadsafe_wrapper.go +++ b/pkg/state/threadsafe_wrapper.go @@ -6,6 +6,7 @@ import ( "sync/atomic" "github.com/wavesplatform/gowaves/pkg/crypto" + g "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/ride/ast" "github.com/wavesplatform/gowaves/pkg/settings" @@ -374,6 +375,12 @@ func (a *ThreadSafeReadWrapper) TotalWavesAmount(height proto.Height) (uint64, e return a.s.TotalWavesAmount(height) } +func (a *ThreadSafeReadWrapper) SnapshotsAtHeight(height proto.Height) (*g.TransactionStateSnapshot, error) { + a.mu.RLock() + defer a.mu.RUnlock() + return a.s.SnapshotsAtHeight(height) +} + func NewThreadSafeReadWrapper(mu *sync.RWMutex, s StateInfo) StateInfo { return &ThreadSafeReadWrapper{ mu: mu, diff --git a/pkg/state/transaction_handler.go b/pkg/state/transaction_handler.go index 0388b935d..00b840d09 100644 --- a/pkg/state/transaction_handler.go +++ b/pkg/state/transaction_handler.go @@ -24,7 +24,7 @@ type scriptEstimation struct { func (e *scriptEstimation) isPresent() bool { return e != nil } type txCheckFunc func(proto.Transaction, *checkerInfo) (txCheckerData, error) -type txPerformFunc func(proto.Transaction, *performerInfo, *invocationResult, txDiff) (TransactionSnapshot, error) +type txPerformFunc func(proto.Transaction, *performerInfo, *invocationResult, txDiff) (proto.TransactionSnapshot, error) type txCreateDiffFunc func(proto.Transaction, *differInfo) (txBalanceChanges, error) type txCountFeeFunc func(proto.Transaction, *feeDistribution) error @@ -199,7 +199,7 @@ func (h *transactionHandler) checkTx(tx proto.Transaction, info *checkerInfo) (t } func (h *transactionHandler) performTx(tx proto.Transaction, info *performerInfo, - invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + invocationRes *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tv := tx.GetTypeInfo() funcs, ok := h.funcs[tv] if !ok { diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 85e95ad59..430970be1 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -29,8 +29,8 @@ func newPerformerInfo(height proto.Height, stateActionsCounter *proto.StateActio type transactionPerformer struct { stor *blockchainEntitiesStorage settings *settings.BlockchainSettings - snapshotGenerator *snapshotGenerator // initialized in appendTx - snapshotApplier SnapshotApplier // initialized in appendTx + snapshotGenerator *snapshotGenerator // initialized in appendTx + snapshotApplier proto.SnapshotApplier // initialized in appendTx } func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings.BlockchainSettings) (*transactionPerformer, error) { @@ -40,7 +40,7 @@ func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings func (tp *transactionPerformer) performGenesis( transaction proto.Transaction, _ *performerInfo, _ *invocationResult, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { _, ok := transaction.(*proto.Genesis) if !ok { return nil, errors.New("failed to convert interface to genesis transaction") @@ -53,7 +53,7 @@ func (tp *transactionPerformer) performGenesis( } func (tp *transactionPerformer) performPayment(transaction proto.Transaction, _ *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { _, ok := transaction.(*proto.Payment) if !ok { return nil, errors.New("failed to convert interface to payment transaction") @@ -65,7 +65,7 @@ func (tp *transactionPerformer) performPayment(transaction proto.Transaction, _ return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performTransfer(balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performTransfer(balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := tp.snapshotGenerator.generateSnapshotForTransferTx(balanceChanges) if err != nil { return nil, err @@ -74,7 +74,7 @@ func (tp *transactionPerformer) performTransfer(balanceChanges txDiff) (Transact } func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transaction, _ *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { _, ok := transaction.(*proto.TransferWithSig) if !ok { return nil, errors.New("failed to convert interface to transfer with sig transaction") @@ -83,7 +83,7 @@ func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transac } func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Transaction, _ *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { _, ok := transaction.(*proto.TransferWithProofs) if !ok { return nil, errors.New("failed to convert interface to transfer with proofs transaction") @@ -93,7 +93,7 @@ func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Tran func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest, assetID crypto.Digest, info *performerInfo, - balanceChanges txDiff, scriptInformation *scriptInformation) (TransactionSnapshot, error) { + balanceChanges txDiff, scriptInformation *scriptInformation) (proto.TransactionSnapshot, error) { blockHeight := info.height + 1 // Create new asset. assetInfo := &assetInfo{ @@ -122,7 +122,7 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest } func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.IssueWithSig) if !ok { return nil, errors.New("failed to convert interface to IssueWithSig transaction") @@ -142,7 +142,7 @@ func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transactio } func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.IssueWithProofs) if !ok { return nil, errors.New("failed to convert interface to IssueWithProofs transaction") @@ -175,7 +175,7 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac } func (tp *transactionPerformer) performReissue(tx *proto.Reissue, _ *performerInfo, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { // Modify asset. change := &assetReissueChange{ reissuable: tx.Reissuable, @@ -190,7 +190,7 @@ func (tp *transactionPerformer) performReissue(tx *proto.Reissue, _ *performerIn } func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.ReissueWithSig) if !ok { return nil, errors.New("failed to convert interface to ReissueWithSig transaction") @@ -199,7 +199,7 @@ func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transact } func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Transaction, - info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + info *performerInfo, _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.ReissueWithProofs) if !ok { return nil, errors.New("failed to convert interface to ReissueWithProofs transaction") @@ -208,7 +208,7 @@ func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Trans } func (tp *transactionPerformer) performBurn(tx *proto.Burn, _ *performerInfo, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { // Modify asset. change := &assetBurnChange{ diff: int64(tx.Amount), @@ -222,7 +222,7 @@ func (tp *transactionPerformer) performBurn(tx *proto.Burn, _ *performerInfo, } func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.BurnWithSig) if !ok { return nil, errors.New("failed to convert interface to BurnWithSig transaction") @@ -231,7 +231,7 @@ func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction } func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.BurnWithProofs) if !ok { return nil, errors.New("failed to convert interface to BurnWithProofs transaction") @@ -240,7 +240,7 @@ func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transact } func (tp *transactionPerformer) performExchange(transaction proto.Transaction, _ *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(proto.Exchange) if !ok { return nil, errors.New("failed to convert interface to Exchange transaction") @@ -267,7 +267,7 @@ func (tp *transactionPerformer) performExchange(transaction proto.Transaction, _ } func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest, info *performerInfo, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { return nil, err @@ -287,7 +287,7 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest Recipient: recipientAddr, Amount: tx.Amount, Height: info.height, - Status: LeaseActive, + Status: proto.LeaseActive, } snapshot, err := tp.snapshotGenerator.generateSnapshotForLeaseTx(*l, txID, txID, balanceChanges) if err != nil { @@ -297,7 +297,7 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest } func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseWithSig) if !ok { return nil, errors.New("failed to convert interface to LeaseWithSig transaction") @@ -306,7 +306,7 @@ func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transactio } func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseWithProofs) if !ok { return nil, errors.New("failed to convert interface to LeaseWithProofs transaction") @@ -315,7 +315,7 @@ func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transac } func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID *crypto.Digest, info *performerInfo, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { oldLease, err := tp.stor.leases.newestLeasingInfo(tx.LeaseID) if err != nil { return nil, errors.Wrap(err, "failed to receiver leasing info") @@ -331,7 +331,7 @@ func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID * } func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseCancelWithSig) if !ok { return nil, errors.New("failed to convert interface to LeaseCancelWithSig transaction") @@ -340,7 +340,7 @@ func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Tran } func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseCancelWithProofs) if !ok { return nil, errors.New("failed to convert interface to LeaseCancelWithProofs transaction") @@ -349,7 +349,7 @@ func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.T } func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, - _ *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *performerInfo, balanceChanges txDiff) (proto.TransactionSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { return nil, err @@ -363,7 +363,7 @@ func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, } func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.CreateAliasWithSig) if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithSig transaction") @@ -372,7 +372,7 @@ func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Tran } func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.CreateAliasWithProofs) if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") @@ -381,7 +381,7 @@ func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.T } func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto.Transaction, _ *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { _, ok := transaction.(*proto.MassTransferWithProofs) if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") @@ -394,7 +394,7 @@ func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto. } func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, - _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.DataWithProofs) if !ok { return nil, errors.New("failed to convert interface to DataWithProofs transaction") @@ -412,7 +412,7 @@ func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transact } func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.Transaction, _ *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.SponsorshipWithProofs) if !ok { return nil, errors.New("failed to convert interface to SponsorshipWithProofs transaction") @@ -426,7 +426,7 @@ func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.T } func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.SetScriptWithProofs) if !ok { return nil, errors.New("failed to convert interface to SetScriptWithProofs transaction") @@ -476,7 +476,7 @@ func storeScriptByAddress( } func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction proto.Transaction, - info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + info *performerInfo, _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.SetAssetScriptWithProofs) if !ok { return nil, errors.New("failed to convert interface to SetAssetScriptWithProofs transaction") @@ -507,7 +507,7 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.InvokeScriptWithProofs) if !ok { return nil, errors.New("failed to convert interface to InvokeScriptWithProofs transaction") @@ -551,7 +551,7 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.InvokeExpressionTransactionWithProofs) if !ok { return nil, errors.New("failed to convert interface to InvokeExpressionWithProofs transaction") @@ -575,7 +575,7 @@ func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction pr } func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo, - invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + invocationRes *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { ethTx, ok := transaction.(*proto.EthereumTransaction) if !ok { return nil, errors.New("failed to convert interface to EthereumTransaction transaction") @@ -609,7 +609,7 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction } func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction proto.Transaction, - info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + info *performerInfo, _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.UpdateAssetInfoWithProofs) if !ok { return nil, errors.New("failed to convert interface to UpdateAssetInfoWithProofs transaction") diff --git a/pkg/state/transaction_performer_test.go b/pkg/state/transaction_performer_test.go index 6205ef3ec..86aa33858 100644 --- a/pkg/state/transaction_performer_test.go +++ b/pkg/state/transaction_performer_test.go @@ -241,7 +241,7 @@ func TestPerformLeaseWithSig(t *testing.T) { to.stor.flush(t) leasingInfo := &leasing{ OriginTransactionID: tx.ID, - Status: LeaseActive, + Status: proto.LeaseActive, Amount: tx.Amount, Recipient: *tx.Recipient.Address(), Sender: testGlobal.senderInfo.addr, @@ -263,7 +263,7 @@ func TestPerformLeaseWithProofs(t *testing.T) { to.stor.flush(t) leasingInfo := &leasing{ OriginTransactionID: tx.ID, - Status: LeaseActive, + Status: proto.LeaseActive, Amount: tx.Amount, Recipient: *tx.Recipient.Address(), Sender: testGlobal.senderInfo.addr, @@ -286,7 +286,7 @@ func TestPerformLeaseCancelWithSig(t *testing.T) { tx := createLeaseCancelWithSig(t, *leaseTx.ID) leasingInfo := &leasing{ OriginTransactionID: leaseTx.ID, - Status: LeaseCanceled, + Status: proto.LeaseCanceled, Amount: leaseTx.Amount, Recipient: *leaseTx.Recipient.Address(), Sender: testGlobal.senderInfo.addr, @@ -312,7 +312,7 @@ func TestPerformLeaseCancelWithProofs(t *testing.T) { tx := createLeaseCancelWithProofs(t, *leaseTx.ID) leasingInfo := &leasing{ OriginTransactionID: leaseTx.ID, - Status: LeaseCanceled, + Status: proto.LeaseCanceled, Amount: leaseTx.Amount, Recipient: *leaseTx.Recipient.Address(), Sender: testGlobal.senderInfo.addr, From 6a5502e9ffc74da4e6830df97abd57a6715a9425 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Thu, 5 Oct 2023 12:02:21 +0300 Subject: [PATCH 070/139] fix some linter issues --- pkg/state/appender.go | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 4c906884b..0cd843bb2 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -503,9 +503,6 @@ func (a *txAppender) handleTxAndScripts( accountHasVerifierScript bool, senderAddr proto.Address, ) (*applicationResult, *invocationResult, bool, error) { - var applicationRes *applicationResult - var invocationRes *invocationResult - needToValidateBalanceDiff := false switch tx.GetTypeInfo().Type { case proto.InvokeScriptTransaction, proto.InvokeExpressionTransaction, proto.ExchangeTransaction: // Invoke and Exchange transactions should be handled differently. @@ -515,19 +512,19 @@ func (a *txAppender) handleTxAndScripts( senderScripted: accountHasVerifierScript, senderAddress: senderAddr, } - var err error - invocationRes, applicationRes, err = a.handleInvokeOrExchangeTransaction(tx, fallibleInfo) + + invocationRes, applicationRes, err := a.handleInvokeOrExchangeTransaction(tx, fallibleInfo) if err != nil { return nil, nil, false, errors.Wrap(err, "failed to handle invoke or exchange transaction") } // Exchange and Invoke balances are validated in UTX when acceptFailed is false. // When acceptFailed is true, balances are validated inside handleFallible(). - needToValidateBalanceDiff = params.validatingUtx && !params.acceptFailed + needToValidateBalanceDiff := params.validatingUtx && !params.acceptFailed + return applicationRes, invocationRes, needToValidateBalanceDiff, nil case proto.EthereumMetamaskTransaction: return a.handleEthTx(tx, params, accountHasVerifierScript, senderAddr) default: - var err error - applicationRes, err = a.handleDefaultTransaction(tx, params, accountHasVerifierScript) + applicationRes, err := a.handleDefaultTransaction(tx, params, accountHasVerifierScript) if err != nil { id, idErr := tx.GetID(a.settings.AddressSchemeCharacter) if idErr != nil { @@ -536,9 +533,8 @@ func (a *txAppender) handleTxAndScripts( return nil, nil, false, errors.Wrapf(err, "failed to handle transaction '%s'", base58.Encode(id)) } // In UTX balances are always validated. - needToValidateBalanceDiff = params.validatingUtx + return applicationRes, nil, params.validatingUtx, nil } - return applicationRes, invocationRes, needToValidateBalanceDiff, nil } func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) (proto.TransactionSnapshot, error) { From efce4cbbcaf1da3e8b3d2f0bba0f87edb1068d7e Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Thu, 5 Oct 2023 16:52:31 +0300 Subject: [PATCH 071/139] move snapshots types to proto --- pkg/{state => proto}/snapshot_types.go | 31 ++-- pkg/proto/types.go | 8 + pkg/state/appender.go | 12 +- pkg/state/invoke_applier.go | 2 +- pkg/state/leases.go | 20 +-- pkg/state/leases_test.go | 4 +- pkg/state/snapshot_applier.go | 28 ++-- pkg/state/snapshot_generator.go | 158 +++++++++--------- pkg/state/snapshot_generator_internal_test.go | 146 ++++++++-------- pkg/state/transaction_handler.go | 4 +- pkg/state/transaction_performer.go | 72 ++++---- pkg/state/transaction_performer_test.go | 8 +- 12 files changed, 247 insertions(+), 246 deletions(-) rename pkg/{state => proto}/snapshot_types.go (91%) diff --git a/pkg/state/snapshot_types.go b/pkg/proto/snapshot_types.go similarity index 91% rename from pkg/state/snapshot_types.go rename to pkg/proto/snapshot_types.go index bed1c253f..cfcccd9c0 100644 --- a/pkg/state/snapshot_types.go +++ b/pkg/proto/snapshot_types.go @@ -1,4 +1,4 @@ -package state +package proto import ( "math/big" @@ -6,7 +6,6 @@ import ( "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" - "github.com/wavesplatform/gowaves/pkg/proto" ) type TransactionSnapshot []AtomicSnapshot @@ -31,7 +30,7 @@ type AtomicSnapshot interface { } type WavesBalanceSnapshot struct { - Address proto.WavesAddress + Address WavesAddress Balance uint64 } @@ -42,7 +41,7 @@ func (s WavesBalanceSnapshot) IsGeneratedByTxDiff() bool { func (s WavesBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyWavesBalance(s) } type AssetBalanceSnapshot struct { - Address proto.WavesAddress + Address WavesAddress AssetID crypto.Digest Balance uint64 } @@ -54,8 +53,8 @@ func (s AssetBalanceSnapshot) IsGeneratedByTxDiff() bool { func (s AssetBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetBalance(s) } type DataEntriesSnapshot struct { // AccountData in pb - Address proto.WavesAddress - DataEntries []proto.DataEntry + Address WavesAddress + DataEntries []DataEntry } func (s DataEntriesSnapshot) IsGeneratedByTxDiff() bool { @@ -66,7 +65,7 @@ func (s DataEntriesSnapshot) Apply(a SnapshotApplier) error { return a.ApplyData type AccountScriptSnapshot struct { SenderPublicKey crypto.PublicKey - Script proto.Script + Script Script VerifierComplexity uint64 } @@ -78,7 +77,7 @@ func (s AccountScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAc type AssetScriptSnapshot struct { AssetID crypto.Digest - Script proto.Script + Script Script SenderPK crypto.PublicKey // should be removed later Complexity uint64 } @@ -90,7 +89,7 @@ func (s AssetScriptSnapshot) IsGeneratedByTxDiff() bool { func (s AssetScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetScript(s) } type LeaseBalanceSnapshot struct { - Address proto.WavesAddress + Address WavesAddress LeaseIn uint64 LeaseOut uint64 } @@ -103,7 +102,7 @@ func (s LeaseBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLea type LeaseStateStatus struct { Value LeaseStatus // can be only LeaseActive or LeaseCanceled - CancelHeight proto.Height + CancelHeight Height CancelTransactionID *crypto.Digest } @@ -111,10 +110,10 @@ type LeaseStateSnapshot struct { LeaseID crypto.Digest Status LeaseStateStatus Amount uint64 - Sender proto.WavesAddress - Recipient proto.WavesAddress + Sender WavesAddress + Recipient WavesAddress OriginTransactionID *crypto.Digest - Height proto.Height + Height Height } func (s LeaseStateSnapshot) IsGeneratedByTxDiff() bool { @@ -135,8 +134,8 @@ func (s SponsorshipSnapshot) IsGeneratedByTxDiff() bool { func (s SponsorshipSnapshot) Apply(a SnapshotApplier) error { return a.ApplySponsorship(s) } type AliasSnapshot struct { - Address proto.WavesAddress - Alias proto.Alias + Address WavesAddress + Alias Alias } func (s AliasSnapshot) IsGeneratedByTxDiff() bool { @@ -188,7 +187,7 @@ type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb AssetID crypto.Digest AssetName string AssetDescription string - ChangeHeight proto.Height // last_updated in pb + ChangeHeight Height // last_updated in pb } func (s AssetDescriptionSnapshot) IsGeneratedByTxDiff() bool { diff --git a/pkg/proto/types.go b/pkg/proto/types.go index 5a3b5aa9a..016d1bba8 100644 --- a/pkg/proto/types.go +++ b/pkg/proto/types.go @@ -4295,3 +4295,11 @@ func (s StateHashDebug) GetStateHash() *StateHash { } return sh } + +type LeaseStatus byte + +const ( + LeaseActive LeaseStatus = iota + LeaseCanceled + //TODO: LeaseExpired (for future use) +) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 142dc1550..3afbb964d 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -327,7 +327,7 @@ func (a *txAppender) commitTxApplication( tx proto.Transaction, params *appendTxParams, invocationRes *invocationResult, - applicationRes *applicationResult) (TransactionSnapshot, error) { + applicationRes *applicationResult) (proto.TransactionSnapshot, error) { // Add transaction ID to recent IDs. txID, err := tx.GetID(a.settings.AddressSchemeCharacter) if err != nil { @@ -344,7 +344,7 @@ func (a *txAppender) commitTxApplication( } currentMinerAddress := proto.MustAddressFromPublicKey(a.settings.AddressSchemeCharacter, params.currentMinerPK) - var snapshot TransactionSnapshot + var snapshot proto.TransactionSnapshot if applicationRes.status { // We only perform tx in case it has not failed. performerInfo := &performerInfo{ @@ -421,7 +421,7 @@ type appendTxParams struct { currentMinerPK crypto.PublicKey snapshotGenerator *snapshotGenerator - snapshotApplier SnapshotApplier + snapshotApplier proto.SnapshotApplier } func (a *txAppender) handleInvokeOrExchangeTransaction( @@ -586,20 +586,20 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro } // rewards and 60% of the fee to the previous miner. -func (a *txAppender) createInitialBlockSnapshot(minerAndRewardDiff txDiff) (TransactionSnapshot, error) { +func (a *txAppender) createInitialBlockSnapshot(minerAndRewardDiff txDiff) (proto.TransactionSnapshot, error) { addrWavesBalanceDiff, _, err := balanceDiffFromTxDiff(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 + var snapshot proto.TransactionSnapshot for wavesAddress, diffAmount := range addrWavesBalanceDiff { var fullBalance balanceProfile 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{ + newBalance := &proto.WavesBalanceSnapshot{ Address: wavesAddress, Balance: uint64(int64(fullBalance.balance) + diffAmount.balance), } diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index 42d680510..46b14616b 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -664,7 +664,7 @@ func (ia *invokeApplier) fallibleValidation(tx proto.Transaction, info *addlInvo Recipient: recipientAddress, Amount: uint64(a.Amount), Height: info.blockInfo.Height, - Status: LeaseActive, + Status: proto.LeaseActive, } ia.stor.leases.addLeasingUncertain(a.ID, l) diff --git a/pkg/state/leases.go b/pkg/state/leases.go index cf754da6f..dca931269 100644 --- a/pkg/state/leases.go +++ b/pkg/state/leases.go @@ -13,14 +13,6 @@ import ( "github.com/wavesplatform/gowaves/pkg/proto" ) -type LeaseStatus byte - -const ( - LeaseActive LeaseStatus = iota - LeaseCanceled - //TODO: LeaseExpired (for future use) -) - type leaseRecordForStateHashes struct { id *crypto.Digest active byte @@ -46,14 +38,14 @@ type leasing struct { Recipient proto.WavesAddress `cbor:"1,keyasint"` Amount uint64 `cbor:"2,keyasint"` Height uint64 `cbor:"3,keyasint"` - Status LeaseStatus `cbor:"4,keyasint"` + Status proto.LeaseStatus `cbor:"4,keyasint"` OriginTransactionID *crypto.Digest `cbor:"5,keyasint,omitempty"` CancelHeight uint64 `cbor:"7,keyasint,omitempty"` CancelTransactionID *crypto.Digest `cbor:"8,keyasint,omitempty"` } func (l *leasing) isActive() bool { - return l.Status == LeaseActive + return l.Status == proto.LeaseActive } func (l *leasing) marshalBinary() ([]byte, error) { @@ -114,7 +106,7 @@ func (l *leases) cancelLeases(bySenders map[proto.WavesAddress]struct{}, blockID return errors.Wrap(err, "failed to unmarshal lease key") } zap.S().Infof("State: cancelling lease %s", k.leaseID.String()) - record.Status = LeaseCanceled + record.Status = proto.LeaseCanceled if err := l.addLeasing(k.leaseID, record, blockID); err != nil { return errors.Wrap(err, "failed to save lease to storage") } @@ -137,7 +129,7 @@ func (l *leases) cancelLeasesToDisabledAliases(scheme proto.Scheme, height proto return nil, errors.Wrapf(err, "failed to get newest leasing info by id %q", leaseID.String()) } zap.S().Infof("State: canceling lease %s", leaseID) - record.Status = LeaseCanceled + record.Status = proto.LeaseCanceled record.CancelHeight = height if err := l.addLeasing(leaseID, record, blockID); err != nil { return nil, errors.Wrapf(err, "failed to save leasing %q to storage", leaseID) @@ -270,7 +262,7 @@ func (l *leases) cancelLeasing(id crypto.Digest, blockID proto.BlockID, height u if err != nil { return errors.Errorf("failed to get leasing info: %v", err) } - leasing.Status = LeaseCanceled + leasing.Status = proto.LeaseCanceled leasing.CancelHeight = height leasing.CancelTransactionID = txID return l.addLeasing(id, leasing, blockID) @@ -281,7 +273,7 @@ func (l *leases) cancelLeasingUncertain(id crypto.Digest, height uint64, txID *c if err != nil { return errors.Errorf("failed to get leasing info: %v", err) } - leasing.Status = LeaseCanceled + leasing.Status = proto.LeaseCanceled leasing.CancelTransactionID = txID leasing.CancelHeight = height l.addLeasingUncertain(id, leasing) diff --git a/pkg/state/leases_test.go b/pkg/state/leases_test.go index 57c02be7b..7222f3658 100644 --- a/pkg/state/leases_test.go +++ b/pkg/state/leases_test.go @@ -30,7 +30,7 @@ func createLease(t *testing.T, sender string, id crypto.Digest) *leasing { Recipient: recipientAddr, Sender: senderAddr, Amount: 10, - Status: LeaseActive, + Status: proto.LeaseActive, } } @@ -155,7 +155,7 @@ func TestCancelLeasing(t *testing.T) { assert.NoError(t, err, "failed to add leasing") err = to.leases.cancelLeasing(leaseID, blockID0, to.stor.rw.height, &txID) assert.NoError(t, err, "failed to cancel leasing") - r.Status = LeaseCanceled + r.Status = proto.LeaseCanceled r.CancelHeight = 1 r.CancelTransactionID = &txID to.stor.flush(t) diff --git a/pkg/state/snapshot_applier.go b/pkg/state/snapshot_applier.go index 5375925ed..02d9726b3 100644 --- a/pkg/state/snapshot_applier.go +++ b/pkg/state/snapshot_applier.go @@ -44,7 +44,7 @@ func newSnapshotApplierStorages(stor *blockchainEntitiesStorage) snapshotApplier } } -var _ = SnapshotApplier((*blockSnapshotsApplier)(nil)) +var _ = proto.SnapshotApplier((*blockSnapshotsApplier)(nil)) type blockSnapshotsApplierInfo struct { ci *checkerInfo @@ -83,7 +83,7 @@ func (s blockSnapshotsApplierInfo) StateActionsCounter() *proto.StateActionsCoun return s.stateActionsCounter } -func (a *blockSnapshotsApplier) ApplyWavesBalance(snapshot WavesBalanceSnapshot) error { +func (a *blockSnapshotsApplier) ApplyWavesBalance(snapshot proto.WavesBalanceSnapshot) error { addrID := snapshot.Address.ID() profile, err := a.stor.balances.wavesBalance(addrID) if err != nil { @@ -98,7 +98,7 @@ func (a *blockSnapshotsApplier) ApplyWavesBalance(snapshot WavesBalanceSnapshot) return nil } -func (a *blockSnapshotsApplier) ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) error { +func (a *blockSnapshotsApplier) ApplyLeaseBalance(snapshot proto.LeaseBalanceSnapshot) error { addrID := snapshot.Address.ID() var err error profile, err := a.stor.balances.wavesBalance(addrID) @@ -115,17 +115,17 @@ func (a *blockSnapshotsApplier) ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) return nil } -func (a *blockSnapshotsApplier) ApplyAssetBalance(snapshot AssetBalanceSnapshot) error { +func (a *blockSnapshotsApplier) ApplyAssetBalance(snapshot proto.AssetBalanceSnapshot) error { addrID := snapshot.Address.ID() assetID := proto.AssetIDFromDigest(snapshot.AssetID) return a.stor.balances.setAssetBalance(addrID, assetID, snapshot.Balance, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyAlias(snapshot AliasSnapshot) error { +func (a *blockSnapshotsApplier) ApplyAlias(snapshot proto.AliasSnapshot) error { return a.stor.aliases.createAlias(snapshot.Alias.Alias, snapshot.Address, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyStaticAssetInfo(snapshot StaticAssetInfoSnapshot) error { +func (a *blockSnapshotsApplier) ApplyStaticAssetInfo(snapshot proto.StaticAssetInfoSnapshot) error { assetID := proto.AssetIDFromDigest(snapshot.AssetID) assetFullInfo := &assetInfo{ assetConstInfo: assetConstInfo{ @@ -140,7 +140,7 @@ func (a *blockSnapshotsApplier) ApplyStaticAssetInfo(snapshot StaticAssetInfoSna return a.stor.assets.issueAsset(assetID, assetFullInfo, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyAssetDescription(snapshot AssetDescriptionSnapshot) error { +func (a *blockSnapshotsApplier) ApplyAssetDescription(snapshot proto.AssetDescriptionSnapshot) error { change := &assetInfoChange{ newName: snapshot.AssetName, newDescription: snapshot.AssetDescription, @@ -149,7 +149,7 @@ func (a *blockSnapshotsApplier) ApplyAssetDescription(snapshot AssetDescriptionS return a.stor.assets.updateAssetInfo(snapshot.AssetID, change, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyAssetVolume(snapshot AssetVolumeSnapshot) error { +func (a *blockSnapshotsApplier) ApplyAssetVolume(snapshot proto.AssetVolumeSnapshot) error { assetID := proto.AssetIDFromDigest(snapshot.AssetID) assetFullInfo, err := a.stor.assets.newestAssetInfo(assetID) if err != nil { @@ -160,7 +160,7 @@ func (a *blockSnapshotsApplier) ApplyAssetVolume(snapshot AssetVolumeSnapshot) e return a.stor.assets.storeAssetInfo(assetID, assetFullInfo, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyAssetScript(snapshot AssetScriptSnapshot) error { +func (a *blockSnapshotsApplier) ApplyAssetScript(snapshot proto.AssetScriptSnapshot) error { // estimation := ride.TreeEstimation{ // Estimation: int(snapshot.Complexity), // Verifier: int(snapshot.Complexity), @@ -180,11 +180,11 @@ func (a *blockSnapshotsApplier) ApplyAssetScript(snapshot AssetScriptSnapshot) e return a.stor.scriptsStorage.setAssetScript(snapshot.AssetID, snapshot.Script, snapshot.SenderPK, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplySponsorship(snapshot SponsorshipSnapshot) error { +func (a *blockSnapshotsApplier) ApplySponsorship(snapshot proto.SponsorshipSnapshot) error { return a.stor.sponsoredAssets.sponsorAsset(snapshot.AssetID, snapshot.MinSponsoredFee, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyAccountScript(snapshot AccountScriptSnapshot) error { +func (a *blockSnapshotsApplier) ApplyAccountScript(snapshot proto.AccountScriptSnapshot) error { addr, err := proto.NewAddressFromPublicKey(a.info.Scheme(), snapshot.SenderPublicKey) if err != nil { return errors.Wrapf(err, "failed to create address from scheme %d and PK %q", @@ -208,12 +208,12 @@ func (a *blockSnapshotsApplier) ApplyAccountScript(snapshot AccountScriptSnapsho return a.stor.scriptsStorage.setAccountScript(addr, snapshot.Script, snapshot.SenderPublicKey, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyFilledVolumeAndFee(snapshot FilledVolumeFeeSnapshot) error { +func (a *blockSnapshotsApplier) ApplyFilledVolumeAndFee(snapshot proto.FilledVolumeFeeSnapshot) error { return a.stor.ordersVolumes.storeFilled(snapshot.OrderID.Bytes(), snapshot.FilledVolume, snapshot.FilledFee, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyDataEntries(snapshot DataEntriesSnapshot) error { +func (a *blockSnapshotsApplier) ApplyDataEntries(snapshot proto.DataEntriesSnapshot) error { blockID := a.info.BlockID() for _, entry := range snapshot.DataEntries { if err := a.stor.accountsDataStor.appendEntry(snapshot.Address, entry, blockID); err != nil { @@ -223,7 +223,7 @@ func (a *blockSnapshotsApplier) ApplyDataEntries(snapshot DataEntriesSnapshot) e return nil } -func (a *blockSnapshotsApplier) ApplyLeaseState(snapshot LeaseStateSnapshot) error { +func (a *blockSnapshotsApplier) ApplyLeaseState(snapshot proto.LeaseStateSnapshot) error { l := &leasing{ Sender: snapshot.Sender, Recipient: snapshot.Recipient, diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index 95e6aa958..8f671b3b1 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -81,15 +81,15 @@ func (assetDiff addressAssetBalanceDiff) appendOnlySender( } } -func (sg *snapshotGenerator) generateSnapshotForGenesisTx(balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForGenesisTx(balanceChanges txDiff) (proto.TransactionSnapshot, error) { return sg.generateBalancesSnapshot(balanceChanges) } -func (sg *snapshotGenerator) generateSnapshotForPaymentTx(balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForPaymentTx(balanceChanges txDiff) (proto.TransactionSnapshot, error) { return sg.generateBalancesSnapshot(balanceChanges) } -func (sg *snapshotGenerator) generateSnapshotForTransferTx(balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForTransferTx(balanceChanges txDiff) (proto.TransactionSnapshot, error) { return sg.generateBalancesSnapshot(balanceChanges) } @@ -100,21 +100,21 @@ type scriptInformation struct { func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, txID crypto.Digest, senderPK crypto.PublicKey, assetInfo assetInfo, balanceChanges txDiff, - scriptInformation *scriptInformation) (TransactionSnapshot, error) { - var snapshot TransactionSnapshot + scriptInformation *scriptInformation) (proto.TransactionSnapshot, error) { + var snapshot proto.TransactionSnapshot addrWavesBalanceDiff, addrAssetBalanceDiff, err := balanceDiffFromTxDiff(balanceChanges, sg.scheme) 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 + var specialAssetSnapshot *proto.AssetBalanceSnapshot for key, diffAmount := range addrAssetBalanceDiff { if key.asset == proto.AssetIDFromDigest(assetID) { // remove the element from the array delete(addrAssetBalanceDiff, key) - specialAssetSnapshot = &AssetBalanceSnapshot{ + specialAssetSnapshot = &proto.AssetBalanceSnapshot{ Address: key.address, AssetID: assetID, Balance: uint64(diffAmount), @@ -122,7 +122,7 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t } } - issueStaticInfoSnapshot := &StaticAssetInfoSnapshot{ + issueStaticInfoSnapshot := &proto.StaticAssetInfoSnapshot{ AssetID: assetID, IssuerPublicKey: senderPK, SourceTransactionID: txID, @@ -130,14 +130,14 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t IsNFT: assetInfo.isNFT(), } - assetDescription := &AssetDescriptionSnapshot{ + assetDescription := &proto.AssetDescriptionSnapshot{ AssetID: assetID, AssetName: assetInfo.name, AssetDescription: assetInfo.description, ChangeHeight: assetInfo.lastNameDescChangeHeight, } - assetReissuability := &AssetVolumeSnapshot{ + assetReissuability := &proto.AssetVolumeSnapshot{ AssetID: assetID, IsReissuable: assetInfo.reissuable, TotalQuantity: assetInfo.quantity, @@ -146,7 +146,7 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) if scriptInformation != nil { - assetScriptSnapshot := &AssetScriptSnapshot{ + assetScriptSnapshot := &proto.AssetScriptSnapshot{ AssetID: assetID, Script: scriptInformation.script, Complexity: uint64(scriptInformation.complexity), @@ -174,7 +174,7 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t } func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, - change assetReissueChange, balanceChanges txDiff) (TransactionSnapshot, error) { + change assetReissueChange, balanceChanges txDiff) (proto.TransactionSnapshot, error) { quantityDiff := big.NewInt(change.diff) assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) if err != nil { @@ -186,7 +186,7 @@ func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } - assetReissuability := &AssetVolumeSnapshot{ + assetReissuability := &proto.AssetVolumeSnapshot{ AssetID: assetID, TotalQuantity: *resQuantity, IsReissuable: change.reissuable, @@ -196,7 +196,7 @@ func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, } func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, change assetBurnChange, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { quantityDiff := big.NewInt(change.diff) assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) if err != nil { @@ -208,7 +208,7 @@ func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, ch if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } - assetReissuability := &AssetVolumeSnapshot{ + assetReissuability := &proto.AssetVolumeSnapshot{ AssetID: assetID, TotalQuantity: *resQuantity, IsReissuable: assetInfo.reissuable, @@ -219,7 +219,7 @@ func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, ch func (sg *snapshotGenerator) generateSnapshotForExchangeTx(sellOrder proto.Order, sellFee uint64, buyOrder proto.Order, buyFee uint64, volume uint64, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") @@ -247,7 +247,7 @@ func (sg *snapshotGenerator) generateSnapshotForExchangeTx(sellOrder proto.Order } func (sg *snapshotGenerator) generateSnapshotForLeaseTx(lease leasing, leaseID crypto.Digest, - originalTxID crypto.Digest, balanceChanges txDiff) (TransactionSnapshot, error) { + originalTxID crypto.Digest, balanceChanges txDiff) (proto.TransactionSnapshot, error) { var err error snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { @@ -266,7 +266,7 @@ func (sg *snapshotGenerator) generateSnapshotForLeaseTx(lease leasing, leaseID c func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Digest, oldLease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, - cancelHeight uint64, balanceChanges txDiff) (TransactionSnapshot, error) { + cancelHeight uint64, balanceChanges txDiff) (proto.TransactionSnapshot, error) { var err error snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { @@ -278,8 +278,8 @@ func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Diges if err != nil { return nil, errors.Wrap(err, "failed to generate snapshots for a lease transaction") } - leaseStatusSnapshot.Status = LeaseStateStatus{ - Value: LeaseCanceled, + leaseStatusSnapshot.Status = proto.LeaseStateStatus{ + Value: proto.LeaseCanceled, CancelHeight: cancelHeight, CancelTransactionID: txID, } @@ -289,12 +289,12 @@ func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Diges } func (sg *snapshotGenerator) generateSnapshotForCreateAliasTx(senderAddress proto.WavesAddress, alias proto.Alias, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - aliasSnapshot := &AliasSnapshot{ + aliasSnapshot := &proto.AliasSnapshot{ Address: senderAddress, Alias: alias, } @@ -302,17 +302,19 @@ func (sg *snapshotGenerator) generateSnapshotForCreateAliasTx(senderAddress prot return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForMassTransferTx(balanceChanges txDiff) (TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForMassTransferTx( + balanceChanges txDiff, +) (proto.TransactionSnapshot, error) { return sg.generateBalancesSnapshot(balanceChanges) } func (sg *snapshotGenerator) generateSnapshotForDataTx(senderAddress proto.WavesAddress, entries []proto.DataEntry, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - dataEntriesSnapshot := &DataEntriesSnapshot{ + dataEntriesSnapshot := &proto.DataEntriesSnapshot{ Address: senderAddress, DataEntries: entries, } @@ -321,12 +323,12 @@ func (sg *snapshotGenerator) generateSnapshotForDataTx(senderAddress proto.Waves } func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Digest, - minAssetFee uint64, balanceChanges txDiff) (TransactionSnapshot, error) { + minAssetFee uint64, balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - sponsorshipSnapshot := &SponsorshipSnapshot{ + sponsorshipSnapshot := &proto.SponsorshipSnapshot{ AssetID: assetID, MinSponsoredFee: minAssetFee, } @@ -335,12 +337,12 @@ func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Dig } func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.PublicKey, script proto.Script, - complexity int, balanceChanges txDiff) (TransactionSnapshot, error) { + complexity int, balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - sponsorshipSnapshot := &AccountScriptSnapshot{ + sponsorshipSnapshot := &proto.AccountScriptSnapshot{ SenderPublicKey: senderPK, Script: script, VerifierComplexity: uint64(complexity), @@ -350,13 +352,13 @@ func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.Publ } func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, - complexity int, senderPK crypto.PublicKey, balanceChanges txDiff) (TransactionSnapshot, error) { + complexity int, senderPK crypto.PublicKey, balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - sponsorshipSnapshot := &AssetScriptSnapshot{ + sponsorshipSnapshot := &proto.AssetScriptSnapshot{ AssetID: assetID, Script: script, Complexity: uint64(complexity), @@ -368,29 +370,29 @@ func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto. func (sg *snapshotGenerator) generateSnapshotForInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff, - txPublicKey crypto.PublicKey) (TransactionSnapshot, error) { + txPublicKey crypto.PublicKey) (proto.TransactionSnapshot, error) { return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges, txPublicKey) } func (sg *snapshotGenerator) generateSnapshotForInvokeExpressionTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff, - txPublicKey crypto.PublicKey) (TransactionSnapshot, error) { + txPublicKey crypto.PublicKey) (proto.TransactionSnapshot, error) { return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges, txPublicKey) } func (sg *snapshotGenerator) generateSnapshotForEthereumInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff, - txPublicKey crypto.PublicKey) (TransactionSnapshot, error) { + txPublicKey crypto.PublicKey) (proto.TransactionSnapshot, error) { return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges, txPublicKey) } func (sg *snapshotGenerator) generateSnapshotForUpdateAssetInfoTx(assetID crypto.Digest, assetName string, - assetDescription string, changeHeight proto.Height, balanceChanges txDiff) (TransactionSnapshot, error) { + assetDescription string, changeHeight proto.Height, balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - sponsorshipSnapshot := &AssetDescriptionSnapshot{ + sponsorshipSnapshot := &proto.AssetDescriptionSnapshot{ AssetID: assetID, AssetName: assetName, AssetDescription: assetDescription, @@ -462,8 +464,8 @@ func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( info *performerInfo, txID crypto.Digest, assetBalanceDiff addressAssetBalanceDiff, - senderPK crypto.PublicKey) ([]AtomicSnapshot, error) { - var atomicSnapshots []AtomicSnapshot + senderPK crypto.PublicKey) ([]proto.AtomicSnapshot, error) { + var atomicSnapshots []proto.AtomicSnapshot assetInf := assetInfo{ assetConstInfo: assetConstInfo{ tail: proto.DigestTail(action.ID), @@ -480,7 +482,7 @@ func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( }, } - issueStaticInfoSnapshot := &StaticAssetInfoSnapshot{ + issueStaticInfoSnapshot := &proto.StaticAssetInfoSnapshot{ AssetID: action.ID, IssuerPublicKey: senderPK, SourceTransactionID: txID, @@ -488,14 +490,14 @@ func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( IsNFT: assetInf.isNFT(), } - assetDescription := &AssetDescriptionSnapshot{ + assetDescription := &proto.AssetDescriptionSnapshot{ AssetID: action.ID, AssetName: assetInf.name, AssetDescription: assetInf.description, ChangeHeight: assetInf.lastNameDescChangeHeight, } - assetReissuability := &AssetVolumeSnapshot{ + assetReissuability := &proto.AssetVolumeSnapshot{ AssetID: action.ID, IsReissuable: assetInf.reissuable, TotalQuantity: assetInf.quantity, @@ -511,7 +513,7 @@ func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( } } if scriptInfo != nil { - assetScriptSnapshot := &AssetScriptSnapshot{ + assetScriptSnapshot := &proto.AssetScriptSnapshot{ AssetID: action.ID, Script: scriptInfo.script, Complexity: uint64(scriptInfo.complexity), @@ -531,15 +533,15 @@ func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( func (sg *snapshotGenerator) atomicActionsFromReissueAction( action proto.ReissueScriptAction, assetBalanceDiff addressAssetBalanceDiff, - issuer proto.WavesAddress) ([]AtomicSnapshot, error) { - var atomicSnapshots []AtomicSnapshot + issuer proto.WavesAddress) ([]proto.AtomicSnapshot, error) { + var atomicSnapshots []proto.AtomicSnapshot assetInf, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(action.AssetID)) if err != nil { return nil, err } quantityDiff := big.NewInt(action.Quantity) resQuantity := assetInf.quantity.Add(&assetInf.quantity, quantityDiff) - assetReissuability := &AssetVolumeSnapshot{ + assetReissuability := &proto.AssetVolumeSnapshot{ AssetID: action.AssetID, TotalQuantity: *resQuantity, IsReissuable: action.Reissuable, @@ -552,8 +554,8 @@ func (sg *snapshotGenerator) atomicActionsFromReissueAction( func (sg *snapshotGenerator) atomicActionsFromBurnAction( action proto.BurnScriptAction, assetBalanceDiff addressAssetBalanceDiff, - issuer proto.WavesAddress) ([]AtomicSnapshot, error) { - var atomicSnapshots []AtomicSnapshot + issuer proto.WavesAddress) ([]proto.AtomicSnapshot, error) { + var atomicSnapshots []proto.AtomicSnapshot var assetInf *assetInfo assetInf, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(action.AssetID)) if err != nil { @@ -561,7 +563,7 @@ func (sg *snapshotGenerator) atomicActionsFromBurnAction( } quantityDiff := big.NewInt(action.Quantity) resQuantity := assetInf.quantity.Sub(&assetInf.quantity, quantityDiff) - assetReissuability := &AssetVolumeSnapshot{ + assetReissuability := &proto.AssetVolumeSnapshot{ AssetID: action.AssetID, TotalQuantity: *resQuantity, IsReissuable: assetInf.reissuable, @@ -575,8 +577,8 @@ func (sg *snapshotGenerator) atomicActionsFromLeaseAction( action proto.LeaseScriptAction, info *performerInfo, txID crypto.Digest, - sender proto.WavesAddress) ([]AtomicSnapshot, error) { - var atomicSnapshots []AtomicSnapshot + sender proto.WavesAddress) ([]proto.AtomicSnapshot, error) { + var atomicSnapshots []proto.AtomicSnapshot var err error var recipientAddr proto.WavesAddress @@ -593,7 +595,7 @@ func (sg *snapshotGenerator) atomicActionsFromLeaseAction( Recipient: recipientAddr, Amount: uint64(action.Amount), Height: info.height, - Status: LeaseActive, + Status: proto.LeaseActive, } var amount = int64(l.Amount) leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := @@ -610,8 +612,8 @@ func (sg *snapshotGenerator) atomicActionsFromLeaseAction( func (sg *snapshotGenerator) atomicSnapshotsFromLeaseCancelAction( action proto.LeaseCancelScriptAction, - txID crypto.Digest) ([]AtomicSnapshot, error) { - var atomicSnapshots []AtomicSnapshot + txID crypto.Digest) ([]proto.AtomicSnapshot, error) { + var atomicSnapshots []proto.AtomicSnapshot // TODO what if the leasing is not in the stor yet? lease and leaseCancel in the same contract? leasingInfo, err := sg.stor.leases.leasingInfo(action.LeaseID) if err != nil { @@ -641,8 +643,8 @@ func (sg *snapshotGenerator) collectBalanceAndSnapshotFromAction( txID crypto.Digest, senderAddress proto.WavesAddress, senderPK crypto.PublicKey, -) ([]AtomicSnapshot, error) { - var atomicSnapshots []AtomicSnapshot +) ([]proto.AtomicSnapshot, error) { + var atomicSnapshots []proto.AtomicSnapshot switch a := action.(type) { case *proto.DataEntryScriptAction: // snapshots store data entries in a different format, so we convert the actions to this format @@ -661,7 +663,7 @@ func (sg *snapshotGenerator) collectBalanceAndSnapshotFromAction( return nil, err } case *proto.SponsorshipScriptAction: - sponsorshipSnapshot := &SponsorshipSnapshot{ + sponsorshipSnapshot := &proto.SponsorshipSnapshot{ AssetID: a.AssetID, MinSponsoredFee: uint64(a.MinFee), } @@ -727,9 +729,9 @@ func (sg *snapshotGenerator) atomicSnapshotsFromScriptActions( blockHeight uint64, info *performerInfo, txID crypto.Digest, - txPublicKey crypto.PublicKey) ([]AtomicSnapshot, error) { + txPublicKey crypto.PublicKey) ([]proto.AtomicSnapshot, error) { var dataEntries = make(SenderDataEntries) - var atomicSnapshots []AtomicSnapshot + var atomicSnapshots []proto.AtomicSnapshot for _, action := range actions { senderAddress, senderPK, err := senderFromScriptAction(action, txPublicKey, sg.scheme) if err != nil { @@ -745,7 +747,7 @@ func (sg *snapshotGenerator) atomicSnapshotsFromScriptActions( } for address, entries := range dataEntries { - dataEntrySnapshot := &DataEntriesSnapshot{Address: address, DataEntries: entries} + dataEntrySnapshot := &proto.DataEntriesSnapshot{Address: address, DataEntries: entries} atomicSnapshots = append(atomicSnapshots, dataEntrySnapshot) } return atomicSnapshots, nil @@ -755,16 +757,16 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, - balanceChanges txDiff, txPublicKey crypto.PublicKey) (TransactionSnapshot, error) { + balanceChanges txDiff, txPublicKey crypto.PublicKey) (proto.TransactionSnapshot, error) { blockHeight := info.height + 1 addrWavesBalanceDiff, addrAssetBalanceDiff, err := balanceDiffFromTxDiff(balanceChanges, sg.scheme) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") } - var snapshot TransactionSnapshot + var snapshot proto.TransactionSnapshot if invocationRes != nil { - var atomicSnapshots []AtomicSnapshot + var atomicSnapshots []proto.AtomicSnapshot atomicSnapshots, err = sg.atomicSnapshotsFromScriptActions( invocationRes.actions, addrWavesBalanceDiff, addrAssetBalanceDiff, blockHeight, info, txID, @@ -795,10 +797,10 @@ func (sg *snapshotGenerator) generateLeaseAtomicSnapshots(leaseID crypto.Digest, l leasing, originalTxID crypto.Digest, senderAddress proto.WavesAddress, receiverAddress proto.WavesAddress, - amount int64) (*LeaseStateSnapshot, *LeaseBalanceSnapshot, *LeaseBalanceSnapshot, error) { - leaseStatusSnapshot := &LeaseStateSnapshot{ + amount int64) (*proto.LeaseStateSnapshot, *proto.LeaseBalanceSnapshot, *proto.LeaseBalanceSnapshot, error) { + leaseStatusSnapshot := &proto.LeaseStateSnapshot{ LeaseID: leaseID, - Status: LeaseStateStatus{ + Status: proto.LeaseStateStatus{ Value: l.Status, }, Amount: l.Amount, @@ -812,7 +814,7 @@ func (sg *snapshotGenerator) generateLeaseAtomicSnapshots(leaseID crypto.Digest, if err != nil { return nil, nil, nil, errors.Wrap(err, "failed to receive sender's waves balance") } - senderLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ + senderLeaseBalanceSnapshot := &proto.LeaseBalanceSnapshot{ Address: senderAddress, LeaseIn: uint64(senderBalanceProfile.leaseIn), LeaseOut: uint64(senderBalanceProfile.leaseOut + amount), @@ -822,7 +824,7 @@ func (sg *snapshotGenerator) generateLeaseAtomicSnapshots(leaseID crypto.Digest, if err != nil { return nil, nil, nil, errors.Wrap(err, "failed to receive recipient's waves balance") } - recipientLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ + recipientLeaseBalanceSnapshot := &proto.LeaseBalanceSnapshot{ Address: receiverAddress, LeaseIn: uint64(receiverBalanceProfile.leaseIn + amount), LeaseOut: uint64(receiverBalanceProfile.leaseOut), @@ -832,7 +834,7 @@ func (sg *snapshotGenerator) generateLeaseAtomicSnapshots(leaseID crypto.Digest, } func (sg *snapshotGenerator) generateOrderAtomicSnapshot(orderID []byte, - volume uint64, fee uint64) (*FilledVolumeFeeSnapshot, error) { + volume uint64, fee uint64) (*proto.FilledVolumeFeeSnapshot, error) { newestFilledAmount, newestFilledFee, err := sg.stor.ordersVolumes.newestFilled(orderID) if err != nil { return nil, err @@ -842,7 +844,7 @@ func (sg *snapshotGenerator) generateOrderAtomicSnapshot(orderID []byte, return nil, errors.Wrap(err, "failed to construct digest from order id bytes") } // TODO must be added to newest filled amounts and fee - orderSnapshot := &FilledVolumeFeeSnapshot{ + orderSnapshot := &proto.FilledVolumeFeeSnapshot{ OrderID: orderIDDigset, FilledFee: newestFilledFee + fee, FilledVolume: newestFilledAmount + volume, @@ -850,8 +852,8 @@ func (sg *snapshotGenerator) generateOrderAtomicSnapshot(orderID []byte, return orderSnapshot, nil } -func (sg *snapshotGenerator) generateBalancesSnapshot(balanceChanges txDiff) (TransactionSnapshot, error) { - var transactionSnapshot TransactionSnapshot +func (sg *snapshotGenerator) generateBalancesSnapshot(balanceChanges txDiff) (proto.TransactionSnapshot, error) { + var transactionSnapshot proto.TransactionSnapshot addrWavesBalanceDiff, addrAssetBalanceDiff, err := balanceDiffFromTxDiff(balanceChanges, sg.scheme) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") @@ -871,7 +873,7 @@ func (sg *snapshotGenerator) generateBalancesSnapshot(balanceChanges txDiff) (Tr } func (sg *snapshotGenerator) generateBalancesAtomicSnapshots(addrWavesBalanceDiff addressWavesBalanceDiff, - addrAssetBalanceDiff addressAssetBalanceDiff) ([]WavesBalanceSnapshot, []AssetBalanceSnapshot, error) { + addrAssetBalanceDiff addressAssetBalanceDiff) ([]proto.WavesBalanceSnapshot, []proto.AssetBalanceSnapshot, error) { wavesBalanceSnapshot, err := sg.wavesBalanceSnapshotFromBalanceDiff(addrWavesBalanceDiff) if err != nil { return nil, nil, errors.Wrap(err, "failed to construct waves balance snapshot") @@ -927,8 +929,8 @@ func balanceDiffFromTxDiff(diff txDiff, scheme proto.Scheme) (addressWavesBalanc // from txDiff and fees. no validation needed at this point. func (sg *snapshotGenerator) wavesBalanceSnapshotFromBalanceDiff( - diff addressWavesBalanceDiff) ([]WavesBalanceSnapshot, error) { - var wavesBalances []WavesBalanceSnapshot + diff addressWavesBalanceDiff) ([]proto.WavesBalanceSnapshot, error) { + var wavesBalances []proto.WavesBalanceSnapshot // add miner address to the diff for wavesAddress, diffAmount := range diff { @@ -936,7 +938,7 @@ func (sg *snapshotGenerator) wavesBalanceSnapshotFromBalanceDiff( if err != nil { return nil, errors.Wrap(err, "failed to receive sender's waves balance") } - newBalance := WavesBalanceSnapshot{ + newBalance := proto.WavesBalanceSnapshot{ Address: wavesAddress, Balance: uint64(int64(fullBalance.balance) + diffAmount.balance), } @@ -946,8 +948,8 @@ func (sg *snapshotGenerator) wavesBalanceSnapshotFromBalanceDiff( } func (sg *snapshotGenerator) assetBalanceSnapshotFromBalanceDiff( - diff addressAssetBalanceDiff) ([]AssetBalanceSnapshot, error) { - var assetBalances []AssetBalanceSnapshot + diff addressAssetBalanceDiff) ([]proto.AssetBalanceSnapshot, error) { + var assetBalances []proto.AssetBalanceSnapshot // add miner address to the diff for key, diffAmount := range diff { @@ -960,7 +962,7 @@ func (sg *snapshotGenerator) assetBalanceSnapshotFromBalanceDiff( return nil, errors.Wrap(err, "failed to get newest asset info") } - newBalance := AssetBalanceSnapshot{ + newBalance := proto.AssetBalanceSnapshot{ Address: key.address, AssetID: key.asset.Digest(assetInfo.tail), Balance: uint64(int64(balance) + diffAmount), diff --git a/pkg/state/snapshot_generator_internal_test.go b/pkg/state/snapshot_generator_internal_test.go index a1d610c20..63fecff77 100644 --- a/pkg/state/snapshot_generator_internal_test.go +++ b/pkg/state/snapshot_generator_internal_test.go @@ -79,16 +79,16 @@ func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { transactionSnapshot, err := to.tp.performTransferWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform transfer tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.issuerInfo.addr, Balance: 299700000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.recipientInfo.addr, Balance: 200000, }, @@ -138,33 +138,33 @@ func TestDefaultIssueTransactionSnapshot(t *testing.T) { defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform issue tx") - expectedSnapshot := TransactionSnapshot{ - &StaticAssetInfoSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.StaticAssetInfoSnapshot{ AssetID: *tx.ID, SourceTransactionID: *tx.ID, IssuerPublicKey: testGlobal.issuerInfo.pk, Decimals: defaultDecimals, IsNFT: false}, - &AssetDescriptionSnapshot{ + &proto.AssetDescriptionSnapshot{ AssetID: *tx.ID, AssetName: "asset0", AssetDescription: "description", ChangeHeight: 1, }, - &AssetVolumeSnapshot{ + &proto.AssetVolumeSnapshot{ AssetID: *tx.ID, TotalQuantity: *big.NewInt(int64(defaultQuantity)), IsReissuable: true, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.issuerInfo.addr, Balance: 299900000, }, - &AssetBalanceSnapshot{ + &proto.AssetBalanceSnapshot{ Address: testGlobal.issuerInfo.addr, AssetID: *tx.ID, Balance: 1000, @@ -222,21 +222,21 @@ func TestDefaultReissueSnapshot(t *testing.T) { defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform reissue tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.issuerInfo.addr, Balance: 299900000, }, - &AssetBalanceSnapshot{ + &proto.AssetBalanceSnapshot{ Address: testGlobal.issuerInfo.addr, AssetID: testGlobal.asset0.assetID, Balance: 1050, }, - &AssetVolumeSnapshot{ + &proto.AssetVolumeSnapshot{ AssetID: testGlobal.asset0.assetID, TotalQuantity: *big.NewInt(int64(defaultQuantity + 50)), IsReissuable: false, @@ -293,21 +293,21 @@ func TestDefaultBurnSnapshot(t *testing.T) { defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.issuerInfo.addr, Balance: 299900000, }, - &AssetBalanceSnapshot{ + &proto.AssetBalanceSnapshot{ Address: testGlobal.issuerInfo.addr, AssetID: testGlobal.asset0.assetID, Balance: 950, }, - &AssetVolumeSnapshot{ + &proto.AssetVolumeSnapshot{ AssetID: testGlobal.asset0.assetID, TotalQuantity: *big.NewInt(int64(defaultQuantity - 100)), IsReissuable: false, @@ -393,49 +393,49 @@ func TestDefaultExchangeTransaction(t *testing.T) { nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.senderInfo.addr, Balance: 299999999, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.recipientInfo.addr, Balance: 599999998, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.matcherInfo.addr, Balance: 899900003, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &AssetBalanceSnapshot{ + &proto.AssetBalanceSnapshot{ Address: testGlobal.senderInfo.addr, AssetID: testGlobal.asset0.assetID, Balance: 10, }, - &AssetBalanceSnapshot{ + &proto.AssetBalanceSnapshot{ Address: testGlobal.recipientInfo.addr, AssetID: testGlobal.asset0.assetID, Balance: 590, }, - &AssetBalanceSnapshot{ + &proto.AssetBalanceSnapshot{ Address: testGlobal.senderInfo.addr, AssetID: testGlobal.asset1.assetID, Balance: 400, }, - &AssetBalanceSnapshot{ + &proto.AssetBalanceSnapshot{ Address: testGlobal.recipientInfo.addr, AssetID: testGlobal.asset1.assetID, Balance: 100, }, - &FilledVolumeFeeSnapshot{ + &proto.FilledVolumeFeeSnapshot{ OrderID: *bo.ID, FilledVolume: 10, FilledFee: 1, }, - &FilledVolumeFeeSnapshot{ + &proto.FilledVolumeFeeSnapshot{ OrderID: *so.ID, FilledVolume: 10, FilledFee: 2, @@ -485,19 +485,19 @@ func TestDefaultLeaseSnapshot(t *testing.T) { nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.senderInfo.addr, Balance: 299900000, }, - &LeaseStateSnapshot{ + &proto.LeaseStateSnapshot{ LeaseID: *tx.ID, - Status: LeaseStateStatus{ - Value: LeaseActive, + Status: proto.LeaseStateStatus{ + Value: proto.LeaseActive, }, Amount: 50, Sender: testGlobal.senderInfo.addr, @@ -505,12 +505,12 @@ func TestDefaultLeaseSnapshot(t *testing.T) { OriginTransactionID: tx.ID, Height: 0, }, - &LeaseBalanceSnapshot{ + &proto.LeaseBalanceSnapshot{ Address: testGlobal.senderInfo.addr, LeaseIn: 0, LeaseOut: 50, }, - &LeaseBalanceSnapshot{ + &proto.LeaseBalanceSnapshot{ Address: testGlobal.recipientInfo.addr, LeaseIn: 50, LeaseOut: 0, @@ -551,7 +551,7 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { Recipient: testGlobal.recipientInfo.addr, Amount: 50, Height: 1, - Status: LeaseActive, + Status: proto.LeaseActive, OriginTransactionID: &leaseID, } err := to.stor.entities.leases.addLeasing(leaseID, leasing, blockID0) @@ -576,19 +576,19 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.senderInfo.addr, Balance: 299900000, }, - &LeaseStateSnapshot{ + &proto.LeaseStateSnapshot{ LeaseID: leaseID, - Status: LeaseStateStatus{ - Value: LeaseCanceled, + Status: proto.LeaseStateStatus{ + Value: proto.LeaseCanceled, CancelHeight: 0, CancelTransactionID: tx.ID, }, @@ -598,12 +598,12 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { OriginTransactionID: &leaseID, Height: 1, }, - &LeaseBalanceSnapshot{ + &proto.LeaseBalanceSnapshot{ Address: testGlobal.senderInfo.addr, LeaseIn: 0, LeaseOut: 0, }, - &LeaseBalanceSnapshot{ + &proto.LeaseBalanceSnapshot{ Address: testGlobal.recipientInfo.addr, LeaseIn: 0, LeaseOut: 0, @@ -651,16 +651,16 @@ func TestDefaultCreateAliasSnapshot(t *testing.T) { nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.senderInfo.addr, Balance: 299900000, }, - &AliasSnapshot{ + &proto.AliasSnapshot{ Address: testGlobal.senderInfo.addr, Alias: *proto.NewAlias(proto.TestNetScheme, "aliasForSender"), }, @@ -716,16 +716,16 @@ func TestDefaultDataSnapshot(t *testing.T) { nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.senderInfo.addr, Balance: 299900000, }, - &DataEntriesSnapshot{ + &proto.DataEntriesSnapshot{ Address: testGlobal.senderInfo.addr, DataEntries: []proto.DataEntry{&proto.StringDataEntry{Key: "key_str", Value: "value_str"}, &proto.IntegerDataEntry{Key: "key_int", Value: 2}}, @@ -775,16 +775,16 @@ func TestDefaultSponsorshipSnapshot(t *testing.T) { defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.senderInfo.addr, Balance: 299900000, }, - &SponsorshipSnapshot{ + &proto.SponsorshipSnapshot{ AssetID: testGlobal.asset0.assetID, MinSponsoredFee: 500000, }, @@ -840,16 +840,16 @@ func TestDefaultSetScriptSnapshot(t *testing.T) { defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.senderInfo.addr, Balance: 299900000, }, - &AccountScriptSnapshot{ + &proto.AccountScriptSnapshot{ SenderPublicKey: testGlobal.senderInfo.pk, Script: testGlobal.scriptBytes, VerifierComplexity: 340, @@ -915,16 +915,16 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.T) { defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 40000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.senderInfo.addr, Balance: 299900000, }, - &AssetScriptSnapshot{ + &proto.AssetScriptSnapshot{ AssetID: testGlobal.asset0.assetID, Script: testGlobal.scriptBytes, Complexity: 340, @@ -1039,16 +1039,16 @@ func TestDefaultInvokeScriptSnapshot(t *testing.T) { invocationResult, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform invoke script tx") - expectedSnapshot := TransactionSnapshot{ - &WavesBalanceSnapshot{ + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.minerInfo.addr, Balance: 200000, }, - &WavesBalanceSnapshot{ + &proto.WavesBalanceSnapshot{ Address: testGlobal.senderInfo.addr, Balance: 299500000, }, - &DataEntriesSnapshot{ + &proto.DataEntriesSnapshot{ Address: testGlobal.recipientInfo.addr, DataEntries: []proto.DataEntry{ &proto.BooleanDataEntry{Key: "bool", Value: true}, diff --git a/pkg/state/transaction_handler.go b/pkg/state/transaction_handler.go index 0388b935d..00b840d09 100644 --- a/pkg/state/transaction_handler.go +++ b/pkg/state/transaction_handler.go @@ -24,7 +24,7 @@ type scriptEstimation struct { func (e *scriptEstimation) isPresent() bool { return e != nil } type txCheckFunc func(proto.Transaction, *checkerInfo) (txCheckerData, error) -type txPerformFunc func(proto.Transaction, *performerInfo, *invocationResult, txDiff) (TransactionSnapshot, error) +type txPerformFunc func(proto.Transaction, *performerInfo, *invocationResult, txDiff) (proto.TransactionSnapshot, error) type txCreateDiffFunc func(proto.Transaction, *differInfo) (txBalanceChanges, error) type txCountFeeFunc func(proto.Transaction, *feeDistribution) error @@ -199,7 +199,7 @@ func (h *transactionHandler) checkTx(tx proto.Transaction, info *checkerInfo) (t } func (h *transactionHandler) performTx(tx proto.Transaction, info *performerInfo, - invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + invocationRes *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tv := tx.GetTypeInfo() funcs, ok := h.funcs[tv] if !ok { diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 85e95ad59..430970be1 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -29,8 +29,8 @@ func newPerformerInfo(height proto.Height, stateActionsCounter *proto.StateActio type transactionPerformer struct { stor *blockchainEntitiesStorage settings *settings.BlockchainSettings - snapshotGenerator *snapshotGenerator // initialized in appendTx - snapshotApplier SnapshotApplier // initialized in appendTx + snapshotGenerator *snapshotGenerator // initialized in appendTx + snapshotApplier proto.SnapshotApplier // initialized in appendTx } func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings.BlockchainSettings) (*transactionPerformer, error) { @@ -40,7 +40,7 @@ func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings func (tp *transactionPerformer) performGenesis( transaction proto.Transaction, _ *performerInfo, _ *invocationResult, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { _, ok := transaction.(*proto.Genesis) if !ok { return nil, errors.New("failed to convert interface to genesis transaction") @@ -53,7 +53,7 @@ func (tp *transactionPerformer) performGenesis( } func (tp *transactionPerformer) performPayment(transaction proto.Transaction, _ *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { _, ok := transaction.(*proto.Payment) if !ok { return nil, errors.New("failed to convert interface to payment transaction") @@ -65,7 +65,7 @@ func (tp *transactionPerformer) performPayment(transaction proto.Transaction, _ return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performTransfer(balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performTransfer(balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := tp.snapshotGenerator.generateSnapshotForTransferTx(balanceChanges) if err != nil { return nil, err @@ -74,7 +74,7 @@ func (tp *transactionPerformer) performTransfer(balanceChanges txDiff) (Transact } func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transaction, _ *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { _, ok := transaction.(*proto.TransferWithSig) if !ok { return nil, errors.New("failed to convert interface to transfer with sig transaction") @@ -83,7 +83,7 @@ func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transac } func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Transaction, _ *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { _, ok := transaction.(*proto.TransferWithProofs) if !ok { return nil, errors.New("failed to convert interface to transfer with proofs transaction") @@ -93,7 +93,7 @@ func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Tran func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest, assetID crypto.Digest, info *performerInfo, - balanceChanges txDiff, scriptInformation *scriptInformation) (TransactionSnapshot, error) { + balanceChanges txDiff, scriptInformation *scriptInformation) (proto.TransactionSnapshot, error) { blockHeight := info.height + 1 // Create new asset. assetInfo := &assetInfo{ @@ -122,7 +122,7 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest } func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.IssueWithSig) if !ok { return nil, errors.New("failed to convert interface to IssueWithSig transaction") @@ -142,7 +142,7 @@ func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transactio } func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.IssueWithProofs) if !ok { return nil, errors.New("failed to convert interface to IssueWithProofs transaction") @@ -175,7 +175,7 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac } func (tp *transactionPerformer) performReissue(tx *proto.Reissue, _ *performerInfo, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { // Modify asset. change := &assetReissueChange{ reissuable: tx.Reissuable, @@ -190,7 +190,7 @@ func (tp *transactionPerformer) performReissue(tx *proto.Reissue, _ *performerIn } func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.ReissueWithSig) if !ok { return nil, errors.New("failed to convert interface to ReissueWithSig transaction") @@ -199,7 +199,7 @@ func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transact } func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Transaction, - info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + info *performerInfo, _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.ReissueWithProofs) if !ok { return nil, errors.New("failed to convert interface to ReissueWithProofs transaction") @@ -208,7 +208,7 @@ func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Trans } func (tp *transactionPerformer) performBurn(tx *proto.Burn, _ *performerInfo, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { // Modify asset. change := &assetBurnChange{ diff: int64(tx.Amount), @@ -222,7 +222,7 @@ func (tp *transactionPerformer) performBurn(tx *proto.Burn, _ *performerInfo, } func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.BurnWithSig) if !ok { return nil, errors.New("failed to convert interface to BurnWithSig transaction") @@ -231,7 +231,7 @@ func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction } func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.BurnWithProofs) if !ok { return nil, errors.New("failed to convert interface to BurnWithProofs transaction") @@ -240,7 +240,7 @@ func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transact } func (tp *transactionPerformer) performExchange(transaction proto.Transaction, _ *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(proto.Exchange) if !ok { return nil, errors.New("failed to convert interface to Exchange transaction") @@ -267,7 +267,7 @@ func (tp *transactionPerformer) performExchange(transaction proto.Transaction, _ } func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest, info *performerInfo, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { return nil, err @@ -287,7 +287,7 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest Recipient: recipientAddr, Amount: tx.Amount, Height: info.height, - Status: LeaseActive, + Status: proto.LeaseActive, } snapshot, err := tp.snapshotGenerator.generateSnapshotForLeaseTx(*l, txID, txID, balanceChanges) if err != nil { @@ -297,7 +297,7 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest } func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseWithSig) if !ok { return nil, errors.New("failed to convert interface to LeaseWithSig transaction") @@ -306,7 +306,7 @@ func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transactio } func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseWithProofs) if !ok { return nil, errors.New("failed to convert interface to LeaseWithProofs transaction") @@ -315,7 +315,7 @@ func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transac } func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID *crypto.Digest, info *performerInfo, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { oldLease, err := tp.stor.leases.newestLeasingInfo(tx.LeaseID) if err != nil { return nil, errors.Wrap(err, "failed to receiver leasing info") @@ -331,7 +331,7 @@ func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID * } func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseCancelWithSig) if !ok { return nil, errors.New("failed to convert interface to LeaseCancelWithSig transaction") @@ -340,7 +340,7 @@ func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Tran } func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseCancelWithProofs) if !ok { return nil, errors.New("failed to convert interface to LeaseCancelWithProofs transaction") @@ -349,7 +349,7 @@ func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.T } func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, - _ *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *performerInfo, balanceChanges txDiff) (proto.TransactionSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { return nil, err @@ -363,7 +363,7 @@ func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, } func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.CreateAliasWithSig) if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithSig transaction") @@ -372,7 +372,7 @@ func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Tran } func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.CreateAliasWithProofs) if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") @@ -381,7 +381,7 @@ func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.T } func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto.Transaction, _ *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { _, ok := transaction.(*proto.MassTransferWithProofs) if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") @@ -394,7 +394,7 @@ func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto. } func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, - _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.DataWithProofs) if !ok { return nil, errors.New("failed to convert interface to DataWithProofs transaction") @@ -412,7 +412,7 @@ func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transact } func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.Transaction, _ *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.SponsorshipWithProofs) if !ok { return nil, errors.New("failed to convert interface to SponsorshipWithProofs transaction") @@ -426,7 +426,7 @@ func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.T } func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.SetScriptWithProofs) if !ok { return nil, errors.New("failed to convert interface to SetScriptWithProofs transaction") @@ -476,7 +476,7 @@ func storeScriptByAddress( } func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction proto.Transaction, - info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + info *performerInfo, _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.SetAssetScriptWithProofs) if !ok { return nil, errors.New("failed to convert interface to SetAssetScriptWithProofs transaction") @@ -507,7 +507,7 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.InvokeScriptWithProofs) if !ok { return nil, errors.New("failed to convert interface to InvokeScriptWithProofs transaction") @@ -551,7 +551,7 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, - balanceChanges txDiff) (TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.InvokeExpressionTransactionWithProofs) if !ok { return nil, errors.New("failed to convert interface to InvokeExpressionWithProofs transaction") @@ -575,7 +575,7 @@ func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction pr } func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo, - invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + invocationRes *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { ethTx, ok := transaction.(*proto.EthereumTransaction) if !ok { return nil, errors.New("failed to convert interface to EthereumTransaction transaction") @@ -609,7 +609,7 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction } func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction proto.Transaction, - info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { + info *performerInfo, _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.UpdateAssetInfoWithProofs) if !ok { return nil, errors.New("failed to convert interface to UpdateAssetInfoWithProofs transaction") diff --git a/pkg/state/transaction_performer_test.go b/pkg/state/transaction_performer_test.go index 6205ef3ec..86aa33858 100644 --- a/pkg/state/transaction_performer_test.go +++ b/pkg/state/transaction_performer_test.go @@ -241,7 +241,7 @@ func TestPerformLeaseWithSig(t *testing.T) { to.stor.flush(t) leasingInfo := &leasing{ OriginTransactionID: tx.ID, - Status: LeaseActive, + Status: proto.LeaseActive, Amount: tx.Amount, Recipient: *tx.Recipient.Address(), Sender: testGlobal.senderInfo.addr, @@ -263,7 +263,7 @@ func TestPerformLeaseWithProofs(t *testing.T) { to.stor.flush(t) leasingInfo := &leasing{ OriginTransactionID: tx.ID, - Status: LeaseActive, + Status: proto.LeaseActive, Amount: tx.Amount, Recipient: *tx.Recipient.Address(), Sender: testGlobal.senderInfo.addr, @@ -286,7 +286,7 @@ func TestPerformLeaseCancelWithSig(t *testing.T) { tx := createLeaseCancelWithSig(t, *leaseTx.ID) leasingInfo := &leasing{ OriginTransactionID: leaseTx.ID, - Status: LeaseCanceled, + Status: proto.LeaseCanceled, Amount: leaseTx.Amount, Recipient: *leaseTx.Recipient.Address(), Sender: testGlobal.senderInfo.addr, @@ -312,7 +312,7 @@ func TestPerformLeaseCancelWithProofs(t *testing.T) { tx := createLeaseCancelWithProofs(t, *leaseTx.ID) leasingInfo := &leasing{ OriginTransactionID: leaseTx.ID, - Status: LeaseCanceled, + Status: proto.LeaseCanceled, Amount: leaseTx.Amount, Recipient: *leaseTx.Recipient.Address(), Sender: testGlobal.senderInfo.addr, From 22a02ac877531f7386e3a0c50ab9e78aa75bc60d Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Mon, 9 Oct 2023 11:39:28 +0300 Subject: [PATCH 072/139] fix linter issues --- pkg/state/appender.go | 7 ++++++- pkg/state/snapshot_storage_test.go | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 0cd843bb2..75c65ab48 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -523,7 +523,10 @@ func (a *txAppender) handleTxAndScripts( return applicationRes, invocationRes, needToValidateBalanceDiff, nil case proto.EthereumMetamaskTransaction: return a.handleEthTx(tx, params, accountHasVerifierScript, senderAddr) - default: + case proto.GenesisTransaction, proto.PaymentTransaction, proto.IssueTransaction, proto.TransferTransaction, + proto.ReissueTransaction, proto.BurnTransaction, proto.LeaseTransaction, proto.LeaseCancelTransaction, + proto.CreateAliasTransaction, proto.MassTransferTransaction, proto.DataTransaction, proto.SetScriptTransaction, + proto.SponsorshipTransaction, proto.SetAssetScriptTransaction, proto.UpdateAssetInfoTransaction: applicationRes, err := a.handleDefaultTransaction(tx, params, accountHasVerifierScript) if err != nil { id, idErr := tx.GetID(a.settings.AddressSchemeCharacter) @@ -534,6 +537,8 @@ func (a *txAppender) handleTxAndScripts( } // In UTX balances are always validated. return applicationRes, nil, params.validatingUtx, nil + default: + return nil, nil, false, errors.Errorf("Undefined transaction type %d", tx.GetTypeInfo()) } } diff --git a/pkg/state/snapshot_storage_test.go b/pkg/state/snapshot_storage_test.go index d2f13f00f..f6d14bc24 100644 --- a/pkg/state/snapshot_storage_test.go +++ b/pkg/state/snapshot_storage_test.go @@ -1,4 +1,4 @@ -package state +package state //nolint:testpackage //TODO: check this import ( "testing" From d41ea11e2bd7c984c6187c69b993255407ad3c45 Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 9 Oct 2023 18:42:41 -0500 Subject: [PATCH 073/139] Fixed a bug with wrong action sender --- pkg/state/snapshot_generator.go | 32 ++++++++++++++---------------- pkg/state/transaction_performer.go | 19 +++++++++++++++--- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index 8f671b3b1..e230b616a 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -370,20 +370,20 @@ func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto. func (sg *snapshotGenerator) generateSnapshotForInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff, - txPublicKey crypto.PublicKey) (proto.TransactionSnapshot, error) { - return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges, txPublicKey) + scriptPK crypto.PublicKey, scriptAddress proto.WavesAddress) (proto.TransactionSnapshot, error) { + return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges, scriptPK, scriptAddress) } func (sg *snapshotGenerator) generateSnapshotForInvokeExpressionTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff, - txPublicKey crypto.PublicKey) (proto.TransactionSnapshot, error) { - return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges, txPublicKey) + scriptPK crypto.PublicKey, scriptAddress proto.WavesAddress) (proto.TransactionSnapshot, error) { + return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges, scriptPK, scriptAddress) } func (sg *snapshotGenerator) generateSnapshotForEthereumInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff, - txPublicKey crypto.PublicKey) (proto.TransactionSnapshot, error) { - return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges, txPublicKey) + scriptPK crypto.PublicKey, scriptAddress proto.WavesAddress) (proto.TransactionSnapshot, error) { + return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges, scriptPK, scriptAddress) } func (sg *snapshotGenerator) generateSnapshotForUpdateAssetInfoTx(assetID crypto.Digest, assetName string, @@ -705,15 +705,13 @@ func (sg *snapshotGenerator) collectBalanceAndSnapshotFromAction( return atomicSnapshots, nil } -func senderFromScriptAction(a proto.ScriptAction, txPublicKey crypto.PublicKey, - scheme proto.Scheme) (proto.WavesAddress, crypto.PublicKey, error) { - senderPK := txPublicKey - senderAddress, err := proto.NewAddressFromPublicKey(scheme, senderPK) - if err != nil { - return proto.WavesAddress{}, crypto.PublicKey{}, err - } +func senderFromScriptAction(a proto.ScriptAction, + scheme proto.Scheme, scriptPK crypto.PublicKey, scriptAddress proto.WavesAddress) (proto.WavesAddress, crypto.PublicKey, error) { + senderPK := scriptPK + senderAddress := scriptAddress if a.SenderPK() != nil { senderPK = *a.SenderPK() + var err error senderAddress, err = proto.NewAddressFromPublicKey(scheme, senderPK) if err != nil { return proto.WavesAddress{}, crypto.PublicKey{}, err @@ -729,11 +727,11 @@ func (sg *snapshotGenerator) atomicSnapshotsFromScriptActions( blockHeight uint64, info *performerInfo, txID crypto.Digest, - txPublicKey crypto.PublicKey) ([]proto.AtomicSnapshot, error) { + scriptPublicKey crypto.PublicKey, scriptAddress proto.WavesAddress) ([]proto.AtomicSnapshot, error) { var dataEntries = make(SenderDataEntries) var atomicSnapshots []proto.AtomicSnapshot for _, action := range actions { - senderAddress, senderPK, err := senderFromScriptAction(action, txPublicKey, sg.scheme) + senderAddress, senderPK, err := senderFromScriptAction(action, sg.scheme, scriptPublicKey, scriptAddress) if err != nil { return nil, err } @@ -757,7 +755,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, - balanceChanges txDiff, txPublicKey crypto.PublicKey) (proto.TransactionSnapshot, error) { + balanceChanges txDiff, scriptPublicKey crypto.PublicKey, scriptAddress proto.WavesAddress) (proto.TransactionSnapshot, error) { blockHeight := info.height + 1 addrWavesBalanceDiff, addrAssetBalanceDiff, err := balanceDiffFromTxDiff(balanceChanges, sg.scheme) @@ -770,7 +768,7 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( atomicSnapshots, err = sg.atomicSnapshotsFromScriptActions( invocationRes.actions, addrWavesBalanceDiff, addrAssetBalanceDiff, blockHeight, info, txID, - txPublicKey) + scriptPublicKey, scriptAddress) if err != nil { return nil, errors.Wrap(err, "failed to generate atomic snapshots from script actions") } diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 430970be1..f6a021306 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -541,8 +541,17 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. return nil, err } + scriptAddr, err := recipientToAddress(tx.ScriptRecipient, tp.stor.aliases) + + var si scriptBasicInfoRecord + si, err = tp.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptAddr.ID()) + if err != nil { + return nil, errors.Wrapf(err, "failed to get script's public key on address '%s'", tx.ScriptRecipient.Address().String()) + } + scriptPK := si.PK + snapshot, err := tp.snapshotGenerator.generateSnapshotForInvokeScriptTx(txID, info, - invocationRes, balanceChanges, tx.SenderPK) + invocationRes, balanceChanges, scriptPK, scriptAddr) if err != nil { return nil, err } @@ -566,8 +575,12 @@ func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction pr return nil, err } + senderAddress, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) + if err != nil { + return nil, errors.Wrap(err, "recipientToAddress() failed") + } snapshot, err := tp.snapshotGenerator.generateSnapshotForInvokeExpressionTx(txID, info, invocationRes, - balanceChanges, tx.SenderPK) + balanceChanges, tx.SenderPK, senderAddress) if err != nil { return nil, err } @@ -601,7 +614,7 @@ func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction } scriptPK := si.PK snapshot, err := tp.snapshotGenerator.generateSnapshotForEthereumInvokeScriptTx(txID, - info, invocationRes, balanceChanges, scriptPK) + info, invocationRes, balanceChanges, scriptPK, scriptAddr) if err != nil { return nil, err } From 0fb6d3fd1b5601d820b1d2f119044ab800abd5d1 Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 9 Oct 2023 19:08:00 -0500 Subject: [PATCH 074/139] Fixed a bug with wrong action sender --- pkg/state/snapshot_generator.go | 7 +++++-- pkg/state/transaction_performer.go | 10 +++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index e230b616a..180852e50 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -706,7 +706,8 @@ func (sg *snapshotGenerator) collectBalanceAndSnapshotFromAction( } func senderFromScriptAction(a proto.ScriptAction, - scheme proto.Scheme, scriptPK crypto.PublicKey, scriptAddress proto.WavesAddress) (proto.WavesAddress, crypto.PublicKey, error) { + scheme proto.Scheme, scriptPK crypto.PublicKey, + scriptAddress proto.WavesAddress) (proto.WavesAddress, crypto.PublicKey, error) { senderPK := scriptPK senderAddress := scriptAddress if a.SenderPK() != nil { @@ -755,7 +756,9 @@ func (sg *snapshotGenerator) generateInvokeSnapshot( txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, - balanceChanges txDiff, scriptPublicKey crypto.PublicKey, scriptAddress proto.WavesAddress) (proto.TransactionSnapshot, error) { + balanceChanges txDiff, + scriptPublicKey crypto.PublicKey, + scriptAddress proto.WavesAddress) (proto.TransactionSnapshot, error) { blockHeight := info.height + 1 addrWavesBalanceDiff, addrAssetBalanceDiff, err := balanceDiffFromTxDiff(balanceChanges, sg.scheme) diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index f6a021306..619b6ba52 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -541,12 +541,16 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. return nil, err } - scriptAddr, err := recipientToAddress(tx.ScriptRecipient, tp.stor.aliases) - + scriptAddr, cnvrtErr := recipientToAddress(tx.ScriptRecipient, tp.stor.aliases) + if cnvrtErr != nil { + return nil, err + } var si scriptBasicInfoRecord si, err = tp.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptAddr.ID()) if err != nil { - return nil, errors.Wrapf(err, "failed to get script's public key on address '%s'", tx.ScriptRecipient.Address().String()) + return nil, errors.Wrapf(err, + "failed to get script's public key on address '%s'", + tx.ScriptRecipient.Address().String()) } scriptPK := si.PK From 59f2e60d02f6b21816a5598e2f218454c19a7d52 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Tue, 17 Oct 2023 11:08:19 +0300 Subject: [PATCH 075/139] use vtproto --- pkg/proto/snapshot_types.go | 181 ++++++++++++------ pkg/state/appender.go | 2 + pkg/state/headers_validation_test.go | 17 -- pkg/state/snapshot_storage.go | 10 +- ...t.go => snapshot_storage_internal_test.go} | 2 +- 5 files changed, 134 insertions(+), 78 deletions(-) rename pkg/state/{snapshot_storage_test.go => snapshot_storage_internal_test.go} (94%) diff --git a/pkg/proto/snapshot_types.go b/pkg/proto/snapshot_types.go index 7516188fa..0b6f0aed6 100644 --- a/pkg/proto/snapshot_types.go +++ b/pkg/proto/snapshot_types.go @@ -23,12 +23,14 @@ func (ts TransactionSnapshot) Apply(a SnapshotApplier) error { return nil } -func (ts TransactionSnapshot) ToProtobuf() *g.TransactionStateSnapshot { +func (ts TransactionSnapshot) ToProtobuf() (*g.TransactionStateSnapshot, error) { var res g.TransactionStateSnapshot for _, atomicSnapshot := range ts { - atomicSnapshot.AppendToProtobuf(&res) + if err := atomicSnapshot.AppendToProtobuf(&res); err != nil { + return nil, errors.Wrap(err, "failed to marshall TransactionSnapshot to proto") + } } - return &res + return &res, nil } type AtomicSnapshot interface { @@ -36,7 +38,7 @@ type AtomicSnapshot interface { /* is temporarily used to mark snapshots generated by tx diff that shouldn't be applied, because balances diffs are applied later in the block. */ IsGeneratedByTxDiff() bool - AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) + AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) error } type WavesBalanceSnapshot struct { @@ -50,18 +52,23 @@ func (s WavesBalanceSnapshot) IsGeneratedByTxDiff() bool { func (s WavesBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyWavesBalance(s) } -func (s WavesBalanceSnapshot) ToProtobuf() *g.TransactionStateSnapshot_Balance { +func (s WavesBalanceSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_Balance, error) { return &g.TransactionStateSnapshot_Balance{ Address: s.Address.Body(), Amount: &g.Amount{ AssetId: nil, Amount: int64(s.Balance), }, - } + }, nil } -func (s WavesBalanceSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { - txSnapshots.Balances = append(txSnapshots.Balances, s.ToProtobuf()) +func (s WavesBalanceSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) error { + snapshotInProto, err := s.ToProtobuf() + if err != nil { + return err + } + txSnapshots.Balances = append(txSnapshots.Balances, snapshotInProto) + return nil } type AssetBalanceSnapshot struct { @@ -76,18 +83,23 @@ func (s AssetBalanceSnapshot) IsGeneratedByTxDiff() bool { func (s AssetBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetBalance(s) } -func (s AssetBalanceSnapshot) ToProtobuf() *g.TransactionStateSnapshot_Balance { +func (s AssetBalanceSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_Balance, error) { return &g.TransactionStateSnapshot_Balance{ Address: s.Address.Body(), Amount: &g.Amount{ AssetId: s.AssetID.Bytes(), Amount: int64(s.Balance), }, - } + }, nil } -func (s AssetBalanceSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { - txSnapshots.Balances = append(txSnapshots.Balances, s.ToProtobuf()) +func (s AssetBalanceSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) error { + snapshotInProto, err := s.ToProtobuf() + if err != nil { + return err + } + txSnapshots.Balances = append(txSnapshots.Balances, snapshotInProto) + return nil } type DataEntriesSnapshot struct { // AccountData in pb @@ -101,7 +113,7 @@ func (s DataEntriesSnapshot) IsGeneratedByTxDiff() bool { func (s DataEntriesSnapshot) Apply(a SnapshotApplier) error { return a.ApplyDataEntries(s) } -func (s DataEntriesSnapshot) ToProtobuf() *g.TransactionStateSnapshot_AccountData { +func (s DataEntriesSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_AccountData, error) { entries := make([]*g.DataTransactionData_DataEntry, 0, len(s.DataEntries)) for _, e := range s.DataEntries { entries = append(entries, e.ToProtobuf()) @@ -109,11 +121,16 @@ func (s DataEntriesSnapshot) ToProtobuf() *g.TransactionStateSnapshot_AccountDat return &g.TransactionStateSnapshot_AccountData{ Address: s.Address.Body(), Entries: entries, - } + }, nil } -func (s DataEntriesSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { - txSnapshots.AccountData = append(txSnapshots.AccountData, s.ToProtobuf()) +func (s DataEntriesSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) error { + snapshotInProto, err := s.ToProtobuf() + if err != nil { + return err + } + txSnapshots.AccountData = append(txSnapshots.AccountData, snapshotInProto) + return nil } type AccountScriptSnapshot struct { @@ -128,16 +145,21 @@ func (s AccountScriptSnapshot) IsGeneratedByTxDiff() bool { func (s AccountScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAccountScript(s) } -func (s AccountScriptSnapshot) ToProtobuf() *g.TransactionStateSnapshot_AccountScript { +func (s AccountScriptSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_AccountScript, error) { return &g.TransactionStateSnapshot_AccountScript{ SenderPublicKey: s.SenderPublicKey.Bytes(), Script: s.Script, VerifierComplexity: int64(s.VerifierComplexity), - } + }, nil } -func (s AccountScriptSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { - txSnapshots.AccountScripts = append(txSnapshots.AccountScripts, s.ToProtobuf()) +func (s AccountScriptSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) error { + snapshotInProto, err := s.ToProtobuf() + if err != nil { + return err + } + txSnapshots.AccountScripts = append(txSnapshots.AccountScripts, snapshotInProto) + return nil } type AssetScriptSnapshot struct { @@ -153,15 +175,20 @@ func (s AssetScriptSnapshot) IsGeneratedByTxDiff() bool { func (s AssetScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetScript(s) } -func (s AssetScriptSnapshot) ToProtobuf() *g.TransactionStateSnapshot_AssetScript { +func (s AssetScriptSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_AssetScript, error) { return &g.TransactionStateSnapshot_AssetScript{ AssetId: s.AssetID.Bytes(), Script: s.Script, - } + }, nil } -func (s AssetScriptSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { - txSnapshots.AssetScripts = append(txSnapshots.AssetScripts, s.ToProtobuf()) +func (s AssetScriptSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) error { + snapshotInProto, err := s.ToProtobuf() + if err != nil { + return err + } + txSnapshots.AssetScripts = append(txSnapshots.AssetScripts, snapshotInProto) + return nil } type LeaseBalanceSnapshot struct { @@ -176,16 +203,21 @@ func (s LeaseBalanceSnapshot) IsGeneratedByTxDiff() bool { func (s LeaseBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseBalance(s) } -func (s LeaseBalanceSnapshot) ToProtobuf() *g.TransactionStateSnapshot_LeaseBalance { +func (s LeaseBalanceSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_LeaseBalance, error) { return &g.TransactionStateSnapshot_LeaseBalance{ Address: s.Address.Body(), In: int64(s.LeaseIn), Out: int64(s.LeaseOut), - } + }, nil } -func (s LeaseBalanceSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { - txSnapshots.LeaseBalances = append(txSnapshots.LeaseBalances, s.ToProtobuf()) +func (s LeaseBalanceSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) error { + snapshotInProto, err := s.ToProtobuf() + if err != nil { + return err + } + txSnapshots.LeaseBalances = append(txSnapshots.LeaseBalances, snapshotInProto) + return nil } type LeaseStateStatus struct { @@ -210,7 +242,7 @@ func (s LeaseStateSnapshot) IsGeneratedByTxDiff() bool { func (s LeaseStateSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseState(s) } -func (s LeaseStateSnapshot) ToProtobuf() *g.TransactionStateSnapshot_LeaseState { +func (s LeaseStateSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_LeaseState, error) { res := &g.TransactionStateSnapshot_LeaseState{ LeaseId: s.LeaseID.Bytes(), Status: nil, @@ -228,12 +260,19 @@ func (s LeaseStateSnapshot) ToProtobuf() *g.TransactionStateSnapshot_LeaseState Height: int32(s.Status.CancelHeight), TransactionId: s.Status.CancelTransactionID.Bytes(), } + default: + return nil, errors.Errorf("Failed to serialize LeaseStateSnapshot to Proto: invalid Lease status") } - return res + return res, nil } -func (s LeaseStateSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { - txSnapshots.LeaseStates = append(txSnapshots.LeaseStates, s.ToProtobuf()) +func (s LeaseStateSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) error { + snapshotInProto, err := s.ToProtobuf() + if err != nil { + return err + } + txSnapshots.LeaseStates = append(txSnapshots.LeaseStates, snapshotInProto) + return nil } type SponsorshipSnapshot struct { @@ -247,15 +286,20 @@ func (s SponsorshipSnapshot) IsGeneratedByTxDiff() bool { func (s SponsorshipSnapshot) Apply(a SnapshotApplier) error { return a.ApplySponsorship(s) } -func (s SponsorshipSnapshot) ToProtobuf() *g.TransactionStateSnapshot_Sponsorship { +func (s SponsorshipSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_Sponsorship, error) { return &g.TransactionStateSnapshot_Sponsorship{ AssetId: s.AssetID.Bytes(), MinFee: int64(s.MinSponsoredFee), - } + }, nil } -func (s SponsorshipSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { - txSnapshots.Sponsorships = append(txSnapshots.Sponsorships, s.ToProtobuf()) +func (s SponsorshipSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) error { + snapshotInProto, err := s.ToProtobuf() + if err != nil { + return err + } + txSnapshots.Sponsorships = append(txSnapshots.Sponsorships, snapshotInProto) + return nil } type AliasSnapshot struct { @@ -269,15 +313,20 @@ func (s AliasSnapshot) IsGeneratedByTxDiff() bool { func (s AliasSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAlias(s) } -func (s AliasSnapshot) ToProtobuf() *g.TransactionStateSnapshot_Alias { +func (s AliasSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_Alias, error) { return &g.TransactionStateSnapshot_Alias{ Address: s.Address.Body(), Alias: s.Alias.Alias, - } + }, nil } -func (s AliasSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { - txSnapshots.Aliases = append(txSnapshots.Aliases, s.ToProtobuf()) +func (s AliasSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) error { + snapshotInProto, err := s.ToProtobuf() + if err != nil { + return err + } + txSnapshots.Aliases = append(txSnapshots.Aliases, snapshotInProto) + return nil } // FilledVolumeFeeSnapshot Filled Volume and Fee. @@ -293,16 +342,21 @@ func (s FilledVolumeFeeSnapshot) IsGeneratedByTxDiff() bool { func (s FilledVolumeFeeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyFilledVolumeAndFee(s) } -func (s FilledVolumeFeeSnapshot) ToProtobuf() *g.TransactionStateSnapshot_OrderFill { +func (s FilledVolumeFeeSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_OrderFill, error) { return &g.TransactionStateSnapshot_OrderFill{ OrderId: s.OrderID.Bytes(), Volume: int64(s.FilledVolume), Fee: int64(s.FilledFee), - } + }, nil } -func (s FilledVolumeFeeSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { - txSnapshots.OrderFills = append(txSnapshots.OrderFills, s.ToProtobuf()) +func (s FilledVolumeFeeSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) error { + snapshotInProto, err := s.ToProtobuf() + if err != nil { + return err + } + txSnapshots.OrderFills = append(txSnapshots.OrderFills, snapshotInProto) + return nil } type StaticAssetInfoSnapshot struct { @@ -319,18 +373,23 @@ func (s StaticAssetInfoSnapshot) IsGeneratedByTxDiff() bool { func (s StaticAssetInfoSnapshot) Apply(a SnapshotApplier) error { return a.ApplyStaticAssetInfo(s) } -func (s StaticAssetInfoSnapshot) ToProtobuf() *g.TransactionStateSnapshot_AssetStatic { +func (s StaticAssetInfoSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_AssetStatic, error) { return &g.TransactionStateSnapshot_AssetStatic{ AssetId: s.AssetID.Bytes(), SourceTransactionId: s.SourceTransactionID.Bytes(), IssuerPublicKey: s.IssuerPublicKey.Bytes(), Decimals: int32(s.Decimals), Nft: s.IsNFT, - } + }, nil } -func (s StaticAssetInfoSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { - txSnapshots.AssetStatics = append(txSnapshots.AssetStatics, s.ToProtobuf()) +func (s StaticAssetInfoSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) error { + snapshotInProto, err := s.ToProtobuf() + if err != nil { + return err + } + txSnapshots.AssetStatics = append(txSnapshots.AssetStatics, snapshotInProto) + return nil } type AssetVolumeSnapshot struct { // AssetVolume in pb @@ -345,16 +404,21 @@ func (s AssetVolumeSnapshot) IsGeneratedByTxDiff() bool { func (s AssetVolumeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetVolume(s) } -func (s AssetVolumeSnapshot) ToProtobuf() *g.TransactionStateSnapshot_AssetVolume { +func (s AssetVolumeSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_AssetVolume, error) { return &g.TransactionStateSnapshot_AssetVolume{ AssetId: s.AssetID.Bytes(), Reissuable: s.IsReissuable, Volume: s.TotalQuantity.Bytes(), - } + }, nil } -func (s AssetVolumeSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { - txSnapshots.AssetVolumes = append(txSnapshots.AssetVolumes, s.ToProtobuf()) +func (s AssetVolumeSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) error { + snapshotInProto, err := s.ToProtobuf() + if err != nil { + return err + } + txSnapshots.AssetVolumes = append(txSnapshots.AssetVolumes, snapshotInProto) + return nil } type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb @@ -370,17 +434,22 @@ func (s AssetDescriptionSnapshot) IsGeneratedByTxDiff() bool { func (s AssetDescriptionSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetDescription(s) } -func (s AssetDescriptionSnapshot) ToProtobuf() *g.TransactionStateSnapshot_AssetNameAndDescription { +func (s AssetDescriptionSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_AssetNameAndDescription, error) { return &g.TransactionStateSnapshot_AssetNameAndDescription{ AssetId: s.AssetID.Bytes(), Name: s.AssetName, Description: s.AssetDescription, LastUpdated: int32(s.ChangeHeight), - } + }, nil } -func (s AssetDescriptionSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) { - txSnapshots.AssetNamesAndDescriptions = append(txSnapshots.AssetNamesAndDescriptions, s.ToProtobuf()) +func (s AssetDescriptionSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) error { + snapshotInProto, err := s.ToProtobuf() + if err != nil { + return err + } + txSnapshots.AssetNamesAndDescriptions = append(txSnapshots.AssetNamesAndDescriptions, snapshotInProto) + return nil } type SnapshotApplier interface { diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 75c65ab48..35daa05ee 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -493,6 +493,8 @@ func (a *txAppender) handleEthTx( "failed to handle ethereum invoke script transaction (type %s) with id %s, on height %d", ethTx.TxKind.String(), ethTx.ID.String(), params.checkerInfo.height+1) } + default: + return nil, nil, false, errors.Errorf("Undefined ethereum transaction kind %T", ethTx.TxKind) } return applicationRes, invocationRes, needToValidateBalanceDiff, nil } diff --git a/pkg/state/headers_validation_test.go b/pkg/state/headers_validation_test.go index 9aa5421a3..75c343e14 100644 --- a/pkg/state/headers_validation_test.go +++ b/pkg/state/headers_validation_test.go @@ -141,20 +141,3 @@ func TestHeadersValidation(t *testing.T) { err = st.RollbackToHeight(1) assert.NoError(t, err, "failed to rollback state") } - -func TestSnapshots(t *testing.T) { - blocks, err := readBlocksFromTestPath(blocksNumber) - if err != nil { - t.Fatalf("Can not read blocks from blockchain file: %v\n", err) - } - var ( - sets = settings.MainNetSettings - scheme = sets.AddressSchemeCharacter - st = newTestState(t, true, stateParams(), sets) - ) - - err = applyBlocks(t, blocks, st, scheme) - assert.NoError(t, err, "failed to apply correct blocks") - err = st.RollbackToHeight(1) - assert.NoError(t, err, "failed to rollback state") -} diff --git a/pkg/state/snapshot_storage.go b/pkg/state/snapshot_storage.go index cbdc1aa54..b0a8abfef 100644 --- a/pkg/state/snapshot_storage.go +++ b/pkg/state/snapshot_storage.go @@ -1,8 +1,6 @@ package state import ( - protobuf "google.golang.org/protobuf/proto" - g "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" "github.com/wavesplatform/gowaves/pkg/proto" ) @@ -21,7 +19,11 @@ func (s *snapshotsAtHeight) saveSnapshots( txSnapshots proto.TransactionSnapshot, ) error { key := snapshotsKey{height: blockHeight} - recordBytes, err := protobuf.Marshal(txSnapshots.ToProtobuf()) + txSnapshotsProto, err := txSnapshots.ToProtobuf() + if err != nil { + return err + } + recordBytes, err := txSnapshotsProto.MarshalVTStrict() if err != nil { return err } @@ -35,7 +37,7 @@ func (s *snapshotsAtHeight) shapshots(height uint64) (*g.TransactionStateSnapsho return nil, err } var res g.TransactionStateSnapshot - if err = protobuf.Unmarshal(snapshotsBytes, &res); err != nil { + if err = res.UnmarshalVT(snapshotsBytes); err != nil { return nil, err } return &res, nil diff --git a/pkg/state/snapshot_storage_test.go b/pkg/state/snapshot_storage_internal_test.go similarity index 94% rename from pkg/state/snapshot_storage_test.go rename to pkg/state/snapshot_storage_internal_test.go index f6d14bc24..d2f13f00f 100644 --- a/pkg/state/snapshot_storage_test.go +++ b/pkg/state/snapshot_storage_internal_test.go @@ -1,4 +1,4 @@ -package state //nolint:testpackage //TODO: check this +package state import ( "testing" From 1f75b9fad6ee7fc512d2b9ac4e3d2fc7430ca024 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Tue, 24 Oct 2023 06:59:11 +0300 Subject: [PATCH 076/139] Add 'TransactionStatusSnapshot'. --- pkg/proto/snapshot_types.go | 6 ++++++ pkg/proto/types.go | 8 ++++++++ pkg/state/appender.go | 1 + pkg/state/snapshot_applier.go | 5 +++++ 4 files changed, 20 insertions(+) diff --git a/pkg/proto/snapshot_types.go b/pkg/proto/snapshot_types.go index cfcccd9c0..4a92ce7a1 100644 --- a/pkg/proto/snapshot_types.go +++ b/pkg/proto/snapshot_types.go @@ -196,6 +196,11 @@ func (s AssetDescriptionSnapshot) IsGeneratedByTxDiff() bool { func (s AssetDescriptionSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetDescription(s) } +type TransactionStatusSnapshot struct { + TransactionID crypto.Digest + Status TransactionStatus +} + type SnapshotApplier interface { ApplyWavesBalance(snapshot WavesBalanceSnapshot) error ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) error @@ -210,4 +215,5 @@ type SnapshotApplier interface { ApplyFilledVolumeAndFee(snapshot FilledVolumeFeeSnapshot) error ApplyDataEntries(snapshot DataEntriesSnapshot) error ApplyLeaseState(snapshot LeaseStateSnapshot) error + ApplyTransactionsStatus(snapshot TransactionStatusSnapshot) error } diff --git a/pkg/proto/types.go b/pkg/proto/types.go index 016d1bba8..ff1569e63 100644 --- a/pkg/proto/types.go +++ b/pkg/proto/types.go @@ -4303,3 +4303,11 @@ const ( LeaseCanceled //TODO: LeaseExpired (for future use) ) + +type TransactionStatus byte + +const ( + TransactionSucceeded TransactionStatus = iota + TransactionFailed + TransactionElided +) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 3afbb964d..5a44b8ee2 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -374,6 +374,7 @@ func (a *txAppender) commitTxApplication( return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to write transaction to storage: %v", err)) } } + // TODO: transaction status snapshot has to be appended here return snapshot, nil } diff --git a/pkg/state/snapshot_applier.go b/pkg/state/snapshot_applier.go index 02d9726b3..88e599b51 100644 --- a/pkg/state/snapshot_applier.go +++ b/pkg/state/snapshot_applier.go @@ -2,6 +2,7 @@ package state import ( "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/proto" ) @@ -236,3 +237,7 @@ func (a *blockSnapshotsApplier) ApplyLeaseState(snapshot proto.LeaseStateSnapsho } return a.stor.leases.addLeasing(snapshot.LeaseID, l, a.info.BlockID()) } + +func (a *blockSnapshotsApplier) ApplyTransactionsStatus(_ proto.TransactionStatusSnapshot) error { + return nil // no-op +} From 2ae62291473053c2a8309c89a6ec309caa79cd6e Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Tue, 24 Oct 2023 22:09:54 +0300 Subject: [PATCH 077/139] Implemented 'AtomicSnapshot' interface for 'TransactionStatusSnapshot'. --- pkg/proto/snapshot_types.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/proto/snapshot_types.go b/pkg/proto/snapshot_types.go index 4a92ce7a1..eafef7286 100644 --- a/pkg/proto/snapshot_types.go +++ b/pkg/proto/snapshot_types.go @@ -201,6 +201,14 @@ type TransactionStatusSnapshot struct { Status TransactionStatus } +func (s TransactionStatusSnapshot) Apply(a SnapshotApplier) error { + return a.ApplyTransactionsStatus(s) +} + +func (s TransactionStatusSnapshot) IsGeneratedByTxDiff() bool { + return false +} + type SnapshotApplier interface { ApplyWavesBalance(snapshot WavesBalanceSnapshot) error ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) error From 94aa8c2190c8d3998ef6a3af97b19428065b84df Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Wed, 25 Oct 2023 17:50:44 +0300 Subject: [PATCH 078/139] Changed 'AssetScriptSnapshot' and 'scriptStorageState.setAssetScript'. Removed 'pk' arg from 'setAssetScript'. Removed two fields from 'AssetScriptSnapshot': - 'SenderPK' - 'Complexity' --- pkg/proto/snapshot_types.go | 6 +- pkg/state/common_test.go | 2 +- pkg/state/scripts_storage.go | 56 +++++++++++++++---- pkg/state/scripts_storage_interface.go | 2 +- pkg/state/scripts_storage_moq_test.go | 14 ++--- pkg/state/scripts_storage_test.go | 5 +- pkg/state/snapshot_applier.go | 2 +- pkg/state/snapshot_generator.go | 21 ++++--- pkg/state/snapshot_generator_internal_test.go | 9 ++- pkg/state/transaction_checker_test.go | 2 +- pkg/state/transaction_performer.go | 12 ++-- pkg/state/transaction_performer_test.go | 3 +- 12 files changed, 79 insertions(+), 55 deletions(-) diff --git a/pkg/proto/snapshot_types.go b/pkg/proto/snapshot_types.go index eafef7286..c8963e2a9 100644 --- a/pkg/proto/snapshot_types.go +++ b/pkg/proto/snapshot_types.go @@ -76,10 +76,8 @@ func (s AccountScriptSnapshot) IsGeneratedByTxDiff() bool { func (s AccountScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAccountScript(s) } type AssetScriptSnapshot struct { - AssetID crypto.Digest - Script Script - SenderPK crypto.PublicKey // should be removed later - Complexity uint64 + AssetID crypto.Digest + Script Script } func (s AssetScriptSnapshot) IsGeneratedByTxDiff() bool { diff --git a/pkg/state/common_test.go b/pkg/state/common_test.go index f40cc16c1..7494ed75a 100644 --- a/pkg/state/common_test.go +++ b/pkg/state/common_test.go @@ -490,7 +490,7 @@ func (s *testStorageObjects) createAsset(t *testing.T, assetID crypto.Digest) *a func (s *testStorageObjects) createSmartAsset(t *testing.T, assetID crypto.Digest) { s.addBlock(t, blockID0) - err := s.entities.scriptsStorage.setAssetScript(assetID, testGlobal.scriptBytes, testGlobal.senderInfo.pk, blockID0) + err := s.entities.scriptsStorage.setAssetScript(assetID, testGlobal.scriptBytes, blockID0) assert.NoError(t, err, "setAssetScript failed") s.flush(t) } diff --git a/pkg/state/scripts_storage.go b/pkg/state/scripts_storage.go index 00af3f05d..3298721cc 100644 --- a/pkg/state/scripts_storage.go +++ b/pkg/state/scripts_storage.go @@ -6,6 +6,7 @@ import ( "github.com/fxamacker/cbor/v2" "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/ride/ast" @@ -74,7 +75,7 @@ func (as *assetScripRecordForHashes) less(other stateComponent) bool { } type scriptBasicInfoRecord struct { - PK crypto.PublicKey `cbor:"0,keyasint,omitemtpy"` + PK crypto.PublicKey `cbor:"0,keyasint,omitemtpy"` // not empty only for account script ScriptLen uint32 `cbor:"1,keyasint,omitemtpy"` LibraryVersion ast.LibraryVersion `cbor:"2,keyasint,omitemtpy"` HasVerifier bool `cbor:"3,keyasint,omitemtpy"` @@ -112,16 +113,49 @@ func (r *scriptBasicInfoRecord) unmarshalBinary(data []byte) error { return cbor.Unmarshal(data, r) } +func newAccountScriptBasicInfoRecord( + pk crypto.PublicKey, + script proto.Script, +) (scriptBasicInfoRecord, *ast.Tree, error) { + info, tree, err := newScriptBasicInfoRecord(pk, script) + if err != nil { + return scriptBasicInfoRecord{}, nil, errors.Wrap(err, "failed to create new account script basic info record") + } + return info, tree, nil +} + +func newAssetScriptBasicInfoRecord(script proto.Script) (scriptBasicInfoRecord, *ast.Tree, error) { + var emptyPKStub crypto.PublicKey + info, tree, err := newScriptBasicInfoRecord(emptyPKStub, script) + if err != nil { + return scriptBasicInfoRecord{}, nil, errors.Wrap(err, "failed to create new asset script basic info record") + } + return info, tree, nil +} + type scriptDBItem struct { script proto.Script tree *ast.Tree info scriptBasicInfoRecord } -func newScriptDBItem(pk crypto.PublicKey, script proto.Script) (scriptDBItem, error) { - info, tree, err := newScriptBasicInfoRecord(pk, script) +func newAccountScriptDBItem(pk crypto.PublicKey, script proto.Script) (scriptDBItem, error) { + info, tree, err := newAccountScriptBasicInfoRecord(pk, script) + if err != nil { + return scriptDBItem{}, errors.Wrap(err, "failed to create new account script basic info record") + } + dbItem := scriptDBItem{ + script: script, + tree: tree, + info: info, + } + return dbItem, nil +} + +func newAssetScriptDBIterm(script proto.Script) (scriptDBItem, error) { + info, tree, err := newAssetScriptBasicInfoRecord(script) if err != nil { - return scriptDBItem{}, errors.Wrap(err, "failed to create new script basic info record") + return scriptDBItem{}, errors.Wrap(err, "failed to create new asset script basic info record") } dbItem := scriptDBItem{ script: script, @@ -233,7 +267,7 @@ func (ss *scriptsStorage) scriptTreeByKey(key []byte) (*ast.Tree, error) { func (ss *scriptsStorage) commitUncertain(blockID proto.BlockID) error { for assetID, r := range ss.uncertainAssetScripts { digest := proto.ReconstructDigest(assetID, r.assetIDTail) - if err := ss.setAssetScript(digest, r.scriptDBItem.script, r.scriptDBItem.info.PK, blockID); err != nil { + if err := ss.setAssetScript(digest, r.scriptDBItem.script, blockID); err != nil { return err } } @@ -250,7 +284,7 @@ func (ss *scriptsStorage) setAssetScriptUncertain(fullAssetID crypto.Digest, scr assetID = proto.AssetIDFromDigest(fullAssetID) assetIDTail = proto.DigestTail(fullAssetID) ) - dbItem, err := newScriptDBItem(pk, script) + dbItem, err := newAccountScriptDBItem(pk, script) if err != nil { return errors.Wrapf(err, "failed to set uncertain asset script for asset %q with pk %q", fullAssetID.String(), pk.String(), @@ -263,7 +297,7 @@ func (ss *scriptsStorage) setAssetScriptUncertain(fullAssetID crypto.Digest, scr return nil } -func (ss *scriptsStorage) setAssetScript(fullAssetID crypto.Digest, script proto.Script, pk crypto.PublicKey, blockID proto.BlockID) error { +func (ss *scriptsStorage) setAssetScript(fullAssetID crypto.Digest, script proto.Script, blockID proto.BlockID) error { // NOTE: we use fullAssetID (crypto.Digest) only for state hashes compatibility key := assetScriptKey{assetID: proto.AssetIDFromDigest(fullAssetID)} if ss.calculateHashes { @@ -276,10 +310,10 @@ func (ss *scriptsStorage) setAssetScript(fullAssetID crypto.Digest, script proto return err } } - dbItem, err := newScriptDBItem(pk, script) + dbItem, err := newAssetScriptDBIterm(script) if err != nil { - return errors.Wrapf(err, "failed to set asset script for asset %q with pk %q on block %q", - fullAssetID.String(), pk.String(), blockID.String(), + return errors.Wrapf(err, "failed to set asset script for asset %q with on block %q", + fullAssetID.String(), blockID.String(), ) } return ss.setScript(assetScript, &key, dbItem, blockID) @@ -367,7 +401,7 @@ func (ss *scriptsStorage) setAccountScript(addr proto.WavesAddress, script proto return err } } - dbItem, err := newScriptDBItem(pk, script) + dbItem, err := newAccountScriptDBItem(pk, script) if err != nil { return errors.Wrapf(err, "failed to set account script for account %q with pk %q on block %q", addr.String(), pk.String(), blockID.String(), diff --git a/pkg/state/scripts_storage_interface.go b/pkg/state/scripts_storage_interface.go index 5817a0e8a..1dc04d242 100644 --- a/pkg/state/scripts_storage_interface.go +++ b/pkg/state/scripts_storage_interface.go @@ -11,7 +11,7 @@ type scriptStorageState interface { commitUncertain(blockID proto.BlockID) error dropUncertain() setAssetScriptUncertain(fullAssetID crypto.Digest, script proto.Script, pk crypto.PublicKey) error - setAssetScript(assetID crypto.Digest, script proto.Script, pk crypto.PublicKey, blockID proto.BlockID) error + setAssetScript(assetID crypto.Digest, script proto.Script, blockID proto.BlockID) error newestIsSmartAsset(assetID proto.AssetID) (bool, error) isSmartAsset(assetID proto.AssetID) (bool, error) newestScriptByAsset(assetID proto.AssetID) (*ast.Tree, error) diff --git a/pkg/state/scripts_storage_moq_test.go b/pkg/state/scripts_storage_moq_test.go index 08a4d4084..1949daff9 100644 --- a/pkg/state/scripts_storage_moq_test.go +++ b/pkg/state/scripts_storage_moq_test.go @@ -98,7 +98,7 @@ var _ scriptStorageState = &mockScriptStorageState{} // setAccountScriptFunc: func(addr proto.WavesAddress, script proto.Script, pk crypto.PublicKey, blockID proto.BlockID) error { // panic("mock out the setAccountScript method") // }, -// setAssetScriptFunc: func(assetID crypto.Digest, script proto.Script, pk crypto.PublicKey, blockID proto.BlockID) error { +// setAssetScriptFunc: func(assetID crypto.Digest, script proto.Script, blockID proto.BlockID) error { // panic("mock out the setAssetScript method") // }, // setAssetScriptUncertainFunc: func(fullAssetID crypto.Digest, script proto.Script, pk crypto.PublicKey) error { @@ -190,7 +190,7 @@ type mockScriptStorageState struct { setAccountScriptFunc func(addr proto.WavesAddress, script proto.Script, pk crypto.PublicKey, blockID proto.BlockID) error // setAssetScriptFunc mocks the setAssetScript method. - setAssetScriptFunc func(assetID crypto.Digest, script proto.Script, pk crypto.PublicKey, blockID proto.BlockID) error + setAssetScriptFunc func(assetID crypto.Digest, script proto.Script, blockID proto.BlockID) error // setAssetScriptUncertainFunc mocks the setAssetScriptUncertain method. setAssetScriptUncertainFunc func(fullAssetID crypto.Digest, script proto.Script, pk crypto.PublicKey) error @@ -327,8 +327,6 @@ type mockScriptStorageState struct { AssetID crypto.Digest // Script is the script argument value. Script proto.Script - // Pk is the pk argument value. - Pk crypto.PublicKey // BlockID is the blockID argument value. BlockID proto.BlockID } @@ -1187,25 +1185,23 @@ func (mock *mockScriptStorageState) setAccountScriptCalls() []struct { } // setAssetScript calls setAssetScriptFunc. -func (mock *mockScriptStorageState) setAssetScript(assetID crypto.Digest, script proto.Script, pk crypto.PublicKey, blockID proto.BlockID) error { +func (mock *mockScriptStorageState) setAssetScript(assetID crypto.Digest, script proto.Script, blockID proto.BlockID) error { if mock.setAssetScriptFunc == nil { panic("mockScriptStorageState.setAssetScriptFunc: method is nil but scriptStorageState.setAssetScript was just called") } callInfo := struct { AssetID crypto.Digest Script proto.Script - Pk crypto.PublicKey BlockID proto.BlockID }{ AssetID: assetID, Script: script, - Pk: pk, BlockID: blockID, } mock.locksetAssetScript.Lock() mock.calls.setAssetScript = append(mock.calls.setAssetScript, callInfo) mock.locksetAssetScript.Unlock() - return mock.setAssetScriptFunc(assetID, script, pk, blockID) + return mock.setAssetScriptFunc(assetID, script, blockID) } // setAssetScriptCalls gets all the calls that were made to setAssetScript. @@ -1215,13 +1211,11 @@ func (mock *mockScriptStorageState) setAssetScript(assetID crypto.Digest, script func (mock *mockScriptStorageState) setAssetScriptCalls() []struct { AssetID crypto.Digest Script proto.Script - Pk crypto.PublicKey BlockID proto.BlockID } { var calls []struct { AssetID crypto.Digest Script proto.Script - Pk crypto.PublicKey BlockID proto.BlockID } mock.locksetAssetScript.RLock() diff --git a/pkg/state/scripts_storage_test.go b/pkg/state/scripts_storage_test.go index bbf157db5..23be0f013 100644 --- a/pkg/state/scripts_storage_test.go +++ b/pkg/state/scripts_storage_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/wavesplatform/gowaves/pkg/proto" ) @@ -129,7 +130,7 @@ func TestSetAssetScript(t *testing.T) { fullAssetID := testGlobal.asset0.asset.ID shortAssetID := proto.AssetIDFromDigest(fullAssetID) - err := to.scriptsStorage.setAssetScript(fullAssetID, testGlobal.scriptBytes, testGlobal.senderInfo.pk, blockID0) + err := to.scriptsStorage.setAssetScript(fullAssetID, testGlobal.scriptBytes, blockID0) assert.NoError(t, err, "setAssetScript() failed") // Test newest before flushing. @@ -166,7 +167,7 @@ func TestSetAssetScript(t *testing.T) { assert.Equal(t, testGlobal.scriptAst, scriptAst) // Test discarding script. - err = to.scriptsStorage.setAssetScript(fullAssetID, proto.Script{}, testGlobal.senderInfo.pk, blockID0) + err = to.scriptsStorage.setAssetScript(fullAssetID, proto.Script{}, blockID0) assert.NoError(t, err, "setAssetScript() failed") // Test newest before flushing. diff --git a/pkg/state/snapshot_applier.go b/pkg/state/snapshot_applier.go index 88e599b51..e2693461e 100644 --- a/pkg/state/snapshot_applier.go +++ b/pkg/state/snapshot_applier.go @@ -178,7 +178,7 @@ func (a *blockSnapshotsApplier) ApplyAssetScript(snapshot proto.AssetScriptSnaps // if err != nil { // return errors.Wrapf(err, "failed to get const asset info for asset %q", snapshot.AssetID.String()) // } - return a.stor.scriptsStorage.setAssetScript(snapshot.AssetID, snapshot.Script, snapshot.SenderPK, a.info.BlockID()) + return a.stor.scriptsStorage.setAssetScript(snapshot.AssetID, snapshot.Script, a.info.BlockID()) } func (a *blockSnapshotsApplier) ApplySponsorship(snapshot proto.SponsorshipSnapshot) error { diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index 180852e50..0a5183d40 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -4,6 +4,7 @@ import ( "math/big" "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" ) @@ -147,10 +148,10 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t if scriptInformation != nil { assetScriptSnapshot := &proto.AssetScriptSnapshot{ - AssetID: assetID, - Script: scriptInformation.script, - Complexity: uint64(scriptInformation.complexity), + AssetID: assetID, + Script: scriptInformation.script, } + // TODO: special snapshot for complexity should be generated here snapshot = append(snapshot, assetScriptSnapshot) } @@ -352,17 +353,15 @@ func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.Publ } func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, - complexity int, senderPK crypto.PublicKey, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } sponsorshipSnapshot := &proto.AssetScriptSnapshot{ - AssetID: assetID, - Script: script, - Complexity: uint64(complexity), - SenderPK: senderPK, + AssetID: assetID, + Script: script, } snapshot = append(snapshot, sponsorshipSnapshot) return snapshot, nil @@ -514,10 +513,10 @@ func (sg *snapshotGenerator) atomicSnapshotsFromIssueAction( } if scriptInfo != nil { assetScriptSnapshot := &proto.AssetScriptSnapshot{ - AssetID: action.ID, - Script: scriptInfo.script, - Complexity: uint64(scriptInfo.complexity), + AssetID: action.ID, + Script: scriptInfo.script, } + // TODO: special snapshot for complexity should be generated here atomicSnapshots = append(atomicSnapshots, assetScriptSnapshot) } atomicSnapshots = append(atomicSnapshots, issueStaticInfoSnapshot, assetDescription, assetReissuability) diff --git a/pkg/state/snapshot_generator_internal_test.go b/pkg/state/snapshot_generator_internal_test.go index 63fecff77..6873f8011 100644 --- a/pkg/state/snapshot_generator_internal_test.go +++ b/pkg/state/snapshot_generator_internal_test.go @@ -9,6 +9,7 @@ import ( "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" @@ -894,7 +895,7 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.T) { assert.NoError(t, err, "failed to issue asset") err = to.stor.entities.scriptsStorage.setAssetScript(testGlobal.asset0.assetID, - testGlobal.scriptBytes, testGlobal.senderInfo.pk, blockID0) + testGlobal.scriptBytes, blockID0) assert.NoError(t, err, "failed to issue asset") tx := proto.NewUnsignedSetAssetScriptWithProofs(1, testGlobal.senderInfo.pk, @@ -925,10 +926,8 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.T) { Balance: 299900000, }, &proto.AssetScriptSnapshot{ - AssetID: testGlobal.asset0.assetID, - Script: testGlobal.scriptBytes, - Complexity: 340, - SenderPK: tx.SenderPK, + AssetID: testGlobal.asset0.assetID, + Script: testGlobal.scriptBytes, }, } diff --git a/pkg/state/transaction_checker_test.go b/pkg/state/transaction_checker_test.go index 9f7191d90..075f484ed 100644 --- a/pkg/state/transaction_checker_test.go +++ b/pkg/state/transaction_checker_test.go @@ -1395,7 +1395,7 @@ func TestCheckSetAssetScriptWithProofs(t *testing.T) { assert.Error(t, err, "checkSetAssetScriptWithProofs did not fail with non-smart asset") // Make it smart. - err = to.stor.entities.scriptsStorage.setAssetScript(tx.AssetID, tx.Script, tx.SenderPK, blockID0) + err = to.stor.entities.scriptsStorage.setAssetScript(tx.AssetID, tx.Script, blockID0) assert.NoError(t, err, "setAssetScript failed") // Now should pass. diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 619b6ba52..d97aac546 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -135,8 +135,8 @@ func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transactio if err != nil { return nil, err } - if err := tp.stor.scriptsStorage.setAssetScript(assetID, proto.Script{}, tx.SenderPK, info.blockID); err != nil { - return nil, err + if setErr := tp.stor.scriptsStorage.setAssetScript(assetID, proto.Script{}, info.blockID); setErr != nil { + return nil, setErr } return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges, nil) } @@ -155,8 +155,8 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac if err != nil { return nil, err } - if err := tp.stor.scriptsStorage.setAssetScript(assetID, tx.Script, tx.SenderPK, info.blockID); err != nil { - return nil, err + if setErr := tp.stor.scriptsStorage.setAssetScript(assetID, tx.Script, info.blockID); setErr != nil { + return nil, setErr } var se *scriptEstimation var scriptInfo *scriptInformation @@ -495,11 +495,11 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot if setErr := tp.stor.scriptsComplexity.saveComplexitiesForAddr(senderAddr, *se, info.blockID); setErr != nil { return nil, errors.Wrapf(setErr, "failed to save script complexities for addr %q", senderAddr.String()) } - snapshot, err := tp.snapshotGenerator.generateSnapshotForSetAssetScriptTx(tx.AssetID, - tx.Script, se.estimation.Verifier, tx.SenderPK, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForSetAssetScriptTx(tx.AssetID, tx.Script, balanceChanges) if err != nil { return nil, err } + // TODO: generate special complexities snapshot for asset return snapshot, snapshot.Apply(tp.snapshotApplier) } diff --git a/pkg/state/transaction_performer_test.go b/pkg/state/transaction_performer_test.go index 86aa33858..c2c9711c6 100644 --- a/pkg/state/transaction_performer_test.go +++ b/pkg/state/transaction_performer_test.go @@ -8,7 +8,6 @@ import ( "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" @@ -588,7 +587,7 @@ func TestPerformSetAssetScriptWithProofs(t *testing.T) { assert.Equal(t, testGlobal.scriptAst, scriptAst) // Test discarding script. - err = to.stor.entities.scriptsStorage.setAssetScript(fullAssetID, proto.Script{}, crypto.PublicKey{}, blockID0) + err = to.stor.entities.scriptsStorage.setAssetScript(fullAssetID, proto.Script{}, blockID0) assert.NoError(t, err, "setAssetScript() failed") // Test newest before flushing. From 982fe0a0517ab3ae39964ae495987d4386b319ae Mon Sep 17 00:00:00 2001 From: Aleksandr Dolgavin Date: Sun, 29 Oct 2023 14:35:11 -0700 Subject: [PATCH 079/139] * Commented invoke snapshots, import ok (#1165) * Replaced current recording to storage to snapshot applier * Replaced to snapshot applier, except balances * Fixed a comment * Removed the comment * Removed unnecessary code * Returned the linter command back * Added asset script atomic snapshot to the issue script actions * Fixed some linter issues * Fixed a few more linter issues * Fixed all linter issues * Fixed err shadowing * Fixed a mistake with issue counter * removed a useless line * Fixed applying order transactions * Fixed applying order transactions * Added lising snapshot to the tx diff generated group * Moved complexity saving into transaction performer * Moved complexity saving into transaction performer * removed a line * Fixed a bug with an empty sender * Used error.Is * Set an empty script for issue with sig * move snapshots types to proto * Fixed a bug with wrong action sender * Fixed a bug with wrong action sender * Add 'TransactionStatusSnapshot'. * Implemented 'AtomicSnapshot' interface for 'TransactionStatusSnapshot'. * Changed 'AssetScriptSnapshot' and 'scriptStorageState.setAssetScript'. Removed 'pk' arg from 'setAssetScript'. Removed two fields from 'AssetScriptSnapshot': - 'SenderPK' - 'Complexity' * * Commented invoke snapshots, import ok * moved setting complexity and set script to snapshot applier * Fixed a test and a mistake * Fixed renaming * Fixed a comment * Moved dapp complexity to applier * Added dapp complexity to set script as well * Fixed a check mistake * Fixed a test * removed empty script check * removed a todo * Removed useless code * Modified a test * Fixed same keys issue for data entry actions * Remove invoke snapshot (#1235) * moved complexity back * Reverted some changes, import ok * Returned account script and asset script txs, import ? * Uncommented internal snapshot, import ok * Fixed height problem with issue action and issue tx, import NO * Issue action reverted * Added log and issueCounter for issue action * Commented invoke snapshots, import ok --------- Co-authored-by: Nikolay Eskov --------- Co-authored-by: Anton Ilin Co-authored-by: Nikolay Eskov --- pkg/proto/snapshot_types.go | 313 ++++ pkg/proto/types.go | 24 + pkg/state/appender.go | 119 +- pkg/state/common_test.go | 24 +- pkg/state/fee_validation.go | 9 +- pkg/state/fee_validation_test.go | 19 +- pkg/state/invoke_applier.go | 447 +++-- pkg/state/leases.go | 28 +- pkg/state/leases_test.go | 4 +- pkg/state/orders_volume.go | 14 +- pkg/state/scripts_storage.go | 56 +- pkg/state/scripts_storage_interface.go | 2 +- pkg/state/scripts_storage_moq_test.go | 14 +- pkg/state/scripts_storage_test.go | 5 +- pkg/state/snapshot_applier.go | 152 +- pkg/state/snapshot_generator.go | 537 ++---- pkg/state/snapshot_generator_internal_test.go | 1492 +++++++++++++++++ pkg/state/snapshot_generator_test.go | 982 ----------- pkg/state/snapshot_types.go | 142 -- pkg/state/state.go | 3 +- pkg/state/transaction_checker.go | 4 +- pkg/state/transaction_checker_test.go | 182 +- pkg/state/transaction_differ.go | 8 +- pkg/state/transaction_differ_test.go | 129 +- pkg/state/transaction_handler.go | 91 +- pkg/state/transaction_performer.go | 470 ++---- pkg/state/transaction_performer_test.go | 168 +- 27 files changed, 3111 insertions(+), 2327 deletions(-) create mode 100644 pkg/proto/snapshot_types.go create mode 100644 pkg/state/snapshot_generator_internal_test.go delete mode 100644 pkg/state/snapshot_generator_test.go delete mode 100644 pkg/state/snapshot_types.go diff --git a/pkg/proto/snapshot_types.go b/pkg/proto/snapshot_types.go new file mode 100644 index 000000000..f89a2b271 --- /dev/null +++ b/pkg/proto/snapshot_types.go @@ -0,0 +1,313 @@ +package proto + +import ( + "math/big" + + "github.com/pkg/errors" + + "github.com/wavesplatform/gowaves/pkg/crypto" +) + +type TransactionSnapshot []AtomicSnapshot + +func SplitSnapshots(atomicSnapshots []AtomicSnapshot) ([]AtomicSnapshot, []AtomicSnapshot) { + var snapshots []AtomicSnapshot + var internalSnapshots []AtomicSnapshot + for _, snapshot := range atomicSnapshots { + if !snapshot.IsInternal() { + snapshots = append(snapshots, snapshot) + } else { + internalSnapshots = append(internalSnapshots, snapshot) + } + } + return snapshots, internalSnapshots +} + +func (ts TransactionSnapshot) Apply(a SnapshotApplier) error { + mainSnapshots, internalSnapshots := SplitSnapshots(ts) + // internal snapshots must be applied at the end + for _, mainSnapshot := range mainSnapshots { + if !mainSnapshot.IsGeneratedByTxDiff() { + err := mainSnapshot.Apply(a) + if err != nil { + return errors.Wrap(err, "failed to apply main transaction snapshot") + } + } + } + + for _, internalSnapshot := range internalSnapshots { + if !internalSnapshot.IsGeneratedByTxDiff() { + err := internalSnapshot.Apply(a) + if err != nil { + return errors.Wrap(err, "failed to apply internal transaction snapshot") + } + } + } + return nil +} + +type AtomicSnapshot interface { + Apply(SnapshotApplier) error + /* is temporarily used to mark snapshots generated by tx diff that shouldn't be applied, + because balances diffs are applied later in the block. */ + IsGeneratedByTxDiff() bool + IsInternal() bool +} + +type WavesBalanceSnapshot struct { + Address WavesAddress + Balance uint64 +} + +func (s WavesBalanceSnapshot) IsGeneratedByTxDiff() bool { + return true +} + +func (s WavesBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyWavesBalance(s) } + +type AssetBalanceSnapshot struct { + Address WavesAddress + AssetID crypto.Digest + Balance uint64 +} + +func (s WavesBalanceSnapshot) IsInternal() bool { + return false +} + +func (s AssetBalanceSnapshot) IsGeneratedByTxDiff() bool { + return true +} + +func (s AssetBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetBalance(s) } + +func (s AssetBalanceSnapshot) IsInternal() bool { + return false +} + +type DataEntriesSnapshot struct { // AccountData in pb + Address WavesAddress + DataEntries []DataEntry +} + +func (s DataEntriesSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s DataEntriesSnapshot) Apply(a SnapshotApplier) error { return a.ApplyDataEntries(s) } + +func (s DataEntriesSnapshot) IsInternal() bool { + return false +} + +type AccountScriptSnapshot struct { + SenderPublicKey crypto.PublicKey + Script Script + VerifierComplexity uint64 +} + +func (s AccountScriptSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s AccountScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAccountScript(s) } + +func (s AccountScriptSnapshot) IsInternal() bool { + return false +} + +type AssetScriptSnapshot struct { + AssetID crypto.Digest + Script Script +} + +func (s AssetScriptSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s AssetScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetScript(s) } + +func (s AssetScriptSnapshot) IsInternal() bool { + return false +} + +type LeaseBalanceSnapshot struct { + Address WavesAddress + LeaseIn uint64 + LeaseOut uint64 +} + +func (s LeaseBalanceSnapshot) IsGeneratedByTxDiff() bool { + return true +} + +func (s LeaseBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseBalance(s) } + +func (s LeaseBalanceSnapshot) IsInternal() bool { + return false +} + +type LeaseStateStatus struct { + Value LeaseStatus // can be only LeaseActive or LeaseCanceled + CancelHeight Height + CancelTransactionID *crypto.Digest +} + +type LeaseStateSnapshot struct { + LeaseID crypto.Digest + Status LeaseStateStatus + Amount uint64 + Sender WavesAddress + Recipient WavesAddress + OriginTransactionID *crypto.Digest + Height Height +} + +func (s LeaseStateSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s LeaseStateSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseState(s) } + +func (s LeaseStateSnapshot) IsInternal() bool { + return false +} + +type SponsorshipSnapshot struct { + AssetID crypto.Digest + MinSponsoredFee uint64 +} + +func (s SponsorshipSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s SponsorshipSnapshot) Apply(a SnapshotApplier) error { return a.ApplySponsorship(s) } + +func (s SponsorshipSnapshot) IsInternal() bool { + return false +} + +type AliasSnapshot struct { + Address WavesAddress + Alias Alias +} + +func (s AliasSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s AliasSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAlias(s) } + +func (s AliasSnapshot) IsInternal() bool { + return false +} + +// FilledVolumeFeeSnapshot Filled Volume and Fee. +type FilledVolumeFeeSnapshot struct { // OrderFill + OrderID crypto.Digest + FilledVolume uint64 + FilledFee uint64 +} + +func (s FilledVolumeFeeSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s FilledVolumeFeeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyFilledVolumeAndFee(s) } + +func (s FilledVolumeFeeSnapshot) IsInternal() bool { + return false +} + +type StaticAssetInfoSnapshot struct { + AssetID crypto.Digest + SourceTransactionID crypto.Digest + IssuerPublicKey crypto.PublicKey + Decimals uint8 + IsNFT bool +} + +func (s StaticAssetInfoSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s StaticAssetInfoSnapshot) Apply(a SnapshotApplier) error { return a.ApplyStaticAssetInfo(s) } + +func (s StaticAssetInfoSnapshot) IsInternal() bool { + return false +} + +type AssetVolumeSnapshot struct { // AssetVolume in pb + AssetID crypto.Digest + TotalQuantity big.Int // volume in protobuf + IsReissuable bool +} + +func (s AssetVolumeSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s AssetVolumeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetVolume(s) } + +func (s AssetVolumeSnapshot) IsInternal() bool { + return false +} + +type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb + AssetID crypto.Digest + AssetName string + AssetDescription string + ChangeHeight Height // last_updated in pb +} + +func (s AssetDescriptionSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s AssetDescriptionSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetDescription(s) } + +func (s AssetDescriptionSnapshot) IsInternal() bool { + return false +} + +type TransactionStatusSnapshot struct { + TransactionID crypto.Digest + Status TransactionStatus +} + +func (s TransactionStatusSnapshot) Apply(a SnapshotApplier) error { + return a.ApplyTransactionsStatus(s) +} + +func (s TransactionStatusSnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s TransactionStatusSnapshot) IsInternal() bool { + return false +} + +type InternalSnapshot interface { + InternalSnapshotMarker() +} + +type SnapshotApplier interface { + ApplyWavesBalance(snapshot WavesBalanceSnapshot) error + ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) error + ApplyAssetBalance(snapshot AssetBalanceSnapshot) error + ApplyAlias(snapshot AliasSnapshot) error + ApplyStaticAssetInfo(snapshot StaticAssetInfoSnapshot) error + ApplyAssetDescription(snapshot AssetDescriptionSnapshot) error + ApplyAssetVolume(snapshot AssetVolumeSnapshot) error + ApplyAssetScript(snapshot AssetScriptSnapshot) error + ApplySponsorship(snapshot SponsorshipSnapshot) error + ApplyAccountScript(snapshot AccountScriptSnapshot) error + ApplyFilledVolumeAndFee(snapshot FilledVolumeFeeSnapshot) error + ApplyDataEntries(snapshot DataEntriesSnapshot) error + ApplyLeaseState(snapshot LeaseStateSnapshot) error + ApplyTransactionsStatus(snapshot TransactionStatusSnapshot) error + + /* Internal snapshots. Applied only in the full node mode */ + ApplyInternalSnapshot(internalSnapshot InternalSnapshot) error +} diff --git a/pkg/proto/types.go b/pkg/proto/types.go index f1e2cb58e..ff1569e63 100644 --- a/pkg/proto/types.go +++ b/pkg/proto/types.go @@ -4022,6 +4022,14 @@ type FieldsHashes struct { LeaseBalanceHash crypto.Digest } +func (s FieldsHashes) EqualWith(other FieldsHashes) bool { + return s.DataEntryHash == other.DataEntryHash && s.AccountScriptHash == other.AccountScriptHash && + s.AssetScriptHash == other.AssetScriptHash && s.LeaseStatusHash == other.LeaseStatusHash && + s.SponsorshipHash == other.SponsorshipHash && s.AliasesHash == other.AliasesHash && + s.WavesBalanceHash == other.WavesBalanceHash && s.AssetBalanceHash == other.AssetBalanceHash && + s.LeaseBalanceHash == other.LeaseBalanceHash +} + type fieldsHashesJS struct { DataEntryHash DigestWrapped `json:"dataEntryHash"` AccountScriptHash DigestWrapped `json:"accountScriptHash"` @@ -4287,3 +4295,19 @@ func (s StateHashDebug) GetStateHash() *StateHash { } return sh } + +type LeaseStatus byte + +const ( + LeaseActive LeaseStatus = iota + LeaseCanceled + //TODO: LeaseExpired (for future use) +) + +type TransactionStatus byte + +const ( + TransactionSucceeded TransactionStatus = iota + TransactionFailed + TransactionElided +) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index b98f5d550..55a1fbb99 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -14,6 +14,8 @@ import ( "github.com/wavesplatform/gowaves/pkg/types" ) +const snapshotLimit = 1000 + type blockInfoProvider interface { NewestBlockInfoByHeight(height proto.Height) (*proto.BlockInfo, error) } @@ -325,7 +327,7 @@ func (a *txAppender) commitTxApplication( tx proto.Transaction, params *appendTxParams, invocationRes *invocationResult, - applicationRes *applicationResult) (TransactionSnapshot, error) { + applicationRes *applicationResult) (proto.TransactionSnapshot, error) { // Add transaction ID to recent IDs. txID, err := tx.GetID(a.settings.AddressSchemeCharacter) if err != nil { @@ -337,32 +339,28 @@ func (a *txAppender) commitTxApplication( // Update complexity. a.sc.addRecentTxComplexity() // Save balance diff. - // TODO get balances snapshots - if err := a.diffStor.saveTxDiff(applicationRes.changes.diff); err != nil { + if err = a.diffStor.saveTxDiff(applicationRes.changes.diff); err != nil { return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to save balance diff: %v", err)) } currentMinerAddress := proto.MustAddressFromPublicKey(a.settings.AddressSchemeCharacter, params.currentMinerPK) - var snapshot TransactionSnapshot + var snapshot proto.TransactionSnapshot if applicationRes.status { // We only perform tx in case it has not failed. performerInfo := &performerInfo{ height: params.checkerInfo.height, blockID: params.checkerInfo.blockID, currentMinerAddress: currentMinerAddress, - stateActionsCounter: params.stateActionsCounterInBlock, checkerData: applicationRes.checkerData, } - // TODO other snapshots snapshot, err = a.txHandler.performTx(tx, performerInfo, invocationRes, applicationRes.changes.diff) 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, !applicationRes.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 { @@ -371,10 +369,11 @@ func (a *txAppender) commitTxApplication( return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to count miner fee: %v", err)) } // Save transaction to storage. - if err := a.rw.writeTransaction(tx, !applicationRes.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)) } } + // TODO: transaction status snapshot has to be appended here return snapshot, nil } @@ -420,9 +419,14 @@ type appendTxParams struct { validatingUtx bool // if validatingUtx == false then chans MUST be initialized with non nil value stateActionsCounterInBlock *proto.StateActionsCounter currentMinerPK crypto.PublicKey + + snapshotGenerator *snapshotGenerator + snapshotApplier proto.SnapshotApplier } -func (a *txAppender) handleInvokeOrExchangeTransaction(tx proto.Transaction, fallibleInfo *fallibleValidationParams) (*invocationResult, *applicationResult, error) { +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" @@ -454,6 +458,9 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro a.stor.dropUncertain() }() + a.txHandler.tp.snapshotGenerator = params.snapshotGenerator + a.txHandler.tp.snapshotApplier = params.snapshotApplier + blockID := params.checkerInfo.blockID // Check that Protobuf transactions are accepted. if err := a.checkProtobufVersion(tx, params.blockV5Activated); err != nil { @@ -566,7 +573,7 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro return err } // a temporary dummy for linters - if len(snapshot) > 1000 { + if len(snapshot) > snapshotLimit { zap.S().Debug(snapshot) } // Store additional data for API: transaction by address. @@ -579,20 +586,20 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro } // 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) +func (a *txAppender) createInitialBlockSnapshot(minerAndRewardDiff txDiff) (proto.TransactionSnapshot, error) { + addrWavesBalanceDiff, _, err := balanceDiffFromTxDiff(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 + var snapshot proto.TransactionSnapshot for wavesAddress, diffAmount := range addrWavesBalanceDiff { - - fullBalance, err := a.stor.balances.wavesBalance(wavesAddress.ID()) + var fullBalance balanceProfile + 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{ + newBalance := &proto.WavesBalanceSnapshot{ Address: wavesAddress, Balance: uint64(int64(fullBalance.balance) + diffAmount.balance), } @@ -632,6 +639,28 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { if hasParent { checkerInfo.parentTimestamp = params.parent.Timestamp } + stateActionsCounterInBlockValidation := new(proto.StateActionsCounter) + // stateActionsCounterInSnapshots := new(proto.StateActionsCounter) + + snapshotApplier := newBlockSnapshotsApplier( + blockSnapshotsApplierInfo{ + ci: checkerInfo, + scheme: a.settings.AddressSchemeCharacter, + stateActionsCounter: stateActionsCounterInBlockValidation, + }, + snapshotApplierStorages{ + balances: a.stor.balances, + aliases: a.stor.aliases, + assets: a.stor.assets, + scriptsStorage: a.stor.scriptsStorage, + scriptsComplexity: a.stor.scriptsComplexity, + sponsoredAssets: a.stor.sponsoredAssets, + ordersVolumes: a.stor.ordersVolumes, + accountsDataStor: a.stor.accountsDataStor, + leases: a.stor.leases, + }, + ) + snapshotGenerator := snapshotGenerator{stor: a.stor, scheme: a.settings.AddressSchemeCharacter, IsFullNodeMode: true} // Create miner balance diff. // This adds 60% of prev block fees as very first balance diff of the current block @@ -641,16 +670,16 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { return err } // create the initial snapshot - initialSnapshot, err := a.createInitialBlockSnapshot(minerAndRewardDiff) + _, 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(minerAndRewardDiff); err != nil { + + // TODO apply this snapshot when balances are refatored + // err = initialSnapshot.Apply(&snapshotApplier) + + // Save miner diff first (for validation) + if err = a.diffStor.saveTxDiff(minerAndRewardDiff); err != nil { return err } blockInfo, err := a.currentBlockInfo() @@ -673,8 +702,8 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { if err != nil { return err } - stateActionsCounterInBlock := new(proto.StateActionsCounter) // Check and append transactions. + for _, tx := range params.transactions { appendTxArgs := &appendTxParams{ chans: params.chans, @@ -689,8 +718,10 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { blockRewardDistributionActivated: blockRewardDistributionActivated, invokeExpressionActivated: invokeExpressionActivated, validatingUtx: false, - stateActionsCounterInBlock: stateActionsCounterInBlock, + stateActionsCounterInBlock: stateActionsCounterInBlockValidation, currentMinerPK: params.block.GeneratorPublicKey, + snapshotGenerator: &snapshotGenerator, + snapshotApplier: &snapshotApplier, } if err := a.appendTx(tx, appendTxArgs); err != nil { return err @@ -704,6 +735,7 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { return nil } +// used only in tests now. All diffs are applied in snapshotApplier. func (a *txAppender) applyAllDiffs() error { a.recentTxIds = make(map[string]struct{}) return a.moveChangesToHistoryStorage() @@ -732,8 +764,9 @@ func newApplicationResult(status bool, totalScriptsRuns uint64, changes txBalanc return &applicationResult{status, totalScriptsRuns, changes, checkerData} // all fields must be initialized } -func (a *txAppender) handleInvoke(tx proto.Transaction, info *fallibleValidationParams) (*invocationResult, *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: @@ -864,7 +897,9 @@ func (a *txAppender) handleExchange(tx proto.Transaction, info *fallibleValidati return newApplicationResult(true, scriptsRuns, successfulChanges, checkerData), nil } -func (a *txAppender) handleFallible(tx proto.Transaction, info *fallibleValidationParams) (*invocationResult, *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, nil, err @@ -931,6 +966,28 @@ func (a *txAppender) validateNextTx(tx proto.Transaction, currentTimestamp, pare if err != nil { return errs.Extend(err, "failed to check 'InvokeExpression' is activated") // TODO: check feature naming in err message } + issueCounterInBlock := new(proto.StateActionsCounter) + snapshotApplier := newBlockSnapshotsApplier( + blockSnapshotsApplierInfo{ + ci: checkerInfo, + scheme: a.settings.AddressSchemeCharacter, + stateActionsCounter: issueCounterInBlock, + }, + snapshotApplierStorages{ + balances: a.stor.balances, + aliases: a.stor.aliases, + assets: a.stor.assets, + scriptsStorage: a.stor.scriptsStorage, + scriptsComplexity: a.stor.scriptsComplexity, + sponsoredAssets: a.stor.sponsoredAssets, + ordersVolumes: a.stor.ordersVolumes, + accountsDataStor: a.stor.accountsDataStor, + leases: a.stor.leases, + }, + ) + snapshotGenerator := snapshotGenerator{stor: a.stor, scheme: a.settings.AddressSchemeCharacter, + IsFullNodeMode: true} + appendTxArgs := &appendTxParams{ chans: nil, // nil because validatingUtx == true checkerInfo: checkerInfo, @@ -945,7 +1002,9 @@ func (a *txAppender) validateNextTx(tx proto.Transaction, currentTimestamp, pare invokeExpressionActivated: invokeExpressionActivated, validatingUtx: true, // it's correct to use new counter because there's no block exists, but this field is necessary in tx performer - stateActionsCounterInBlock: new(proto.StateActionsCounter), + stateActionsCounterInBlock: issueCounterInBlock, + snapshotGenerator: &snapshotGenerator, + snapshotApplier: &snapshotApplier, } err = a.appendTx(tx, appendTxArgs) if err != nil { diff --git a/pkg/state/common_test.go b/pkg/state/common_test.go index f40cc16c1..73f190596 100644 --- a/pkg/state/common_test.go +++ b/pkg/state/common_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/mr-tron/base58/base58" + "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -490,11 +491,32 @@ func (s *testStorageObjects) createAsset(t *testing.T, assetID crypto.Digest) *a func (s *testStorageObjects) createSmartAsset(t *testing.T, assetID crypto.Digest) { s.addBlock(t, blockID0) - err := s.entities.scriptsStorage.setAssetScript(assetID, testGlobal.scriptBytes, testGlobal.senderInfo.pk, blockID0) + err := s.entities.scriptsStorage.setAssetScript(assetID, testGlobal.scriptBytes, blockID0) assert.NoError(t, err, "setAssetScript failed") s.flush(t) } +func storeScriptByAddress( + stor *blockchainEntitiesStorage, + scheme proto.Scheme, + senderPK crypto.PublicKey, + script proto.Script, + se scriptEstimation, + blockID proto.BlockID, +) error { + senderAddr, err := proto.NewAddressFromPublicKey(scheme, senderPK) + if err != nil { + return errors.Wrapf(err, "failed to create addr from PK %q", senderPK.String()) + } + if setErr := stor.scriptsStorage.setAccountScript(senderAddr, script, senderPK, blockID); setErr != nil { + return errors.Wrapf(setErr, "failed to set account script on addr %q", senderAddr.String()) + } + if setErr := stor.scriptsComplexity.saveComplexitiesForAddr(senderAddr, se, blockID); setErr != nil { + return errors.Wrapf(setErr, "failed to save script complexities for addr %q", senderAddr.String()) + } + return nil +} + func (s *testStorageObjects) setScript(t *testing.T, pk crypto.PublicKey, script proto.Script, blockID proto.BlockID) { var est ride.TreeEstimation if !script.IsEmpty() { diff --git a/pkg/state/fee_validation.go b/pkg/state/fee_validation.go index fba45e57a..0c96a9474 100644 --- a/pkg/state/fee_validation.go +++ b/pkg/state/fee_validation.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/ride" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/errs" @@ -259,14 +260,14 @@ func scriptsCost(tx proto.Transaction, params *feeValidationParams) (*txCosts, e if err != nil { return nil, err } - // check complexity of script for free verifier if complexity <= 200 complexity := 0 if accountScripted && params.rideV5Activated { // For account script we use original estimation - treeEstimation, scErr := params.stor.scriptsComplexity.newestScriptComplexityByAddr(senderWavesAddr) - if scErr != nil { - return nil, errors.Wrap(scErr, "failed to get complexity by addr from store") + var treeEstimation *ride.TreeEstimation + treeEstimation, err = params.stor.scriptsComplexity.newestScriptComplexityByAddr(senderWavesAddr) + if err != nil { + return nil, errors.Wrap(err, "failed to get complexity by addr from store") } complexity = treeEstimation.Verifier } diff --git a/pkg/state/fee_validation_test.go b/pkg/state/fee_validation_test.go index 561c488c1..8528d8fba 100644 --- a/pkg/state/fee_validation_test.go +++ b/pkg/state/fee_validation_test.go @@ -49,11 +49,11 @@ The account script is set on blockID2, then rollback returns storage to the bloc The account must not have a verifier anymore. However, the filter is false, so invalid data (verifier) will be returned\ */ func TestAccountHasVerifierAfterRollbackFilterFalse(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) to.stor.hs.amend = false tx := createSetScriptWithProofs(t) - info := defaultCheckerInfo() to.stor.activateFeature(t, int16(settings.SmartAccounts)) @@ -65,8 +65,9 @@ func TestAccountHasVerifierAfterRollbackFilterFalse(t *testing.T) { address, err := proto.NewAddressFromPublicKey(to.tc.settings.AddressSchemeCharacter, tx.SenderPK) assert.NoError(t, err, "failed to receive an address from public key") - txPerformerInfo := defaultPerformerInfo() + txPerformerInfo := defaultPerformerInfo(to.stateActionsCounter) txPerformerInfo.blockID = blockID2 + info.blockID = blockID2 // the block from checker info is used by snapshot applier to apply a tx txPerformerInfo.checkerData = checkerData _, err = to.tp.performSetScriptWithProofs(tx, txPerformerInfo, nil, nil) @@ -88,7 +89,8 @@ func TestAccountHasVerifierAfterRollbackFilterFalse(t *testing.T) { // the account script is set on blockID2, then blockID3 is added, then rollback returns storage to the blockID1. // The account must not have a verifier anymore. Filter is true, so everything must be valid func TestAccountDoesNotHaveScriptAfterRollbackFilterTrue(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) to.stor.hs.amend = true tx := createSetScriptWithProofs(t) @@ -101,14 +103,11 @@ func TestAccountDoesNotHaveScriptAfterRollbackFilterTrue(t *testing.T) { address, err := proto.NewAddressFromPublicKey(to.tc.settings.AddressSchemeCharacter, tx.SenderPK) assert.NoError(t, err, "failed to receive an address from public key") - txPerformerInfo := defaultPerformerInfo() + txPerformerInfo := defaultPerformerInfo(to.stateActionsCounter) txPerformerInfo.blockID = blockID2 -<<<<<<< HEAD - txPerformerInfo.checkerData.scriptEstimations = &scriptsEstimations{} - _, err = to.tp.performSetScriptWithProofs(tx, txPerformerInfo, nil, nil) -======= + info.blockID = blockID2 // the block from checker info is used by snapshot applier to apply a tx txPerformerInfo.checkerData.scriptEstimation = &scriptEstimation{} ->>>>>>> master + _, err = to.tp.performSetScriptWithProofs(tx, txPerformerInfo, nil, nil) assert.NoError(t, err, "performSetScriptWithProofs failed with valid SetScriptWithProofs tx") diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index 02eddfdd5..46b14616b 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -664,7 +664,7 @@ func (ia *invokeApplier) fallibleValidation(tx proto.Transaction, info *addlInvo Recipient: recipientAddress, Amount: uint64(a.Amount), Height: info.blockInfo.Height, - Status: LeaseActive, + Status: proto.LeaseActive, } ia.stor.leases.addLeasingUncertain(a.ID, l) @@ -726,88 +726,271 @@ func (ia *invokeApplier) fallibleValidation(tx proto.Transaction, info *addlInvo return 0, totalChanges, nil } -// applyInvokeScript checks InvokeScript transaction, creates its balance diffs and adds changes to `uncertain` storage. -// 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) (*invocationResult, *applicationResult, error) { - // In defer we should clean all the temp changes invoke does to state. - defer func() { - ia.invokeDiffStor.invokeDiffsStor.reset() - }() +func (ia *invokeApplier) handleInvokeFunctionError( + err error, + info *fallibleValidationParams, + txID crypto.Digest, + checkerData txCheckerData, + failedChanges txBalanceChanges, +) (*invocationResult, *applicationResult, error) { + // After activation of RideV6 feature transactions are failed if they are not cheap regardless the error kind. + isCheap := int(ia.sc.recentTxComplexity) <= FailFreeInvokeComplexity + if info.rideV6Activated { + if !info.acceptFailed || isCheap { + 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"), + ) + } + invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error()} + var applicationRes *applicationResult + applicationRes, err = ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) + 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 + // 2) The error is ride.InternalInvocationError and correct fail/reject behaviour is activated + // 3) The spent complexity is less than limit + switch ride.GetEvaluationErrorType(err) { + case ride.UserError, ride.RuntimeError, ride.ComplexityLimitExceed: + // 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, 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"), + ) + } + invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error()} + var applicationRes *applicationResult + applicationRes, err = ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) + 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, 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"), + ) + } + invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error()} + var applicationRes *applicationResult + applicationRes, err = ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) + return invocationRes, applicationRes, err - var ( - paymentsLength int - scriptAddr proto.WavesAddress - txID crypto.Digest - sender proto.Address - tree *ast.Tree - scriptPK crypto.PublicKey - ) + case ride.Undefined, ride.EvaluationFailure: // Unhandled or evaluator error + return nil, nil, errors.Wrapf(err, "invocation of transaction '%s' failed", txID.String()) + default: + return nil, nil, errors.Wrapf(err, "invocation of transaction '%s' failed", txID.String()) + } +} + +type scriptParameters struct { + paymentsLength int + scriptAddr proto.WavesAddress + txID crypto.Digest + sender proto.Address + tree *ast.Tree + scriptPK crypto.PublicKey +} + +func (ia *invokeApplier) scriptParametersFromInvokeScript( + transaction *proto.InvokeScriptWithProofs, +) (scriptParameters, error) { + var scriptParams scriptParameters + var err error + scriptParams.scriptAddr, err = recipientToAddress(transaction.ScriptRecipient, ia.stor.aliases) + if err != nil { + return scriptParameters{}, errors.Wrap(err, "recipientToAddress() failed") + } + scriptParams.paymentsLength = len(transaction.Payments) + scriptParams.txID = *transaction.ID + scriptParams.sender, err = proto.NewAddressFromPublicKey(ia.settings.AddressSchemeCharacter, transaction.SenderPK) + if err != nil { + return scriptParameters{}, errors.Wrapf(err, "failed to apply script invocation") + } + scriptParams.tree, err = ia.stor.scriptsStorage.newestScriptByAddr(scriptParams.scriptAddr) + if err != nil { + return scriptParameters{}, + errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptParams.scriptAddr.String()) + } + var si scriptBasicInfoRecord + si, err = ia.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptParams.scriptAddr.ID()) + if err != nil { + return scriptParameters{}, + errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptParams.scriptAddr.String()) + } + scriptParams.scriptPK = si.PK + return scriptParams, nil +} + +func (ia *invokeApplier) scriptParametersFromInvokeExpression( + transaction *proto.InvokeExpressionTransactionWithProofs) (scriptParameters, error) { + var scriptParams scriptParameters + addr, err := proto.NewAddressFromPublicKey(ia.settings.AddressSchemeCharacter, transaction.SenderPK) + if err != nil { + return scriptParameters{}, errors.Wrap(err, "recipientToAddress() failed") + } + scriptParams.sender = addr + scriptParams.scriptAddr = addr + scriptParams.tree, err = serialization.Parse(transaction.Expression) + if err != nil { + return scriptParameters{}, errors.Wrap(err, "failed to parse decoded invoke expression into tree") + } + scriptParams.txID = *transaction.ID + scriptParams.scriptPK = transaction.SenderPK + return scriptParams, nil +} + +func (ia *invokeApplier) scriptParametersFromEthereumInvokeTransaction( + transaction *proto.EthereumTransaction) (scriptParameters, error) { + var scriptParams scriptParameters + var err error + scriptParams.scriptAddr, err = transaction.WavesAddressTo(ia.settings.AddressSchemeCharacter) + if err != nil { + return scriptParameters{}, err + } + decodedData := transaction.TxKind.DecodedData() + scriptParams.paymentsLength = len(decodedData.Payments) + scriptParams.txID = *transaction.ID + scriptParams.sender, err = transaction.WavesAddressFrom(ia.settings.AddressSchemeCharacter) + if err != nil { + return scriptParameters{}, errors.Wrapf(err, "failed to apply script invocation") + } + scriptParams.tree, err = ia.stor.scriptsStorage.newestScriptByAddr(scriptParams.scriptAddr) + if err != nil { + return scriptParameters{}, + errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptParams.scriptAddr.String()) + } + var si scriptBasicInfoRecord + si, err = ia.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptParams.scriptAddr.ID()) + if err != nil { + return scriptParameters{}, + errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptParams.scriptAddr.String()) + } + scriptParams.scriptPK = si.PK + return scriptParams, nil +} + +func (ia *invokeApplier) collectScriptParameters(tx proto.Transaction) (scriptParameters, error) { + var scriptParams scriptParameters + var err error switch transaction := tx.(type) { case *proto.InvokeScriptWithProofs: - var err error - scriptAddr, err = recipientToAddress(transaction.ScriptRecipient, ia.stor.aliases) + scriptParams, err = ia.scriptParametersFromInvokeScript(transaction) if err != nil { - return nil, nil, errors.Wrap(err, "recipientToAddress() failed") + return scriptParameters{}, err } - paymentsLength = len(transaction.Payments) - txID = *transaction.ID - sender, err = proto.NewAddressFromPublicKey(ia.settings.AddressSchemeCharacter, transaction.SenderPK) - if err != nil { - return nil, nil, errors.Wrapf(err, "failed to apply script invocation") - } - tree, err = ia.stor.scriptsStorage.newestScriptByAddr(scriptAddr) + case *proto.InvokeExpressionTransactionWithProofs: + scriptParams, err = ia.scriptParametersFromInvokeExpression(transaction) if err != nil { - return nil, nil, errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptAddr.String()) + return scriptParameters{}, err } - si, err := ia.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptAddr.ID()) + case *proto.EthereumTransaction: + scriptParams, err = ia.scriptParametersFromEthereumInvokeTransaction(transaction) if err != nil { - return nil, nil, errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptAddr.String()) + return scriptParameters{}, err } - scriptPK = si.PK + default: + return scriptParameters{}, errors.Errorf("failed to apply an invoke script: unexpected type of transaction (%T)", tx) + } - case *proto.InvokeExpressionTransactionWithProofs: - addr, err := proto.NewAddressFromPublicKey(ia.settings.AddressSchemeCharacter, transaction.SenderPK) - if err != nil { - return nil, nil, errors.Wrap(err, "recipientToAddress() failed") + return scriptParams, nil +} + +func (ia *invokeApplier) handleFallibleValidationError(err error, + txID crypto.Digest, + code proto.TxFailureReason, + info *fallibleValidationParams, + scriptRuns uint64, + r ride.Result) (*invocationResult, error) { + var invocationRes *invocationResult + if err != nil { + zap.S().Debugf("fallibleValidation error in tx %s. Error: %s", txID.String(), err.Error()) + // If fallibleValidation fails, we should save transaction to blockchain when acceptFailed is true. + if !info.acceptFailed || + (ia.sc.recentTxComplexity <= FailFreeInvokeComplexity && + info.checkerInfo.height >= ia.settings.InternalInvokeCorrectFailRejectBehaviourAfterHeight) { + return nil, err } - sender = addr - scriptAddr = addr - tree, err = serialization.Parse(transaction.Expression) - if err != nil { - return nil, nil, errors.Wrap(err, "failed to parse decoded invoke expression into tree") + invocationRes = &invocationResult{ + failed: true, + code: code, + text: err.Error(), + scriptRuns: scriptRuns, + actions: r.ScriptActions(), + } + } else { + invocationRes = &invocationResult{ + failed: false, + scriptRuns: scriptRuns, + actions: r.ScriptActions(), } - txID = *transaction.ID - scriptPK = transaction.SenderPK + } + return invocationRes, nil +} - case *proto.EthereumTransaction: - var err error - scriptAddr, err = transaction.WavesAddressTo(ia.settings.AddressSchemeCharacter) +func (ia *invokeApplier) countScriptRuns(info *fallibleValidationParams, + paymentSmartAssets []crypto.Digest, + scriptActions []proto.ScriptAction) (uint64, error) { + var scriptRuns uint64 + + // After activation of RideV5 (16) feature we don't take extra fee for execution of smart asset scripts. + if !info.rideV5Activated { + actionScriptRuns, err := ia.countActionScriptRuns(scriptActions) if err != nil { - return nil, nil, err + return 0, errors.Wrap(err, "failed to countActionScriptRuns") } - decodedData := transaction.TxKind.DecodedData() - paymentsLength = len(decodedData.Payments) - txID = *transaction.ID - sender, err = transaction.WavesAddressFrom(ia.settings.AddressSchemeCharacter) + scriptRuns += uint64(len(paymentSmartAssets)) + actionScriptRuns + } + if info.senderScripted { + treeEstimation, err := ia.stor.scriptsComplexity.newestScriptComplexityByAddr( + info.senderAddress) if err != nil { - return nil, nil, errors.Wrapf(err, "failed to apply script invocation") + return 0, errors.Wrap(err, "invoke failed to get verifier complexity") } - tree, err = ia.stor.scriptsStorage.newestScriptByAddr(scriptAddr) - if err != nil { - return nil, nil, errors.Wrapf(err, "failed to instantiate script on address '%s'", scriptAddr.String()) + // Since activation of RideV5 (16) feature + // we don't take fee for verifier execution if it's complexity is less than `FreeVerifierComplexity` limit, + // take fee in any other case + if !(info.rideV5Activated && treeEstimation.Verifier <= FreeVerifierComplexity) { + // take fee + scriptRuns++ } - si, err := ia.stor.scriptsStorage.newestScriptBasicInfoByAddressID(scriptAddr.ID()) - if err != nil { - return nil, nil, errors.Wrapf(err, "failed to get script's public key on address '%s'", scriptAddr.String()) + } + return scriptRuns, nil +} + +func (ia *invokeApplier) refusePayments(scriptParams scriptParameters, disableSelfTransfers bool) bool { + if disableSelfTransfers && scriptParams.paymentsLength > 0 { + if scriptParams.sender == scriptParams.scriptAddr { + return true } - scriptPK = si.PK + } + return false +} - default: - return nil, nil, errors.Errorf("failed to apply an invoke script: unexpected type of transaction (%T)", tx) +// applyInvokeScript checks InvokeScript transaction, creates its balance diffs and adds changes to `uncertain` storage. +// 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) (*invocationResult, *applicationResult, error) { + // In defer we should clean all the temp changes invoke does to state. + defer func() { + ia.invokeDiffStor.invokeDiffsStor.reset() + }() + + scriptParams, err := ia.collectScriptParameters(tx) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to collect script parameters") } // If BlockV5 feature is not activated, we never accept failed transactions. @@ -831,17 +1014,16 @@ func (ia *invokeApplier) applyInvokeScript( // 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, nil, errors.Errorf("multiple payments is not allowed for RIDE library version %d", tree.LibVersion) + if scriptParams.paymentsLength >= 2 && scriptParams.tree.LibVersion < ast.LibV4 { + return nil, nil, + errors.Errorf("multiple payments is not allowed for RIDE library version %d", scriptParams.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, nil, errors.New("paying to DApp itself is forbidden since RIDE V4") - - } + disableSelfTransfers := info.acceptFailed && scriptParams.tree.LibVersion >= ast.LibV4 + if ia.refusePayments(scriptParams, disableSelfTransfers) { + 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)) @@ -850,124 +1032,35 @@ func (ia *invokeApplier) applyInvokeScript( } // Call script function. - r, err := ia.sc.invokeFunction(tree, scriptEstimationUpdate, tx, info, scriptAddr) + r, err := ia.sc.invokeFunction(scriptParams.tree, scriptEstimationUpdate, tx, info, scriptParams.scriptAddr) + if err != nil { - // Script returned error, it's OK, but we have to decide is it failed or rejected transaction. - // After activation of RideV6 feature transactions are failed if they are not cheap regardless the error kind. - isCheap := int(ia.sc.recentTxComplexity) <= FailFreeInvokeComplexity - if info.rideV6Activated { - if !info.acceptFailed || isCheap { - 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"), - ) - } - invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error()} - applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) - 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 - // 2) The error is ride.InternalInvocationError and correct fail/reject behaviour is activated - // 3) The spent complexity is less than limit - switch ride.GetEvaluationErrorType(err) { - case ride.UserError, ride.RuntimeError, ride.ComplexityLimitExceed: - // 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, 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"), - ) - } - invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error()} - applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) - 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, 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"), - ) - } - invocationRes := &invocationResult{failed: true, code: proto.DAppError, text: err.Error()} - applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes, failedChanges) - return invocationRes, applicationRes, err - - case ride.Undefined, ride.EvaluationFailure: // Unhandled or evaluator error - return nil, nil, errors.Wrapf(err, "invocation of transaction '%s' failed", txID.String()) - default: - return nil, nil, errors.Wrapf(err, "invocation of transaction '%s' failed", txID.String()) - } - } - var scriptRuns uint64 = 0 - // After activation of RideV5 (16) feature we don't take extra fee for execution of smart asset scripts. - if !info.rideV5Activated { - actionScriptRuns, err := ia.countActionScriptRuns(r.ScriptActions()) - if err != nil { - return nil, nil, errors.Wrap(err, "failed to countActionScriptRuns") - } - scriptRuns += uint64(len(paymentSmartAssets)) + actionScriptRuns + // Script returned error, it's OK, but we have to decide if it's a failed or rejected transaction. + return ia.handleInvokeFunctionError(err, info, scriptParams.txID, checkerData, failedChanges) } - if info.senderScripted { - // Since activation of RideV5 (16) feature we don't take fee for verifier execution if it's complexity is less than `FreeVerifierComplexity` limit - if info.rideV5Activated { - var treeEstimation *ride.TreeEstimation - treeEstimation, err = ia.stor.scriptsComplexity.newestScriptComplexityByAddr(info.senderAddress) - if err != nil { - return nil, nil, errors.Wrap(err, "invoke failed to get verifier complexity") - // For account script we use original estimation - } - if treeEstimation.Verifier > FreeVerifierComplexity { - scriptRuns++ - } - } else { - scriptRuns++ - } + scriptRuns, err := ia.countScriptRuns(info, paymentSmartAssets, r.ScriptActions()) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to count scripts runs") } - var invocationRes *invocationResult + code, balanceChanges, err := ia.fallibleValidation(tx, &addlInvokeInfo{ fallibleValidationParams: info, - scriptAddr: scriptAddr, - scriptPK: scriptPK, + scriptAddr: scriptParams.scriptAddr, + scriptPK: scriptParams.scriptPK, scriptRuns: scriptRuns, failedChanges: failedChanges, actions: r.ScriptActions(), paymentSmartAssets: paymentSmartAssets, disableSelfTransfers: disableSelfTransfers, - libVersion: tree.LibVersion, + libVersion: scriptParams.tree.LibVersion, }) + invocationRes, err := ia.handleFallibleValidationError(err, scriptParams.txID, code, info, scriptRuns, r) if err != nil { - zap.S().Debugf("fallibleValidation error in tx %s. Error: %s", txID.String(), err.Error()) - // If fallibleValidation fails, we should save transaction to blockchain when acceptFailed is true. - if !info.acceptFailed || - (ia.sc.recentTxComplexity <= FailFreeInvokeComplexity && - info.checkerInfo.height >= ia.settings.InternalInvokeCorrectFailRejectBehaviourAfterHeight) { - return nil, nil, err - } - invocationRes = &invocationResult{ - failed: true, - code: code, - text: err.Error(), - scriptRuns: scriptRuns, - actions: r.ScriptActions(), - } - } else { - invocationRes = &invocationResult{ - failed: false, - scriptRuns: scriptRuns, - actions: r.ScriptActions(), - } + return nil, nil, err } - applicationRes, err := ia.handleInvocationResult(txID, checkerData, info, invocationRes, balanceChanges) + + applicationRes, err := ia.handleInvocationResult(scriptParams.txID, checkerData, info, invocationRes, balanceChanges) return invocationRes, applicationRes, err } @@ -989,7 +1082,9 @@ func toScriptResult(ir *invocationResult) (*proto.ScriptResult, error) { return sr, err } -func (ia *invokeApplier) handleInvocationResult(txID crypto.Digest, checkerData txCheckerData, info *fallibleValidationParams, res *invocationResult, balanceChanges txBalanceChanges) (*applicationResult, error) { +func (ia *invokeApplier) handleInvocationResult(txID crypto.Digest, checkerData txCheckerData, + info *fallibleValidationParams, res *invocationResult, + balanceChanges txBalanceChanges) (*applicationResult, error) { if ia.buildApiData && !info.validatingUtx { // Save invoke result for extended API. res, err := toScriptResult(res) diff --git a/pkg/state/leases.go b/pkg/state/leases.go index c096b54a1..dca931269 100644 --- a/pkg/state/leases.go +++ b/pkg/state/leases.go @@ -13,14 +13,6 @@ import ( "github.com/wavesplatform/gowaves/pkg/proto" ) -type LeaseStatus byte - -const ( - LeaseActive LeaseStatus = iota - LeaseCanceled - //TODO: LeaseExpired (for future use) -) - type leaseRecordForStateHashes struct { id *crypto.Digest active byte @@ -46,14 +38,14 @@ type leasing struct { Recipient proto.WavesAddress `cbor:"1,keyasint"` Amount uint64 `cbor:"2,keyasint"` Height uint64 `cbor:"3,keyasint"` - Status LeaseStatus `cbor:"4,keyasint"` + Status proto.LeaseStatus `cbor:"4,keyasint"` OriginTransactionID *crypto.Digest `cbor:"5,keyasint,omitempty"` CancelHeight uint64 `cbor:"7,keyasint,omitempty"` CancelTransactionID *crypto.Digest `cbor:"8,keyasint,omitempty"` } func (l *leasing) isActive() bool { - return l.Status == LeaseActive + return l.Status == proto.LeaseActive } func (l *leasing) marshalBinary() ([]byte, error) { @@ -100,7 +92,7 @@ func (l *leases) cancelLeases(bySenders map[proto.WavesAddress]struct{}, blockID key := keyvalue.SafeKey(leaseIter) leaseBytes := keyvalue.SafeValue(leaseIter) record := new(leasing) - if err := record.unmarshalBinary(leaseBytes); err != nil { + if err = record.unmarshalBinary(leaseBytes); err != nil { return errors.Wrap(err, "failed to unmarshal lease") } toCancel := true @@ -114,7 +106,7 @@ func (l *leases) cancelLeases(bySenders map[proto.WavesAddress]struct{}, blockID return errors.Wrap(err, "failed to unmarshal lease key") } zap.S().Infof("State: cancelling lease %s", k.leaseID.String()) - record.Status = LeaseCanceled + record.Status = proto.LeaseCanceled if err := l.addLeasing(k.leaseID, record, blockID); err != nil { return errors.Wrap(err, "failed to save lease to storage") } @@ -137,7 +129,7 @@ func (l *leases) cancelLeasesToDisabledAliases(scheme proto.Scheme, height proto return nil, errors.Wrapf(err, "failed to get newest leasing info by id %q", leaseID.String()) } zap.S().Infof("State: canceling lease %s", leaseID) - record.Status = LeaseCanceled + record.Status = proto.LeaseCanceled record.CancelHeight = height if err := l.addLeasing(leaseID, record, blockID); err != nil { return nil, errors.Wrapf(err, "failed to save leasing %q to storage", leaseID) @@ -177,7 +169,7 @@ func (l *leases) validLeaseIns() (map[proto.WavesAddress]int64, error) { for leaseIter.Next() { leaseBytes := keyvalue.SafeValue(leaseIter) record := new(leasing) - if err := record.unmarshalBinary(leaseBytes); err != nil { + if err = record.unmarshalBinary(leaseBytes); err != nil { return nil, errors.Wrap(err, "failed to unmarshal lease") } if record.isActive() { @@ -200,7 +192,7 @@ func (l *leases) newestLeasingInfo(id crypto.Digest) (*leasing, error) { return nil, err } record := new(leasing) - if err := record.unmarshalBinary(recordBytes); err != nil { + if err = record.unmarshalBinary(recordBytes); err != nil { return nil, errors.Wrap(err, "failed to unmarshal record") } if record.OriginTransactionID == nil { @@ -217,7 +209,7 @@ func (l *leases) leasingInfo(id crypto.Digest) (*leasing, error) { return nil, err } record := new(leasing) - if err := record.unmarshalBinary(recordBytes); err != nil { + if err = record.unmarshalBinary(recordBytes); err != nil { return nil, errors.Wrap(err, "failed to unmarshal record") } if record.OriginTransactionID == nil { @@ -270,7 +262,7 @@ func (l *leases) cancelLeasing(id crypto.Digest, blockID proto.BlockID, height u if err != nil { return errors.Errorf("failed to get leasing info: %v", err) } - leasing.Status = LeaseCanceled + leasing.Status = proto.LeaseCanceled leasing.CancelHeight = height leasing.CancelTransactionID = txID return l.addLeasing(id, leasing, blockID) @@ -281,7 +273,7 @@ func (l *leases) cancelLeasingUncertain(id crypto.Digest, height uint64, txID *c if err != nil { return errors.Errorf("failed to get leasing info: %v", err) } - leasing.Status = LeaseCanceled + leasing.Status = proto.LeaseCanceled leasing.CancelTransactionID = txID leasing.CancelHeight = height l.addLeasingUncertain(id, leasing) diff --git a/pkg/state/leases_test.go b/pkg/state/leases_test.go index 57c02be7b..7222f3658 100644 --- a/pkg/state/leases_test.go +++ b/pkg/state/leases_test.go @@ -30,7 +30,7 @@ func createLease(t *testing.T, sender string, id crypto.Digest) *leasing { Recipient: recipientAddr, Sender: senderAddr, Amount: 10, - Status: LeaseActive, + Status: proto.LeaseActive, } } @@ -155,7 +155,7 @@ func TestCancelLeasing(t *testing.T) { assert.NoError(t, err, "failed to add leasing") err = to.leases.cancelLeasing(leaseID, blockID0, to.stor.rw.height, &txID) assert.NoError(t, err, "failed to cancel leasing") - r.Status = LeaseCanceled + r.Status = proto.LeaseCanceled r.CancelHeight = 1 r.CancelTransactionID = &txID to.stor.flush(t) diff --git a/pkg/state/orders_volume.go b/pkg/state/orders_volume.go index 64cc9a421..4e8e91c6a 100644 --- a/pkg/state/orders_volume.go +++ b/pkg/state/orders_volume.go @@ -41,7 +41,7 @@ func newOrdersVolumes(hs *historyStorage) *ordersVolumes { return &ordersVolumes{hs: hs} } -func (ov *ordersVolumes) newestVolumeById(orderID []byte) (*orderVolumeRecord, error) { +func (ov *ordersVolumes) newestVolumeByID(orderID []byte) (*orderVolumeRecord, error) { key := ordersVolumeKey{orderID} recordBytes, err := ov.hs.newestTopEntryData(key.bytes()) if err != nil { @@ -63,8 +63,9 @@ func (ov *ordersVolumes) addNewRecord(orderID []byte, record *orderVolumeRecord, return ov.hs.addNewEntry(ordersVolume, key.bytes(), recordBytes, blockID) } +// TODO remove it func (ov *ordersVolumes) increaseFilled(orderID []byte, amountChange, feeChange uint64, blockID proto.BlockID) error { - prevVolume, err := ov.newestVolumeById(orderID) + prevVolume, err := ov.newestVolumeByID(orderID) if err != nil { if isNotFoundInHistoryOrDBErr(err) { // New record. return ov.addNewRecord(orderID, &orderVolumeRecord{amountFilled: amountChange, feeFilled: feeChange}, blockID) @@ -76,8 +77,13 @@ func (ov *ordersVolumes) increaseFilled(orderID []byte, amountChange, feeChange return ov.addNewRecord(orderID, prevVolume, blockID) } -func (ov *ordersVolumes) newestFilled(orderID []byte) (amount, fee uint64, err error) { - volume, err := ov.newestVolumeById(orderID) +func (ov *ordersVolumes) storeFilled(orderID []byte, amountFilled, feeFilled uint64, blockID proto.BlockID) error { + newVolume := &orderVolumeRecord{amountFilled: amountFilled, feeFilled: feeFilled} + return ov.addNewRecord(orderID, newVolume, blockID) +} + +func (ov *ordersVolumes) newestFilled(orderID []byte) (uint64, uint64, error) { + volume, err := ov.newestVolumeByID(orderID) if err != nil { if isNotFoundInHistoryOrDBErr(err) { // No fee volume filled yet. return 0, 0, nil diff --git a/pkg/state/scripts_storage.go b/pkg/state/scripts_storage.go index 00af3f05d..3298721cc 100644 --- a/pkg/state/scripts_storage.go +++ b/pkg/state/scripts_storage.go @@ -6,6 +6,7 @@ import ( "github.com/fxamacker/cbor/v2" "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/ride/ast" @@ -74,7 +75,7 @@ func (as *assetScripRecordForHashes) less(other stateComponent) bool { } type scriptBasicInfoRecord struct { - PK crypto.PublicKey `cbor:"0,keyasint,omitemtpy"` + PK crypto.PublicKey `cbor:"0,keyasint,omitemtpy"` // not empty only for account script ScriptLen uint32 `cbor:"1,keyasint,omitemtpy"` LibraryVersion ast.LibraryVersion `cbor:"2,keyasint,omitemtpy"` HasVerifier bool `cbor:"3,keyasint,omitemtpy"` @@ -112,16 +113,49 @@ func (r *scriptBasicInfoRecord) unmarshalBinary(data []byte) error { return cbor.Unmarshal(data, r) } +func newAccountScriptBasicInfoRecord( + pk crypto.PublicKey, + script proto.Script, +) (scriptBasicInfoRecord, *ast.Tree, error) { + info, tree, err := newScriptBasicInfoRecord(pk, script) + if err != nil { + return scriptBasicInfoRecord{}, nil, errors.Wrap(err, "failed to create new account script basic info record") + } + return info, tree, nil +} + +func newAssetScriptBasicInfoRecord(script proto.Script) (scriptBasicInfoRecord, *ast.Tree, error) { + var emptyPKStub crypto.PublicKey + info, tree, err := newScriptBasicInfoRecord(emptyPKStub, script) + if err != nil { + return scriptBasicInfoRecord{}, nil, errors.Wrap(err, "failed to create new asset script basic info record") + } + return info, tree, nil +} + type scriptDBItem struct { script proto.Script tree *ast.Tree info scriptBasicInfoRecord } -func newScriptDBItem(pk crypto.PublicKey, script proto.Script) (scriptDBItem, error) { - info, tree, err := newScriptBasicInfoRecord(pk, script) +func newAccountScriptDBItem(pk crypto.PublicKey, script proto.Script) (scriptDBItem, error) { + info, tree, err := newAccountScriptBasicInfoRecord(pk, script) + if err != nil { + return scriptDBItem{}, errors.Wrap(err, "failed to create new account script basic info record") + } + dbItem := scriptDBItem{ + script: script, + tree: tree, + info: info, + } + return dbItem, nil +} + +func newAssetScriptDBIterm(script proto.Script) (scriptDBItem, error) { + info, tree, err := newAssetScriptBasicInfoRecord(script) if err != nil { - return scriptDBItem{}, errors.Wrap(err, "failed to create new script basic info record") + return scriptDBItem{}, errors.Wrap(err, "failed to create new asset script basic info record") } dbItem := scriptDBItem{ script: script, @@ -233,7 +267,7 @@ func (ss *scriptsStorage) scriptTreeByKey(key []byte) (*ast.Tree, error) { func (ss *scriptsStorage) commitUncertain(blockID proto.BlockID) error { for assetID, r := range ss.uncertainAssetScripts { digest := proto.ReconstructDigest(assetID, r.assetIDTail) - if err := ss.setAssetScript(digest, r.scriptDBItem.script, r.scriptDBItem.info.PK, blockID); err != nil { + if err := ss.setAssetScript(digest, r.scriptDBItem.script, blockID); err != nil { return err } } @@ -250,7 +284,7 @@ func (ss *scriptsStorage) setAssetScriptUncertain(fullAssetID crypto.Digest, scr assetID = proto.AssetIDFromDigest(fullAssetID) assetIDTail = proto.DigestTail(fullAssetID) ) - dbItem, err := newScriptDBItem(pk, script) + dbItem, err := newAccountScriptDBItem(pk, script) if err != nil { return errors.Wrapf(err, "failed to set uncertain asset script for asset %q with pk %q", fullAssetID.String(), pk.String(), @@ -263,7 +297,7 @@ func (ss *scriptsStorage) setAssetScriptUncertain(fullAssetID crypto.Digest, scr return nil } -func (ss *scriptsStorage) setAssetScript(fullAssetID crypto.Digest, script proto.Script, pk crypto.PublicKey, blockID proto.BlockID) error { +func (ss *scriptsStorage) setAssetScript(fullAssetID crypto.Digest, script proto.Script, blockID proto.BlockID) error { // NOTE: we use fullAssetID (crypto.Digest) only for state hashes compatibility key := assetScriptKey{assetID: proto.AssetIDFromDigest(fullAssetID)} if ss.calculateHashes { @@ -276,10 +310,10 @@ func (ss *scriptsStorage) setAssetScript(fullAssetID crypto.Digest, script proto return err } } - dbItem, err := newScriptDBItem(pk, script) + dbItem, err := newAssetScriptDBIterm(script) if err != nil { - return errors.Wrapf(err, "failed to set asset script for asset %q with pk %q on block %q", - fullAssetID.String(), pk.String(), blockID.String(), + return errors.Wrapf(err, "failed to set asset script for asset %q with on block %q", + fullAssetID.String(), blockID.String(), ) } return ss.setScript(assetScript, &key, dbItem, blockID) @@ -367,7 +401,7 @@ func (ss *scriptsStorage) setAccountScript(addr proto.WavesAddress, script proto return err } } - dbItem, err := newScriptDBItem(pk, script) + dbItem, err := newAccountScriptDBItem(pk, script) if err != nil { return errors.Wrapf(err, "failed to set account script for account %q with pk %q on block %q", addr.String(), pk.String(), blockID.String(), diff --git a/pkg/state/scripts_storage_interface.go b/pkg/state/scripts_storage_interface.go index 5817a0e8a..1dc04d242 100644 --- a/pkg/state/scripts_storage_interface.go +++ b/pkg/state/scripts_storage_interface.go @@ -11,7 +11,7 @@ type scriptStorageState interface { commitUncertain(blockID proto.BlockID) error dropUncertain() setAssetScriptUncertain(fullAssetID crypto.Digest, script proto.Script, pk crypto.PublicKey) error - setAssetScript(assetID crypto.Digest, script proto.Script, pk crypto.PublicKey, blockID proto.BlockID) error + setAssetScript(assetID crypto.Digest, script proto.Script, blockID proto.BlockID) error newestIsSmartAsset(assetID proto.AssetID) (bool, error) isSmartAsset(assetID proto.AssetID) (bool, error) newestScriptByAsset(assetID proto.AssetID) (*ast.Tree, error) diff --git a/pkg/state/scripts_storage_moq_test.go b/pkg/state/scripts_storage_moq_test.go index 08a4d4084..1949daff9 100644 --- a/pkg/state/scripts_storage_moq_test.go +++ b/pkg/state/scripts_storage_moq_test.go @@ -98,7 +98,7 @@ var _ scriptStorageState = &mockScriptStorageState{} // setAccountScriptFunc: func(addr proto.WavesAddress, script proto.Script, pk crypto.PublicKey, blockID proto.BlockID) error { // panic("mock out the setAccountScript method") // }, -// setAssetScriptFunc: func(assetID crypto.Digest, script proto.Script, pk crypto.PublicKey, blockID proto.BlockID) error { +// setAssetScriptFunc: func(assetID crypto.Digest, script proto.Script, blockID proto.BlockID) error { // panic("mock out the setAssetScript method") // }, // setAssetScriptUncertainFunc: func(fullAssetID crypto.Digest, script proto.Script, pk crypto.PublicKey) error { @@ -190,7 +190,7 @@ type mockScriptStorageState struct { setAccountScriptFunc func(addr proto.WavesAddress, script proto.Script, pk crypto.PublicKey, blockID proto.BlockID) error // setAssetScriptFunc mocks the setAssetScript method. - setAssetScriptFunc func(assetID crypto.Digest, script proto.Script, pk crypto.PublicKey, blockID proto.BlockID) error + setAssetScriptFunc func(assetID crypto.Digest, script proto.Script, blockID proto.BlockID) error // setAssetScriptUncertainFunc mocks the setAssetScriptUncertain method. setAssetScriptUncertainFunc func(fullAssetID crypto.Digest, script proto.Script, pk crypto.PublicKey) error @@ -327,8 +327,6 @@ type mockScriptStorageState struct { AssetID crypto.Digest // Script is the script argument value. Script proto.Script - // Pk is the pk argument value. - Pk crypto.PublicKey // BlockID is the blockID argument value. BlockID proto.BlockID } @@ -1187,25 +1185,23 @@ func (mock *mockScriptStorageState) setAccountScriptCalls() []struct { } // setAssetScript calls setAssetScriptFunc. -func (mock *mockScriptStorageState) setAssetScript(assetID crypto.Digest, script proto.Script, pk crypto.PublicKey, blockID proto.BlockID) error { +func (mock *mockScriptStorageState) setAssetScript(assetID crypto.Digest, script proto.Script, blockID proto.BlockID) error { if mock.setAssetScriptFunc == nil { panic("mockScriptStorageState.setAssetScriptFunc: method is nil but scriptStorageState.setAssetScript was just called") } callInfo := struct { AssetID crypto.Digest Script proto.Script - Pk crypto.PublicKey BlockID proto.BlockID }{ AssetID: assetID, Script: script, - Pk: pk, BlockID: blockID, } mock.locksetAssetScript.Lock() mock.calls.setAssetScript = append(mock.calls.setAssetScript, callInfo) mock.locksetAssetScript.Unlock() - return mock.setAssetScriptFunc(assetID, script, pk, blockID) + return mock.setAssetScriptFunc(assetID, script, blockID) } // setAssetScriptCalls gets all the calls that were made to setAssetScript. @@ -1215,13 +1211,11 @@ func (mock *mockScriptStorageState) setAssetScript(assetID crypto.Digest, script func (mock *mockScriptStorageState) setAssetScriptCalls() []struct { AssetID crypto.Digest Script proto.Script - Pk crypto.PublicKey BlockID proto.BlockID } { var calls []struct { AssetID crypto.Digest Script proto.Script - Pk crypto.PublicKey BlockID proto.BlockID } mock.locksetAssetScript.RLock() diff --git a/pkg/state/scripts_storage_test.go b/pkg/state/scripts_storage_test.go index bbf157db5..23be0f013 100644 --- a/pkg/state/scripts_storage_test.go +++ b/pkg/state/scripts_storage_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/wavesplatform/gowaves/pkg/proto" ) @@ -129,7 +130,7 @@ func TestSetAssetScript(t *testing.T) { fullAssetID := testGlobal.asset0.asset.ID shortAssetID := proto.AssetIDFromDigest(fullAssetID) - err := to.scriptsStorage.setAssetScript(fullAssetID, testGlobal.scriptBytes, testGlobal.senderInfo.pk, blockID0) + err := to.scriptsStorage.setAssetScript(fullAssetID, testGlobal.scriptBytes, blockID0) assert.NoError(t, err, "setAssetScript() failed") // Test newest before flushing. @@ -166,7 +167,7 @@ func TestSetAssetScript(t *testing.T) { assert.Equal(t, testGlobal.scriptAst, scriptAst) // Test discarding script. - err = to.scriptsStorage.setAssetScript(fullAssetID, proto.Script{}, testGlobal.senderInfo.pk, blockID0) + err = to.scriptsStorage.setAssetScript(fullAssetID, proto.Script{}, blockID0) assert.NoError(t, err, "setAssetScript() failed") // Test newest before flushing. diff --git a/pkg/state/snapshot_applier.go b/pkg/state/snapshot_applier.go index 1fb25cc0a..339bebeeb 100644 --- a/pkg/state/snapshot_applier.go +++ b/pkg/state/snapshot_applier.go @@ -2,9 +2,9 @@ package state import ( "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/ride" - "github.com/wavesplatform/gowaves/pkg/ride/serialization" ) type blockSnapshotsApplier struct { @@ -46,7 +46,7 @@ func newSnapshotApplierStorages(stor *blockchainEntitiesStorage) snapshotApplier } } -var _ = SnapshotApplier((*blockSnapshotsApplier)(nil)) +var _ = proto.SnapshotApplier((*blockSnapshotsApplier)(nil)) type blockSnapshotsApplierInfo struct { ci *checkerInfo @@ -54,16 +54,6 @@ type blockSnapshotsApplierInfo struct { stateActionsCounter *proto.StateActionsCounter } -var _ = newBlockSnapshotsApplierInfo - -func newBlockSnapshotsApplierInfo(ci *checkerInfo, scheme proto.Scheme, cnt *proto.StateActionsCounter) blockSnapshotsApplierInfo { - return blockSnapshotsApplierInfo{ - ci: ci, - scheme: scheme, - stateActionsCounter: cnt, - } -} - func (s blockSnapshotsApplierInfo) BlockID() proto.BlockID { return s.ci.blockID } @@ -84,7 +74,7 @@ func (s blockSnapshotsApplierInfo) StateActionsCounter() *proto.StateActionsCoun return s.stateActionsCounter } -func (a *blockSnapshotsApplier) ApplyWavesBalance(snapshot WavesBalanceSnapshot) error { +func (a *blockSnapshotsApplier) ApplyWavesBalance(snapshot proto.WavesBalanceSnapshot) error { addrID := snapshot.Address.ID() profile, err := a.stor.balances.wavesBalance(addrID) if err != nil { @@ -93,14 +83,15 @@ func (a *blockSnapshotsApplier) ApplyWavesBalance(snapshot WavesBalanceSnapshot) newProfile := profile newProfile.balance = snapshot.Balance value := newWavesValue(profile, newProfile) - if err := a.stor.balances.setWavesBalance(addrID, value, a.info.BlockID()); err != nil { + if err = a.stor.balances.setWavesBalance(addrID, value, a.info.BlockID()); err != nil { return errors.Wrapf(err, "failed to get set balance profile for address %q", snapshot.Address.String()) } return nil } -func (a *blockSnapshotsApplier) ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) error { +func (a *blockSnapshotsApplier) ApplyLeaseBalance(snapshot proto.LeaseBalanceSnapshot) error { addrID := snapshot.Address.ID() + var err error profile, err := a.stor.balances.wavesBalance(addrID) if err != nil { return errors.Wrapf(err, "failed to get waves balance profile for address %q", snapshot.Address.String()) @@ -109,38 +100,44 @@ func (a *blockSnapshotsApplier) ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) newProfile.leaseIn = int64(snapshot.LeaseIn) newProfile.leaseOut = int64(snapshot.LeaseOut) value := newWavesValue(profile, newProfile) - if err := a.stor.balances.setWavesBalance(addrID, value, a.info.BlockID()); err != nil { + if err = a.stor.balances.setWavesBalance(addrID, value, a.info.BlockID()); err != nil { return errors.Wrapf(err, "failed to get set balance profile for address %q", snapshot.Address.String()) } return nil } -func (a *blockSnapshotsApplier) ApplyAssetBalance(snapshot AssetBalanceSnapshot) error { +func (a *blockSnapshotsApplier) ApplyAssetBalance(snapshot proto.AssetBalanceSnapshot) error { addrID := snapshot.Address.ID() assetID := proto.AssetIDFromDigest(snapshot.AssetID) return a.stor.balances.setAssetBalance(addrID, assetID, snapshot.Balance, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyAlias(snapshot AliasSnapshot) error { +func (a *blockSnapshotsApplier) ApplyAlias(snapshot proto.AliasSnapshot) error { return a.stor.aliases.createAlias(snapshot.Alias.Alias, snapshot.Address, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyStaticAssetInfo(snapshot StaticAssetInfoSnapshot) error { +func (a *blockSnapshotsApplier) ApplyStaticAssetInfo(snapshot proto.StaticAssetInfoSnapshot) error { assetID := proto.AssetIDFromDigest(snapshot.AssetID) + height := a.info.Height() + 1 + + changeableInfo, err := a.stor.assets.newestChangeableInfo(snapshot.AssetID) + if err != nil { + changeableInfo = &assetChangeableInfo{} + } assetFullInfo := &assetInfo{ assetConstInfo: assetConstInfo{ tail: proto.DigestTail(snapshot.AssetID), issuer: snapshot.IssuerPublicKey, decimals: snapshot.Decimals, - issueHeight: a.info.Height(), + issueHeight: height, issueSequenceInBlock: a.info.StateActionsCounter().NextIssueActionNumber(), }, - assetChangeableInfo: assetChangeableInfo{}, + assetChangeableInfo: *changeableInfo, } return a.stor.assets.issueAsset(assetID, assetFullInfo, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyAssetDescription(snapshot AssetDescriptionSnapshot) error { +func (a *blockSnapshotsApplier) ApplyAssetDescription(snapshot proto.AssetDescriptionSnapshot) error { change := &assetInfoChange{ newName: snapshot.AssetName, newDescription: snapshot.AssetDescription, @@ -149,7 +146,7 @@ func (a *blockSnapshotsApplier) ApplyAssetDescription(snapshot AssetDescriptionS return a.stor.assets.updateAssetInfo(snapshot.AssetID, change, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyAssetVolume(snapshot AssetVolumeSnapshot) error { +func (a *blockSnapshotsApplier) ApplyAssetVolume(snapshot proto.AssetVolumeSnapshot) error { assetID := proto.AssetIDFromDigest(snapshot.AssetID) assetFullInfo, err := a.stor.assets.newestAssetInfo(assetID) if err != nil { @@ -160,54 +157,60 @@ func (a *blockSnapshotsApplier) ApplyAssetVolume(snapshot AssetVolumeSnapshot) e return a.stor.assets.storeAssetInfo(assetID, assetFullInfo, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyAssetScript(snapshot AssetScriptSnapshot) error { - estimation := ride.TreeEstimation{ // TODO: use uint in TreeEstimation - Estimation: int(snapshot.Complexity), - Verifier: int(snapshot.Complexity), - Functions: nil, - } - if err := a.stor.scriptsComplexity.saveComplexitiesForAsset(snapshot.AssetID, estimation, a.info.BlockID()); err != nil { - return errors.Wrapf(err, "failed to store asset script estimation for asset %q", snapshot.AssetID.String()) - } - constInfo, err := a.stor.assets.newestConstInfo(proto.AssetIDFromDigest(snapshot.AssetID)) // only issuer can set new asset script - if err != nil { - return errors.Wrapf(err, "failed to get const asset info for asset %q", snapshot.AssetID.String()) +func (a *blockSnapshotsApplier) ApplyAssetScript(snapshot proto.AssetScriptSnapshot) error { + if snapshot.Script.IsEmpty() { + return a.stor.scriptsStorage.setAssetScript(snapshot.AssetID, proto.Script{}, + a.info.BlockID()) } - return a.stor.scriptsStorage.setAssetScript(snapshot.AssetID, snapshot.Script, constInfo.issuer, a.info.BlockID()) + return a.stor.scriptsStorage.setAssetScript(snapshot.AssetID, snapshot.Script, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplySponsorship(snapshot SponsorshipSnapshot) error { +func (a *blockSnapshotsApplier) ApplySponsorship(snapshot proto.SponsorshipSnapshot) error { return a.stor.sponsoredAssets.sponsorAsset(snapshot.AssetID, snapshot.MinSponsoredFee, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyAccountScript(snapshot AccountScriptSnapshot) error { +func (a *blockSnapshotsApplier) ApplyAccountScript(snapshot proto.AccountScriptSnapshot) error { addr, err := proto.NewAddressFromPublicKey(a.info.Scheme(), snapshot.SenderPublicKey) if err != nil { return errors.Wrapf(err, "failed to create address from scheme %d and PK %q", a.info.Scheme(), snapshot.SenderPublicKey.String()) } - var estimations treeEstimations - if !snapshot.Script.IsEmpty() { - tree, err := serialization.Parse(snapshot.Script) - if err != nil { - return errors.Wrapf(err, "failed to parse script from account script snapshot for addr %q", addr.String()) - } - estimations, err = makeRideEstimations(tree, a.info.EstimatorVersion(), true) - if err != nil { - return errors.Wrapf(err, "failed to make account script estimations for addr %q", addr.String()) - } + // In case of verifier, there are no functions. If it is a full DApp, + // the complexity 'functions' will be stored through the internal snapshot InternalDAppComplexitySnapshot. + if snapshot.Script.IsEmpty() { + return a.stor.scriptsStorage.setAccountScript(addr, proto.Script{}, + snapshot.SenderPublicKey, a.info.BlockID()) + } + treeEstimation := ride.TreeEstimation{ + Estimation: int(snapshot.VerifierComplexity), + Verifier: int(snapshot.VerifierComplexity), + Functions: nil, + } + if snapshot.Script.IsEmpty() { + return a.stor.scriptsStorage.setAccountScript(addr, snapshot.Script, + snapshot.SenderPublicKey, a.info.BlockID()) } - if err := a.stor.scriptsComplexity.saveComplexitiesForAddr(addr, estimations, a.info.BlockID()); err != nil { - return errors.Wrapf(err, "failed to store account script estimation for addr %q", addr.String()) + setErr := a.stor.scriptsStorage.setAccountScript(addr, snapshot.Script, snapshot.SenderPublicKey, a.info.BlockID()) + if setErr != nil { + return setErr } - return a.stor.scriptsStorage.setAccountScript(addr, snapshot.Script, snapshot.SenderPublicKey, a.info.BlockID()) + scriptEstimation := scriptEstimation{currentEstimatorVersion: a.info.EstimatorVersion(), + scriptIsEmpty: snapshot.Script.IsEmpty(), + estimation: treeEstimation} + if cmplErr := a.stor.scriptsComplexity.saveComplexitiesForAddr( + addr, scriptEstimation, a.info.BlockID()); cmplErr != nil { + return errors.Wrapf(cmplErr, "failed to store account script estimation for addr %q", + addr.String()) + } + return nil } -func (a *blockSnapshotsApplier) ApplyFilledVolumeAndFee(snapshot FilledVolumeFeeSnapshot) error { - return a.stor.ordersVolumes.increaseFilled(snapshot.OrderID.Bytes(), snapshot.FilledVolume, snapshot.FilledFee, a.info.BlockID()) +func (a *blockSnapshotsApplier) ApplyFilledVolumeAndFee(snapshot proto.FilledVolumeFeeSnapshot) error { + return a.stor.ordersVolumes.storeFilled(snapshot.OrderID.Bytes(), + snapshot.FilledVolume, snapshot.FilledFee, a.info.BlockID()) } -func (a *blockSnapshotsApplier) ApplyDataEntries(snapshot DataEntriesSnapshot) error { +func (a *blockSnapshotsApplier) ApplyDataEntries(snapshot proto.DataEntriesSnapshot) error { blockID := a.info.BlockID() for _, entry := range snapshot.DataEntries { if err := a.stor.accountsDataStor.appendEntry(snapshot.Address, entry, blockID); err != nil { @@ -217,7 +220,7 @@ func (a *blockSnapshotsApplier) ApplyDataEntries(snapshot DataEntriesSnapshot) e return nil } -func (a *blockSnapshotsApplier) ApplyLeaseState(snapshot LeaseStateSnapshot) error { +func (a *blockSnapshotsApplier) ApplyLeaseState(snapshot proto.LeaseStateSnapshot) error { l := &leasing{ Sender: snapshot.Sender, Recipient: snapshot.Recipient, @@ -230,3 +233,42 @@ func (a *blockSnapshotsApplier) ApplyLeaseState(snapshot LeaseStateSnapshot) err } return a.stor.leases.addLeasing(snapshot.LeaseID, l, a.info.BlockID()) } + +func (a *blockSnapshotsApplier) ApplyTransactionsStatus(_ proto.TransactionStatusSnapshot) error { + return nil // no-op +} + +func (a *blockSnapshotsApplier) ApplyInternalSnapshot( + internalSnapshot proto.InternalSnapshot) error { + /* If you want to add more internal snapshots, + //you should add a switch here iterating through all possible internal snapshots. */ + internalDappComplexitySnapshot, ok := internalSnapshot.(*InternalDAppComplexitySnapshot) + if !ok { + return errors.New("failed to convert interface to internal dapp complexity snapshot") + } + scriptEstimation := scriptEstimation{currentEstimatorVersion: a.info.EstimatorVersion(), + scriptIsEmpty: internalDappComplexitySnapshot.ScriptIsEmpty, estimation: internalDappComplexitySnapshot.Estimation} + if !internalDappComplexitySnapshot.Update { + // Save full complexity of both callable and verifier when the script is set first time + if setErr := a.stor.scriptsComplexity.saveComplexitiesForAddr(internalDappComplexitySnapshot.ScriptAddress, + scriptEstimation, a.info.BlockID()); setErr != nil { + return errors.Wrapf(setErr, "failed to save script complexities for addr %q", + internalDappComplexitySnapshot.ScriptAddress.String()) + } + return nil + } + + // we've pulled up an old script which estimation had been done by an old estimator + // in txChecker we've estimated script with a new estimator + // this is the place where we have to store new estimation + + // update callable and summary complexity, verifier complexity remains the same + if scErr := a.stor.scriptsComplexity.updateCallableComplexitiesForAddr( + internalDappComplexitySnapshot.ScriptAddress, + scriptEstimation, a.info.BlockID()); scErr != nil { + return errors.Wrapf(scErr, "failed to save complexity for addr %q", + internalDappComplexitySnapshot.ScriptAddress, + ) + } + return nil +} diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index 791c22a0c..c32a75c76 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -1,44 +1,65 @@ package state import ( + "math/big" + "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" - "github.com/wavesplatform/gowaves/pkg/settings" - "math/big" + "github.com/wavesplatform/gowaves/pkg/ride" ) type snapshotGenerator struct { - stor *blockchainEntitiesStorage - settings *settings.BlockchainSettings + stor *blockchainEntitiesStorage + scheme proto.Scheme + + /* Is IsFullNodeMode is true, then some additional internal fields will be generated */ + IsFullNodeMode bool } +type addressWavesBalanceDiff map[proto.WavesAddress]balanceDiff + type assetBalanceDiffKey struct { address proto.WavesAddress asset proto.AssetID } - -type addressWavesBalanceDiff map[proto.WavesAddress]balanceDiff type addressAssetBalanceDiff map[assetBalanceDiffKey]int64 -func (sg *snapshotGenerator) generateSnapshotForGenesisTx(balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } +/* +Below are internal snapshots only. +They are not necessary and used for optimization, initialized in the full node mode only. +*/ +type InternalDAppComplexitySnapshot struct { + ScriptAddress proto.WavesAddress + Estimation ride.TreeEstimation + ScriptIsEmpty bool + Update bool +} + +func (s InternalDAppComplexitySnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s InternalDAppComplexitySnapshot) Apply(a proto.SnapshotApplier) error { + return a.ApplyInternalSnapshot(&s) +} + +func (s InternalDAppComplexitySnapshot) IsInternal() bool { + return true +} + +func (s InternalDAppComplexitySnapshot) InternalSnapshotMarker() {} + +func (sg *snapshotGenerator) generateSnapshotForGenesisTx(balanceChanges txDiff) (proto.TransactionSnapshot, error) { return sg.generateBalancesSnapshot(balanceChanges) } -func (sg *snapshotGenerator) generateSnapshotForPaymentTx(balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } +func (sg *snapshotGenerator) generateSnapshotForPaymentTx(balanceChanges txDiff) (proto.TransactionSnapshot, error) { return sg.generateBalancesSnapshot(balanceChanges) } -func (sg *snapshotGenerator) generateSnapshotForTransferTx(balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } +func (sg *snapshotGenerator) generateSnapshotForTransferTx(balanceChanges txDiff) (proto.TransactionSnapshot, error) { return sg.generateBalancesSnapshot(balanceChanges) } @@ -47,24 +68,23 @@ type scriptInformation struct { complexity int } -func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, txID crypto.Digest, senderPK crypto.PublicKey, assetInfo assetInfo, balanceChanges txDiff, scriptInformation *scriptInformation) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } - var snapshot TransactionSnapshot - // TODO add asset script snapshot - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.settings.AddressSchemeCharacter) +func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, txID crypto.Digest, + senderPK crypto.PublicKey, assetInfo assetInfo, balanceChanges txDiff, + scriptInformation *scriptInformation) (proto.TransactionSnapshot, error) { + var snapshot proto.TransactionSnapshot + addrWavesBalanceDiff, addrAssetBalanceDiff, err := balanceDiffFromTxDiff(balanceChanges, sg.scheme) 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 + // 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 *proto.AssetBalanceSnapshot for key, diffAmount := range addrAssetBalanceDiff { if key.asset == proto.AssetIDFromDigest(assetID) { // remove the element from the array delete(addrAssetBalanceDiff, key) - specialAssetSnapshot = &AssetBalanceSnapshot{ + specialAssetSnapshot = &proto.AssetBalanceSnapshot{ Address: key.address, AssetID: assetID, Balance: uint64(diffAmount), @@ -72,7 +92,7 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t } } - issueStaticInfoSnapshot := &StaticAssetInfoSnapshot{ + issueStaticInfoSnapshot := &proto.StaticAssetInfoSnapshot{ AssetID: assetID, IssuerPublicKey: senderPK, SourceTransactionID: txID, @@ -80,14 +100,14 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t IsNFT: assetInfo.isNFT(), } - assetDescription := &AssetDescriptionSnapshot{ + assetDescription := &proto.AssetDescriptionSnapshot{ AssetID: assetID, AssetName: assetInfo.name, AssetDescription: assetInfo.description, ChangeHeight: assetInfo.lastNameDescChangeHeight, } - assetReissuability := &AssetVolumeSnapshot{ + assetReissuability := &proto.AssetVolumeSnapshot{ AssetID: assetID, IsReissuable: assetInfo.reissuable, TotalQuantity: assetInfo.quantity, @@ -95,16 +115,22 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) - if scriptInformation != nil { - sponsorshipSnapshot := &AssetScriptSnapshot{ - AssetID: assetID, - Script: scriptInformation.script, - Complexity: uint64(scriptInformation.complexity), + if scriptInformation == nil { + assetScriptSnapshot := &proto.AssetScriptSnapshot{ + AssetID: assetID, + Script: proto.Script{}, + } + snapshot = append(snapshot, assetScriptSnapshot) + } else { + assetScriptSnapshot := &proto.AssetScriptSnapshot{ + AssetID: assetID, + Script: scriptInformation.script, } - snapshot = append(snapshot, sponsorshipSnapshot) + // TODO: special snapshot for complexity should be generated here + snapshot = append(snapshot, assetScriptSnapshot) } - - wavesBalancesSnapshot, assetBalancesSnapshot, err := sg.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) + wavesBalancesSnapshot, assetBalancesSnapshot, err := + sg.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -122,10 +148,8 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, change assetReissueChange, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } +func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, + change assetReissueChange, balanceChanges txDiff) (proto.TransactionSnapshot, error) { quantityDiff := big.NewInt(change.diff) assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) if err != nil { @@ -137,7 +161,7 @@ func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } - assetReissuability := &AssetVolumeSnapshot{ + assetReissuability := &proto.AssetVolumeSnapshot{ AssetID: assetID, TotalQuantity: *resQuantity, IsReissuable: change.reissuable, @@ -146,10 +170,8 @@ func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, change assetBurnChange, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } +func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, change assetBurnChange, + balanceChanges txDiff) (proto.TransactionSnapshot, error) { quantityDiff := big.NewInt(change.diff) assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) if err != nil { @@ -161,7 +183,7 @@ func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, ch if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } - assetReissuability := &AssetVolumeSnapshot{ + assetReissuability := &proto.AssetVolumeSnapshot{ AssetID: assetID, TotalQuantity: *resQuantity, IsReissuable: assetInfo.reissuable, @@ -170,10 +192,9 @@ func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, ch return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForExchangeTx(sellOrder proto.Order, sellFee uint64, buyOrder proto.Order, buyFee uint64, volume uint64, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } +func (sg *snapshotGenerator) generateSnapshotForExchangeTx(sellOrder proto.Order, sellFee uint64, + buyOrder proto.Order, buyFee uint64, volume uint64, + balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") @@ -200,17 +221,16 @@ func (sg *snapshotGenerator) generateSnapshotForExchangeTx(sellOrder proto.Order return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForLeaseTx(lease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } +func (sg *snapshotGenerator) generateSnapshotForLeaseTx(lease leasing, leaseID crypto.Digest, + originalTxID crypto.Digest, balanceChanges txDiff) (proto.TransactionSnapshot, error) { var err error snapshot, err := sg.generateBalancesSnapshot(balanceChanges) 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 := sg.generateLeaseAtomicSnapshots(leaseID, lease, originalTxID, lease.Sender, lease.Recipient, amount) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := + sg.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") } @@ -219,22 +239,22 @@ func (sg *snapshotGenerator) generateSnapshotForLeaseTx(lease leasing, leaseID c return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Digest, oldLease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, cancelHeight uint64, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } +func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Digest, oldLease leasing, + leaseID crypto.Digest, originalTxID crypto.Digest, + cancelHeight uint64, balanceChanges txDiff) (proto.TransactionSnapshot, error) { var err error snapshot, err := sg.generateBalancesSnapshot(balanceChanges) 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 := sg.generateLeaseAtomicSnapshots(leaseID, oldLease, originalTxID, oldLease.Sender, oldLease.Recipient, negativeAmount) + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := + sg.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, + leaseStatusSnapshot.Status = proto.LeaseStateStatus{ + Value: proto.LeaseCanceled, CancelHeight: cancelHeight, CancelTransactionID: txID, } @@ -243,15 +263,13 @@ func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Diges return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForCreateAliasTx(senderAddress proto.WavesAddress, alias proto.Alias, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } +func (sg *snapshotGenerator) generateSnapshotForCreateAliasTx(senderAddress proto.WavesAddress, alias proto.Alias, + balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - aliasSnapshot := &AliasSnapshot{ + aliasSnapshot := &proto.AliasSnapshot{ Address: senderAddress, Alias: alias, } @@ -259,22 +277,19 @@ func (sg *snapshotGenerator) generateSnapshotForCreateAliasTx(senderAddress prot return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForMassTransferTx(balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } +func (sg *snapshotGenerator) generateSnapshotForMassTransferTx( + balanceChanges txDiff, +) (proto.TransactionSnapshot, error) { return sg.generateBalancesSnapshot(balanceChanges) } -func (sg *snapshotGenerator) generateSnapshotForDataTx(senderAddress proto.WavesAddress, entries []proto.DataEntry, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } +func (sg *snapshotGenerator) generateSnapshotForDataTx(senderAddress proto.WavesAddress, entries []proto.DataEntry, + balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - dataEntriesSnapshot := &DataEntriesSnapshot{ + dataEntriesSnapshot := &proto.DataEntriesSnapshot{ Address: senderAddress, DataEntries: entries, } @@ -282,15 +297,13 @@ func (sg *snapshotGenerator) generateSnapshotForDataTx(senderAddress proto.Waves return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Digest, minAssetFee uint64, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } +func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Digest, + minAssetFee uint64, balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - sponsorshipSnapshot := &SponsorshipSnapshot{ + sponsorshipSnapshot := &proto.SponsorshipSnapshot{ AssetID: assetID, MinSponsoredFee: minAssetFee, } @@ -298,64 +311,59 @@ func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Dig return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.PublicKey, script proto.Script, complexity int, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } +func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.PublicKey, script proto.Script, + scriptEstimation scriptEstimation, balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - sponsorshipSnapshot := &AccountScriptSnapshot{ + // If the script is empty, it will still be stored in the storage. + accountScriptSnapshot := &proto.AccountScriptSnapshot{ SenderPublicKey: senderPK, Script: script, - VerifierComplexity: uint64(complexity), + VerifierComplexity: uint64(scriptEstimation.estimation.Verifier), } - snapshot = append(snapshot, sponsorshipSnapshot) + + snapshot = append(snapshot, accountScriptSnapshot) + + if sg.IsFullNodeMode { + scriptAddr, cnvrtErr := proto.NewAddressFromPublicKey(sg.scheme, senderPK) + if cnvrtErr != nil { + return nil, errors.Wrap(cnvrtErr, "failed to get sender for InvokeScriptWithProofs") + } + internalComplexitySnapshot := InternalDAppComplexitySnapshot{ + Estimation: scriptEstimation.estimation, ScriptAddress: scriptAddr, + Update: false, ScriptIsEmpty: scriptEstimation.scriptIsEmpty} + snapshot = append(snapshot, &internalComplexitySnapshot) + } + return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, complexity int, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } +func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, + balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - sponsorshipSnapshot := &AssetScriptSnapshot{ - AssetID: assetID, - Script: script, - Complexity: uint64(complexity), + assetScrptSnapshot := &proto.AssetScriptSnapshot{ + AssetID: assetID, + Script: script, } - snapshot = append(snapshot, sponsorshipSnapshot) + // TODO generate a special snapshot complexity here + snapshot = append(snapshot, assetScrptSnapshot) return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { - return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges) -} - -func (sg *snapshotGenerator) generateSnapshotForInvokeExpressionTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { - return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges) -} - -func (sg *snapshotGenerator) generateSnapshotForEthereumInvokeScriptTx(txID crypto.Digest, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { - return sg.generateInvokeSnapshot(txID, info, invocationRes, balanceChanges) -} - -func (sg *snapshotGenerator) generateSnapshotForUpdateAssetInfoTx(assetID crypto.Digest, assetName string, assetDescription string, changeHeight proto.Height, balanceChanges txDiff) (TransactionSnapshot, error) { - if balanceChanges == nil { - return nil, nil - } - +func (sg *snapshotGenerator) generateSnapshotForUpdateAssetInfoTx(assetID crypto.Digest, assetName string, + assetDescription string, changeHeight proto.Height, balanceChanges txDiff) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err } - sponsorshipSnapshot := &AssetDescriptionSnapshot{ + sponsorshipSnapshot := &proto.AssetDescriptionSnapshot{ AssetID: assetID, AssetName: assetName, AssetDescription: assetDescription, @@ -365,233 +373,14 @@ func (sg *snapshotGenerator) generateSnapshotForUpdateAssetInfoTx(assetID crypto return snapshot, nil } -// TODO optimize this -func (sg *snapshotGenerator) generateInvokeSnapshot( - txID crypto.Digest, - info *performerInfo, - invocationRes *invocationResult, - balanceChanges txDiff) (TransactionSnapshot, error) { - - blockHeight := info.height + 1 - - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.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(sg.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(sg.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, sg.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(sg.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, sg.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(sg.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 := sg.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(sg.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 := sg.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(sg.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(sg.settings.AddressSchemeCharacter, *a.Sender) - if err != nil { - return nil, err - } - var recipientAddr proto.WavesAddress - if addr := a.Recipient.Address(); addr == nil { - recipientAddr, err = sg.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 := sg.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 := sg.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 := sg.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 := sg.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 (sg *snapshotGenerator) generateLeaseAtomicSnapshots(leaseID crypto.Digest, l leasing, originalTxID crypto.Digest, - senderAddress proto.WavesAddress, receiverAddress proto.WavesAddress, amount int64) (*LeaseStateSnapshot, *LeaseBalanceSnapshot, *LeaseBalanceSnapshot, error) { - leaseStatusSnapshot := &LeaseStateSnapshot{ +func (sg *snapshotGenerator) generateLeaseAtomicSnapshots(leaseID crypto.Digest, + l leasing, originalTxID crypto.Digest, + senderAddress proto.WavesAddress, + receiverAddress proto.WavesAddress, + amount int64) (*proto.LeaseStateSnapshot, *proto.LeaseBalanceSnapshot, *proto.LeaseBalanceSnapshot, error) { + leaseStatusSnapshot := &proto.LeaseStateSnapshot{ LeaseID: leaseID, - Status: LeaseStateStatus{ + Status: proto.LeaseStateStatus{ Value: l.Status, }, Amount: l.Amount, @@ -605,7 +394,7 @@ func (sg *snapshotGenerator) generateLeaseAtomicSnapshots(leaseID crypto.Digest, if err != nil { return nil, nil, nil, errors.Wrap(err, "failed to receive sender's waves balance") } - senderLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ + senderLeaseBalanceSnapshot := &proto.LeaseBalanceSnapshot{ Address: senderAddress, LeaseIn: uint64(senderBalanceProfile.leaseIn), LeaseOut: uint64(senderBalanceProfile.leaseOut + amount), @@ -615,7 +404,7 @@ func (sg *snapshotGenerator) generateLeaseAtomicSnapshots(leaseID crypto.Digest, if err != nil { return nil, nil, nil, errors.Wrap(err, "failed to receive recipient's waves balance") } - recipientLeaseBalanceSnapshot := &LeaseBalanceSnapshot{ + recipientLeaseBalanceSnapshot := &proto.LeaseBalanceSnapshot{ Address: receiverAddress, LeaseIn: uint64(receiverBalanceProfile.leaseIn + amount), LeaseOut: uint64(receiverBalanceProfile.leaseOut), @@ -624,30 +413,33 @@ func (sg *snapshotGenerator) generateLeaseAtomicSnapshots(leaseID crypto.Digest, return leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, nil } -func (sg *snapshotGenerator) generateOrderAtomicSnapshot(orderID []byte, volume uint64, fee uint64) (*FilledVolumeFeeSnapshot, error) { +func (sg *snapshotGenerator) generateOrderAtomicSnapshot(orderID []byte, + volume uint64, fee uint64) (*proto.FilledVolumeFeeSnapshot, error) { newestFilledAmount, newestFilledFee, err := sg.stor.ordersVolumes.newestFilled(orderID) if err != nil { return nil, err } - orderIdDigset, err := crypto.NewDigestFromBytes(orderID) + 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, + // TODO must be added to newest filled amounts and fee + orderSnapshot := &proto.FilledVolumeFeeSnapshot{ + OrderID: orderIDDigset, FilledFee: newestFilledFee + fee, FilledVolume: newestFilledAmount + volume, } return orderSnapshot, nil } -func (sg *snapshotGenerator) generateBalancesSnapshot(balanceChanges txDiff) (TransactionSnapshot, error) { - var transactionSnapshot TransactionSnapshot - addrWavesBalanceDiff, addrAssetBalanceDiff, err := addressBalanceDiffFromTxDiff(balanceChanges, sg.settings.AddressSchemeCharacter) +func (sg *snapshotGenerator) generateBalancesSnapshot(balanceChanges txDiff) (proto.TransactionSnapshot, error) { + var transactionSnapshot proto.TransactionSnapshot + addrWavesBalanceDiff, addrAssetBalanceDiff, err := balanceDiffFromTxDiff(balanceChanges, sg.scheme) if err != nil { return nil, errors.Wrap(err, "failed to create balance diff from tx diff") } - wavesBalancesSnapshot, assetBalancesSnapshot, err := sg.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) + wavesBalancesSnapshot, assetBalancesSnapshot, err := + sg.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } @@ -660,8 +452,9 @@ func (sg *snapshotGenerator) generateBalancesSnapshot(balanceChanges txDiff) (Tr return transactionSnapshot, nil } -func (sg *snapshotGenerator) generateBalancesAtomicSnapshots(addrWavesBalanceDiff addressWavesBalanceDiff, addrAssetBalanceDiff addressAssetBalanceDiff) ([]WavesBalanceSnapshot, []AssetBalanceSnapshot, error) { - wavesBalanceSnapshot, err := sg.constructWavesBalanceSnapshotFromDiff(addrWavesBalanceDiff) +func (sg *snapshotGenerator) generateBalancesAtomicSnapshots(addrWavesBalanceDiff addressWavesBalanceDiff, + addrAssetBalanceDiff addressAssetBalanceDiff) ([]proto.WavesBalanceSnapshot, []proto.AssetBalanceSnapshot, error) { + wavesBalanceSnapshot, err := sg.wavesBalanceSnapshotFromBalanceDiff(addrWavesBalanceDiff) if err != nil { return nil, nil, errors.Wrap(err, "failed to construct waves balance snapshot") } @@ -669,29 +462,30 @@ func (sg *snapshotGenerator) generateBalancesAtomicSnapshots(addrWavesBalanceDif return wavesBalanceSnapshot, nil, nil } - assetBalanceSnapshot, err := sg.constructAssetBalanceSnapshotFromDiff(addrAssetBalanceDiff) + assetBalanceSnapshot, err := sg.assetBalanceSnapshotFromBalanceDiff(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) { +func balanceDiffFromTxDiff(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)) + var address proto.WavesAddress if err != nil { + // if the waves balance unmarshal failed, try to marshal into asset balance, and if it fails, then return the error assetBalanceKey := &assetBalanceKey{} - err := assetBalanceKey.unmarshal([]byte(balanceKeyString)) + 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) + address, err = assetBalanceKey.address.ToWavesAddress(scheme) if err != nil { return nil, nil, errors.Wrap(err, "failed to convert address id to waves address") } @@ -699,12 +493,12 @@ func addressBalanceDiffFromTxDiff(diff txDiff, scheme proto.Scheme) (addressWave addrAssetBalanceDiff[assetBalKey] = diffAmount.balance continue } - address, err := wavesBalanceKey.address.ToWavesAddress(scheme) + 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 the waves balance diff is 0, it means it did not change. + // The reason for the 0 diff to exist is because of how LeaseIn and LeaseOut are handled in transaction differ. if diffAmount.balance == 0 { continue } @@ -714,17 +508,17 @@ func addressBalanceDiffFromTxDiff(diff txDiff, scheme proto.Scheme) (addressWave } // from txDiff and fees. no validation needed at this point. -func (sg *snapshotGenerator) constructWavesBalanceSnapshotFromDiff(diff addressWavesBalanceDiff) ([]WavesBalanceSnapshot, error) { - var wavesBalances []WavesBalanceSnapshot +func (sg *snapshotGenerator) wavesBalanceSnapshotFromBalanceDiff( + diff addressWavesBalanceDiff) ([]proto.WavesBalanceSnapshot, error) { + var wavesBalances []proto.WavesBalanceSnapshot // add miner address to the diff for wavesAddress, diffAmount := range diff { - fullBalance, err := sg.stor.balances.newestWavesBalance(wavesAddress.ID()) if err != nil { return nil, errors.Wrap(err, "failed to receive sender's waves balance") } - newBalance := WavesBalanceSnapshot{ + newBalance := proto.WavesBalanceSnapshot{ Address: wavesAddress, Balance: uint64(int64(fullBalance.balance) + diffAmount.balance), } @@ -733,8 +527,9 @@ func (sg *snapshotGenerator) constructWavesBalanceSnapshotFromDiff(diff addressW return wavesBalances, nil } -func (sg *snapshotGenerator) constructAssetBalanceSnapshotFromDiff(diff addressAssetBalanceDiff) ([]AssetBalanceSnapshot, error) { - var assetBalances []AssetBalanceSnapshot +func (sg *snapshotGenerator) assetBalanceSnapshotFromBalanceDiff( + diff addressAssetBalanceDiff) ([]proto.AssetBalanceSnapshot, error) { + var assetBalances []proto.AssetBalanceSnapshot // add miner address to the diff for key, diffAmount := range diff { @@ -747,7 +542,7 @@ func (sg *snapshotGenerator) constructAssetBalanceSnapshotFromDiff(diff addressA return nil, errors.Wrap(err, "failed to get newest asset info") } - newBalance := AssetBalanceSnapshot{ + newBalance := proto.AssetBalanceSnapshot{ Address: key.address, AssetID: key.asset.Digest(assetInfo.tail), Balance: uint64(int64(balance) + diffAmount), diff --git a/pkg/state/snapshot_generator_internal_test.go b/pkg/state/snapshot_generator_internal_test.go new file mode 100644 index 000000000..3cc227b83 --- /dev/null +++ b/pkg/state/snapshot_generator_internal_test.go @@ -0,0 +1,1492 @@ +package state + +import ( + "encoding/base64" + "encoding/json" + "math/big" + "sort" + "testing" + + "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/settings" +) + +func defaultAssetInfoTransfer(tail [12]byte, reissuable bool, + amount int64, issuer crypto.PublicKey, + name string) *assetInfo { + return &assetInfo{ + assetConstInfo: assetConstInfo{ + tail: tail, + issuer: issuer, + decimals: 2, + }, + assetChangeableInfo: assetChangeableInfo{ + quantity: *big.NewInt(amount), + name: name, + description: "description", + lastNameDescChangeHeight: 1, + reissuable: reissuable, + }, + } +} + +func defaultPerformerInfoWithChecker(checkerData txCheckerData) *performerInfo { + return &performerInfo{0, blockID0, proto.WavesAddress{}, checkerData} +} + +func customCheckerInfo() *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, differ *differTestObjects) *checkerTestObjects { + tc, err := newTransactionChecker(proto.NewBlockIDFromSignature(genSig), differ.stor.entities, settings.MainNetSettings) + require.NoError(t, err, "newTransactionChecker() failed") + return &checkerTestObjects{differ.stor, tc, differ.tp, differ.stateActionsCounter} +} + +func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) + + 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{changes: ch, checkerData: txCheckerData{}} + transactionSnapshot, err := to.tp.performTransferWithSig(tx, + defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + assert.NoError(t, err, "failed to perform transfer tx") + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + Balance: 299700000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.recipientInfo.addr, + Balance: 200000, + }, + } + + var snapshotI []byte + var snapshotJ []byte + 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) +} + +// TODO send only txBalanceChanges to perfomer + +func TestDefaultIssueTransactionSnapshot(t *testing.T) { + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) + + 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.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()) + assert.NoError(t, err, "createDiffIssueWithSig() failed") + applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} + transactionSnapshot, err := to.tp.performIssueWithSig(tx, + defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + assert.NoError(t, err, "failed to perform issue tx") + + expectedSnapshot := proto.TransactionSnapshot{ + &proto.StaticAssetInfoSnapshot{ + AssetID: *tx.ID, + SourceTransactionID: *tx.ID, + IssuerPublicKey: testGlobal.issuerInfo.pk, + Decimals: defaultDecimals, + IsNFT: false}, + &proto.AssetDescriptionSnapshot{ + AssetID: *tx.ID, + AssetName: "asset0", + AssetDescription: "description", + ChangeHeight: 1, + }, + &proto.AssetVolumeSnapshot{ + AssetID: *tx.ID, + TotalQuantity: *big.NewInt(int64(defaultQuantity)), + IsReissuable: true, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + Balance: 299900000, + }, + &proto.AssetBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + AssetID: *tx.ID, + Balance: 1000, + }, + &proto.AssetScriptSnapshot{ + AssetID: *tx.ID, + Script: proto.Script{}, + }, + } + + var snapshotI []byte + var snapshotJ []byte + 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 TestDefaultReissueSnapshot(t *testing.T) { + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) + + 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, 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") + 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(1*FeeUnit)) + err = tx.Sign(proto.TestNetScheme, testGlobal.issuerInfo.sk) + assert.NoError(t, err, "failed to sign reissue tx") + + ch, err := to.td.createDiffReissueWithSig(tx, defaultDifferInfo()) + assert.NoError(t, err, "createDiffReissueWithSig() failed") + applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} + transactionSnapshot, err := to.tp.performReissueWithSig(tx, + defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + assert.NoError(t, err, "failed to perform reissue tx") + + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + Balance: 299900000, + }, + &proto.AssetBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 1050, + }, + &proto.AssetVolumeSnapshot{ + AssetID: testGlobal.asset0.assetID, + TotalQuantity: *big.NewInt(int64(defaultQuantity + 50)), + IsReissuable: false, + }, + } + + var snapshotI []byte + var snapshotJ []byte + 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 TestDefaultBurnSnapshot(t *testing.T) { + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) + + 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), + false, 950, 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") + 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(1*FeeUnit)) + err = tx.Sign(proto.TestNetScheme, testGlobal.issuerInfo.sk) + assert.NoError(t, err, "failed to sign burn tx") + ch, err := to.td.createDiffBurnWithSig(tx, defaultDifferInfo()) + assert.NoError(t, err, "createDiffBurnWithSig() failed") + applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} + transactionSnapshot, err := to.tp.performBurnWithSig(tx, + defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + assert.NoError(t, err, "failed to perform burn tx") + + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + Balance: 299900000, + }, + &proto.AssetBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 950, + }, + &proto.AssetVolumeSnapshot{ + AssetID: testGlobal.asset0.assetID, + TotalQuantity: *big.NewInt(int64(defaultQuantity - 100)), + IsReissuable: false, + }, + } + + var snapshotI []byte + var snapshotJ []byte + 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 TestDefaultExchangeTransaction(t *testing.T) { + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) + + 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{changes: ch, checkerData: txCheckerData{}} + transactionSnapshot, err := to.tp.performExchange(tx, defaultPerformerInfo(to.stateActionsCounter), + nil, applicationRes.changes.diff) + assert.NoError(t, err, "failed to perform burn tx") + + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299999999, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.recipientInfo.addr, + Balance: 599999998, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.matcherInfo.addr, + Balance: 899900003, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.AssetBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 10, + }, + &proto.AssetBalanceSnapshot{ + Address: testGlobal.recipientInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 590, + }, + &proto.AssetBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + AssetID: testGlobal.asset1.assetID, + Balance: 400, + }, + &proto.AssetBalanceSnapshot{ + Address: testGlobal.recipientInfo.addr, + AssetID: testGlobal.asset1.assetID, + Balance: 100, + }, + &proto.FilledVolumeFeeSnapshot{ + OrderID: *bo.ID, + FilledVolume: 10, + FilledFee: 1, + }, + &proto.FilledVolumeFeeSnapshot{ + OrderID: *so.ID, + FilledVolume: 10, + FilledFee: 2, + }, + } + + var snapshotI []byte + var snapshotJ []byte + 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) { + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) + + 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{changes: ch, checkerData: txCheckerData{}} + transactionSnapshot, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), + nil, applicationRes.changes.diff) + assert.NoError(t, err, "failed to perform burn tx") + + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &proto.LeaseStateSnapshot{ + LeaseID: *tx.ID, + Status: proto.LeaseStateStatus{ + Value: proto.LeaseActive, + }, + Amount: 50, + Sender: testGlobal.senderInfo.addr, + Recipient: testGlobal.recipientInfo.addr, + OriginTransactionID: tx.ID, + Height: 0, + }, + &proto.LeaseBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + LeaseIn: 0, + LeaseOut: 50, + }, + &proto.LeaseBalanceSnapshot{ + Address: testGlobal.recipientInfo.addr, + LeaseIn: 50, + LeaseOut: 0, + }, + } + + var snapshotI []byte + var snapshotJ []byte + 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) { + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) + + 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: proto.LeaseActive, + 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{changes: ch, checkerData: txCheckerData{}} + transactionSnapshot, err := to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), + nil, applicationRes.changes.diff) + assert.NoError(t, err, "failed to perform burn tx") + + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &proto.LeaseStateSnapshot{ + LeaseID: leaseID, + Status: proto.LeaseStateStatus{ + Value: proto.LeaseCanceled, + CancelHeight: 0, + CancelTransactionID: tx.ID, + }, + Amount: 50, + Sender: testGlobal.senderInfo.addr, + Recipient: testGlobal.recipientInfo.addr, + OriginTransactionID: &leaseID, + Height: 1, + }, + &proto.LeaseBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + LeaseIn: 0, + LeaseOut: 0, + }, + &proto.LeaseBalanceSnapshot{ + Address: testGlobal.recipientInfo.addr, + LeaseIn: 0, + LeaseOut: 0, + }, + } + var snapshotI []byte + var snapshotJ []byte + 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) { + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) + + 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{changes: ch, checkerData: txCheckerData{}} + transactionSnapshot, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), + nil, applicationRes.changes.diff) + assert.NoError(t, err, "failed to perform burn tx") + + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &proto.AliasSnapshot{ + Address: testGlobal.senderInfo.addr, + Alias: *proto.NewAlias(proto.TestNetScheme, "aliasForSender"), + }, + } + + var snapshotI []byte + var snapshotJ []byte + 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 TestDefaultDataSnapshot(t *testing.T) { + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) + + 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{changes: ch, checkerData: txCheckerData{}} + transactionSnapshot, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), + nil, applicationRes.changes.diff) + assert.NoError(t, err, "failed to perform burn tx") + + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &proto.DataEntriesSnapshot{ + Address: testGlobal.senderInfo.addr, + DataEntries: []proto.DataEntry{&proto.StringDataEntry{Key: "key_str", Value: "value_str"}, + &proto.IntegerDataEntry{Key: "key_int", Value: 2}}, + }, + } + + var snapshotI []byte + var snapshotJ []byte + 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) { + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) + + 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{changes: ch, checkerData: txCheckerData{}} + transactionSnapshot, err := to.tp.performSponsorshipWithProofs(tx, + defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) + assert.NoError(t, err, "failed to perform burn tx") + + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &proto.SponsorshipSnapshot{ + AssetID: testGlobal.asset0.assetID, + MinSponsoredFee: 500000, + }, + } + + var snapshotI []byte + var snapshotJ []byte + 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 TestDefaultSetDappScriptSnapshot(t *testing.T) { + /* + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + @Callable(i) + func call() = { + [ + BooleanEntry("bool", true), + IntegerEntry("int", 1), + IntegerEntry("int", 1), + IntegerEntry("int2", 2), + StringEntry("str", "1"), + StringEntry("str", "1"), + StringEntry("str2", "2") + ] + } + */ + script := "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAAEY2Fsb" + + "AAAAAAJAARMAAAAAgkBAAAADEJvb2xlYW5FbnRyeQAAAAICAAAABGJvb2wGCQAE" + + "TAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAANpbnQAAAAAAAAAAAEJAARMAAAA" + + "AgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2ludAAAAAAAAAAAAQkABEwAAAACCQEAAA" + + "AMSW50ZWdlckVudHJ5AAAAAgIAAAAEaW50MgAAAAAAAAAAAgkABEwAAAACCQEAAAALU3RyaW5nRW" + + "50cnkAAAACAgAAAANzdHICAAAAATEJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgIAAAADc3RyAgAAAA" + + "ExCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAICAAAABHN0cjICAAAAATIFAAAAA25pbAAAAACkN9Gf" + scriptsBytes, err := base64.StdEncoding.DecodeString(script) + + assert.NoError(t, err, "failed to set decode base64 script") + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) + + to.stor.addBlock(t, blockID0) + to.stor.activateFeature(t, int16(settings.NG)) + to.stor.activateFeature(t, int16(settings.RideV5)) + 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, + scriptsBytes, 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) + co.stor = to.stor + checkerData, 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{changes: ch, checkerData: txCheckerData{}} + transactionSnapshot, err := to.tp.performSetScriptWithProofs(tx, + defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) + assert.NoError(t, err, "failed to perform burn tx") + + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &proto.AccountScriptSnapshot{ + SenderPublicKey: testGlobal.senderInfo.pk, + Script: scriptsBytes, + VerifierComplexity: 0, + }, + &InternalDAppComplexitySnapshot{ + ScriptAddress: testGlobal.senderInfo.addr, + Estimation: ride.TreeEstimation{Estimation: 36, Verifier: 0, Functions: map[string]int{"call": 36}}, + ScriptIsEmpty: false, + Update: false, + }, + } + + var snapshotI []byte + var snapshotJ []byte + 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) { + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) + + 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) + co.stor = to.stor + checkerData, 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{changes: ch, checkerData: txCheckerData{}} + transactionSnapshot, err := to.tp.performSetScriptWithProofs(tx, + defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) + assert.NoError(t, err, "failed to perform burn tx") + + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &proto.AccountScriptSnapshot{ + SenderPublicKey: testGlobal.senderInfo.pk, + Script: testGlobal.scriptBytes, + VerifierComplexity: 340, + }, + &InternalDAppComplexitySnapshot{ + ScriptAddress: testGlobal.senderInfo.addr, + Estimation: ride.TreeEstimation{Estimation: 340, Verifier: 340}, + Update: false, + }, + } + + var snapshotI []byte + var snapshotJ []byte + 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 TestDefaultSetEmptyScriptSnapshot(t *testing.T) { + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) + + 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, + nil, 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) + co.stor = to.stor + checkerData, 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{changes: ch, checkerData: txCheckerData{}} + transactionSnapshot, err := to.tp.performSetScriptWithProofs(tx, + defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) + assert.NoError(t, err, "failed to perform burn tx") + + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &proto.AccountScriptSnapshot{ + SenderPublicKey: testGlobal.senderInfo.pk, + Script: nil, + VerifierComplexity: 0, + }, + &InternalDAppComplexitySnapshot{ + ScriptAddress: testGlobal.senderInfo.addr, + Estimation: ride.TreeEstimation{Estimation: 0, Verifier: 0}, + Update: false, + ScriptIsEmpty: true, + }, + } + + var snapshotI []byte + var snapshotJ []byte + 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) { + checkerInfo := customCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) + + to.stor.addBlock(t, blockID0) + to.stor.activateFeature(t, int16(settings.NG)) + var err error + 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, 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) + co.stor = to.stor + checkerData, 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{changes: ch, checkerData: txCheckerData{}} + transactionSnapshot, err := to.tp.performSetAssetScriptWithProofs(tx, + defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) + assert.NoError(t, err, "failed to perform burn tx") + + expectedSnapshot := proto.TransactionSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + + &proto.AssetScriptSnapshot{ + AssetID: testGlobal.asset0.assetID, + Script: testGlobal.scriptBytes, + }, + } + + var snapshotI []byte + var snapshotJ []byte + 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 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) +// scriptEst := scriptEstimation{currentEstimatorVersion: 1, scriptIsEmpty: false, estimation: estimation} +// err = to.stor.entities.scriptsComplexity.saveComplexitiesForAddr(addr, +// scriptEst, 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 := "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAAEY2FsbAAAAAAJAARMAAAAAgkBAAAA" + +// "DEJvb2xlYW5FbnRyeQAAAAICAAAABGJvb2wGCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAAN" + +// "pbnQAAAAAAAAAAAEJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgIAAAADc3RyAgAAAAAFAAAAA25pbAAAAADr9Rv/" +// scriptsBytes, err := base64.StdEncoding.DecodeString(script) +// assert.NoError(t, err, "failed to set decode base64 script") +// +// checkerInfo := customCheckerInfo() +// to := createDifferTestObjects(t, checkerInfo) +// +// 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) +// co.stor = to.stor +// checkerData, 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} +// +// applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} +// transactionSnapshot, err := to.tp.performInvokeScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerData), +// invocationResult, applicationRes.changes.diff) +// assert.NoError(t, err, "failed to perform invoke script tx") +// +// expectedSnapshot := proto.TransactionSnapshot{ +// &proto.WavesBalanceSnapshot{ +// Address: testGlobal.minerInfo.addr, +// Balance: 200000, +// }, +// &proto.WavesBalanceSnapshot{ +// Address: testGlobal.senderInfo.addr, +// Balance: 299500000, +// }, +// &proto.DataEntriesSnapshot{ +// Address: testGlobal.recipientInfo.addr, +// DataEntries: []proto.DataEntry{ +// &proto.BooleanDataEntry{Key: "bool", Value: true}, +// &proto.StringDataEntry{Key: "int", Value: ""}, // IntegerEntry("int", 1) - will be overwritten +// }, +// }, +// &InternalDAppComplexitySnapshot{ +// ScriptAddress: testGlobal.recipientInfo.addr, +// Estimation: ride.TreeEstimation{ +// Estimation: 16, +// Verifier: 0, +// Functions: map[string]int{"call": 16}, +// }, +// Update: true, +// }, +// } +// +// var expectedDataEntrySnapshot proto.DataEntriesSnapshot +// idxExpectedDataSnapshot := 0 +// for idx, atomicSnapshot := range expectedSnapshot { +// if dataEntryS, ok := atomicSnapshot.(*proto.DataEntriesSnapshot); ok { +// idxExpectedDataSnapshot = idx +// expectedDataEntrySnapshot = *dataEntryS +// } +// } +// var transactionDataEntrySnapshot proto.DataEntriesSnapshot +// idxDataSnapshot := 0 +// for idx, atomicSnapshot := range transactionSnapshot { +// if dataEntryS, ok := atomicSnapshot.(*proto.DataEntriesSnapshot); ok { +// idxDataSnapshot = idx +// transactionDataEntrySnapshot = *dataEntryS +// } +// } +// var snapshotI []byte +// var snapshotJ []byte +// sort.Slice(expectedDataEntrySnapshot.DataEntries, func(i, j int) bool { +// snapshotI, err = json.Marshal(expectedDataEntrySnapshot.DataEntries[i]) +// assert.NoError(t, err, "failed to marshal snapshots") +// snapshotJ, err = json.Marshal(expectedDataEntrySnapshot.DataEntries[j]) +// assert.NoError(t, err, "failed to marshal snapshots") +// return string(snapshotI) < string(snapshotJ) +// }) +// +// sort.Slice(transactionDataEntrySnapshot.DataEntries, func(i, j int) bool { +// snapshotI, err = json.Marshal(transactionDataEntrySnapshot.DataEntries[i]) +// assert.NoError(t, err, "failed to marshal snapshots") +// snapshotJ, err = json.Marshal(transactionDataEntrySnapshot.DataEntries[j]) +// assert.NoError(t, err, "failed to marshal snapshots") +// return string(snapshotI) < string(snapshotJ) +// }) +// +// assert.Equal(t, expectedDataEntrySnapshot, transactionDataEntrySnapshot) +// +// expectedSnapshot = remove(expectedSnapshot, idxExpectedDataSnapshot) +// transactionSnapshot = remove(transactionSnapshot, idxDataSnapshot) +// +// 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 TestDefaultInvokeScriptRepeatableActionsSnapshot(t *testing.T) { +// /* +// {-# STDLIB_VERSION 5 #-} +// {-# CONTENT_TYPE DAPP #-} +// {-# SCRIPT_TYPE ACCOUNT #-} +// +// @Callable(i) +// func call() = { +// [ +// BooleanEntry("bool", true), +// IntegerEntry("int", 1), +// IntegerEntry("int", 1), +// IntegerEntry("int2", 2), +// StringEntry("str", "1"), +// StringEntry("str", "1"), +// StringEntry("str2", "2") +// ] +// } +// */ +// script := "AAIFAAAAAAAAAAQIAhIAAAAAAAAAAAEAAAABaQEAAAAEY2Fsb" + +// "AAAAAAJAARMAAAAAgkBAAAADEJvb2xlYW5FbnRyeQAAAAICAAAABGJvb2wGCQAE" + +// "TAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAANpbnQAAAAAAAAAAAEJAARMAAAA" + +// "AgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAA2ludAAAAAAAAAAAAQkABEwAAAACCQEAAA" + +// "AMSW50ZWdlckVudHJ5AAAAAgIAAAAEaW50MgAAAAAAAAAAAgkABEwAAAACCQEAAAALU3RyaW5nRW" + +// "50cnkAAAACAgAAAANzdHICAAAAATEJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgIAAAADc3RyAgAAAA" + +// "ExCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAICAAAABHN0cjICAAAAATIFAAAAA25pbAAAAACkN9Gf" +// scriptsBytes, err := base64.StdEncoding.DecodeString(script) +// assert.NoError(t, err, "failed to set decode base64 script") +// +// checkerInfo := customCheckerInfo() +// to := createDifferTestObjects(t, checkerInfo) +// +// 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) +// co.stor = to.stor +// checkerData, 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.IntegerDataEntry{Key: "int", Value: 1}, +// Sender: &testGlobal.recipientInfo.pk}, +// &proto.DataEntryScriptAction{ +// Entry: &proto.IntegerDataEntry{Key: "int2", Value: 2}, +// Sender: &testGlobal.recipientInfo.pk}, +// &proto.DataEntryScriptAction{ +// Entry: &proto.StringDataEntry{Key: "str", Value: "1"}, +// Sender: &testGlobal.recipientInfo.pk}, +// &proto.DataEntryScriptAction{ +// Entry: &proto.StringDataEntry{Key: "str", Value: "1"}, +// Sender: &testGlobal.recipientInfo.pk}, +// &proto.DataEntryScriptAction{ +// Entry: &proto.StringDataEntry{Key: "str2", Value: "2"}, +// Sender: &testGlobal.recipientInfo.pk}, +// } +// +// invocationResult := &invocationResult{actions: actions} +// +// applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} +// transactionSnapshot, err := to.tp.performInvokeScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerData), +// invocationResult, applicationRes.changes.diff) +// assert.NoError(t, err, "failed to perform invoke script tx") +// +// expectedSnapshot := proto.TransactionSnapshot{ +// &proto.WavesBalanceSnapshot{ +// Address: testGlobal.minerInfo.addr, +// Balance: 200000, +// }, +// &proto.WavesBalanceSnapshot{ +// Address: testGlobal.senderInfo.addr, +// Balance: 299500000, +// }, +// // The order is not deterministic. +// &proto.DataEntriesSnapshot{ +// Address: testGlobal.recipientInfo.addr, +// DataEntries: []proto.DataEntry{ +// &proto.BooleanDataEntry{Key: "bool", Value: true}, +// &proto.IntegerDataEntry{Key: "int", Value: 1}, +// &proto.IntegerDataEntry{Key: "int2", Value: 2}, +// &proto.StringDataEntry{Key: "str", Value: "1"}, +// &proto.StringDataEntry{Key: "str2", Value: "2"}, +// }, +// }, +// &InternalDAppComplexitySnapshot{ +// ScriptAddress: testGlobal.recipientInfo.addr, +// Estimation: ride.TreeEstimation{ +// Estimation: 36, +// Verifier: 0, +// Functions: map[string]int{"call": 36}, +// }, +// Update: true, +// }, +// } +// +// var expectedDataEntrySnapshot proto.DataEntriesSnapshot +// idxExpectedDataSnapshot := 0 +// for idx, atomicSnapshot := range expectedSnapshot { +// if dataEntryS, ok := atomicSnapshot.(*proto.DataEntriesSnapshot); ok { +// idxExpectedDataSnapshot = idx +// expectedDataEntrySnapshot = *dataEntryS +// } +// } +// var transactionDataEntrySnapshot proto.DataEntriesSnapshot +// idxDataSnapshot := 0 +// for idx, atomicSnapshot := range transactionSnapshot { +// if dataEntryS, ok := atomicSnapshot.(*proto.DataEntriesSnapshot); ok { +// idxDataSnapshot = idx +// transactionDataEntrySnapshot = *dataEntryS +// } +// } +// var snapshotI []byte +// var snapshotJ []byte +// sort.Slice(expectedDataEntrySnapshot.DataEntries, func(i, j int) bool { +// snapshotI, err = json.Marshal(expectedDataEntrySnapshot.DataEntries[i]) +// assert.NoError(t, err, "failed to marshal snapshots") +// snapshotJ, err = json.Marshal(expectedDataEntrySnapshot.DataEntries[j]) +// assert.NoError(t, err, "failed to marshal snapshots") +// return string(snapshotI) < string(snapshotJ) +// }) +// +// sort.Slice(transactionDataEntrySnapshot.DataEntries, func(i, j int) bool { +// snapshotI, err = json.Marshal(transactionDataEntrySnapshot.DataEntries[i]) +// assert.NoError(t, err, "failed to marshal snapshots") +// snapshotJ, err = json.Marshal(transactionDataEntrySnapshot.DataEntries[j]) +// assert.NoError(t, err, "failed to marshal snapshots") +// return string(snapshotI) < string(snapshotJ) +// }) +// +// assert.Equal(t, expectedDataEntrySnapshot, transactionDataEntrySnapshot) +// +// expectedSnapshot = remove(expectedSnapshot, idxExpectedDataSnapshot) +// transactionSnapshot = remove(transactionSnapshot, idxDataSnapshot) +// +// 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 remove(slice []proto.AtomicSnapshot, s int) []proto.AtomicSnapshot { +// return append(slice[:s], slice[s+1:]...) +// } diff --git a/pkg/state/snapshot_generator_test.go b/pkg/state/snapshot_generator_test.go deleted file mode 100644 index a652ef035..000000000 --- a/pkg/state/snapshot_generator_test.go +++ /dev/null @@ -1,982 +0,0 @@ -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" - "testing" -) - -func defaultAssetInfoTransfer(tail [12]byte, reissuable bool, amount int64, issuer crypto.PublicKey, name string) *assetInfo { - return &assetInfo{ - assetConstInfo: assetConstInfo{ - tail: tail, - issuer: issuer, - decimals: 2, - }, - assetChangeableInfo: assetChangeableInfo{ - quantity: *big.NewInt(amount), - name: name, - description: "description", - lastNameDescChangeHeight: 1, - reissuable: reissuable, - }, - } -} - -func defaultPerformerInfoWithChecker(checkerData txCheckerData) *performerInfo { - return &performerInfo{0, blockID0, proto.WavesAddress{}, new(proto.StateActionsCounter), checkerData} -} - -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") - snapshotGenerator := &snapshotGenerator{stor: stor.entities, settings: settings.MainNetSettings} - tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) - require.NoError(t, err, "newTransactionPerformer() failed") - return &checkerTestObjects{stor, tc, tp} -} - -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{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performTransferWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) - 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, - }, - } - - 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) -} - -// TODO send only txBalanceChanges to perfomer -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.issuerInfo.addr.ID(), wavesValue{profile: balanceProfile{balance: 1000 * FeeUnit * 3}}, 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()) - assert.NoError(t, err, "createDiffIssueWithSig() failed") - applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) - assert.NoError(t, err, "failed to perform issue tx") - - 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, - }, - } - 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 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), 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") - 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(1*FeeUnit)) - err = tx.Sign(proto.TestNetScheme, testGlobal.issuerInfo.sk) - assert.NoError(t, err, "failed to sign reissue tx") - - ch, err := to.td.createDiffReissueWithSig(tx, defaultDifferInfo()) - assert.NoError(t, err, "createDiffReissueWithSig() failed") - applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) - assert.NoError(t, err, "failed to perform reissue tx") - - 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, - }, - } - - 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 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), 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") - 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(1*FeeUnit)) - err = tx.Sign(proto.TestNetScheme, testGlobal.issuerInfo.sk) - assert.NoError(t, err, "failed to sign burn tx") - ch, err := to.td.createDiffBurnWithSig(tx, defaultDifferInfo()) - assert.NoError(t, err, "createDiffBurnWithSig() failed") - applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) - assert.NoError(t, err, "failed to perform burn tx") - - 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, - }, - } - - 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 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{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performExchange(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) - 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{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) - 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: LeaseStateStatus{ - Value: 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, - 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{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) - 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: LeaseStateStatus{ - Value: LeaseCanceled, - CancelHeight: 0, - CancelTransactionID: tx.ID, - }, - 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{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) - 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) -} - -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{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) - 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{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(), nil, applicationRes.changes.diff) - 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 - checkerData, 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{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performSetScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) - 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 - checkerData, 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{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performSetAssetScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) - 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) -} - -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 - checkerData, 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} - - applicationRes := &applicationResult{changes: ch, checkerData: txCheckerData{}} - transactionSnapshot, err := to.tp.performInvokeScriptWithProofs(tx, defaultPerformerInfoWithChecker(checkerData), invocationResult, applicationRes.changes.diff) - 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) -} diff --git a/pkg/state/snapshot_types.go b/pkg/state/snapshot_types.go deleted file mode 100644 index 6ff55ec17..000000000 --- a/pkg/state/snapshot_types.go +++ /dev/null @@ -1,142 +0,0 @@ -package state - -import ( - "math/big" - - "github.com/wavesplatform/gowaves/pkg/crypto" - "github.com/wavesplatform/gowaves/pkg/proto" -) - -type TransactionSnapshot []AtomicSnapshot - -type AtomicSnapshot interface{ Apply(SnapshotApplier) error } - -type WavesBalanceSnapshot struct { - Address proto.WavesAddress - Balance uint64 -} - -func (s WavesBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyWavesBalance(s) } - -type AssetBalanceSnapshot struct { - Address proto.WavesAddress - AssetID crypto.Digest - Balance uint64 -} - -func (s AssetBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetBalance(s) } - -type DataEntriesSnapshot struct { // AccountData in pb - Address proto.WavesAddress - DataEntries []proto.DataEntry -} - -func (s DataEntriesSnapshot) Apply(a SnapshotApplier) error { return a.ApplyDataEntries(s) } - -type AccountScriptSnapshot struct { - SenderPublicKey crypto.PublicKey - Script proto.Script - VerifierComplexity uint64 -} - -func (s AccountScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAccountScript(s) } - -type AssetScriptSnapshot struct { - AssetID crypto.Digest - Script proto.Script - Complexity uint64 -} - -func (s AssetScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetScript(s) } - -type LeaseBalanceSnapshot struct { - Address proto.WavesAddress - LeaseIn uint64 - LeaseOut uint64 -} - -func (s LeaseBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseBalance(s) } - -type LeaseStateStatus struct { - Value LeaseStatus // can be only LeaseActive or LeaseCanceled - CancelHeight proto.Height - CancelTransactionID *crypto.Digest -} - -type LeaseStateSnapshot struct { - LeaseID crypto.Digest - Status LeaseStateStatus - Amount uint64 - Sender proto.WavesAddress - Recipient proto.WavesAddress - OriginTransactionID *crypto.Digest - Height proto.Height -} - -func (s LeaseStateSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseState(s) } - -type SponsorshipSnapshot struct { - AssetID crypto.Digest - MinSponsoredFee uint64 -} - -func (s SponsorshipSnapshot) Apply(a SnapshotApplier) error { return a.ApplySponsorship(s) } - -type AliasSnapshot struct { - Address proto.WavesAddress - Alias proto.Alias -} - -func (s AliasSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAlias(s) } - -// FilledVolumeFeeSnapshot Filled Volume and Fee. -type FilledVolumeFeeSnapshot struct { // OrderFill - OrderID crypto.Digest - FilledVolume uint64 - FilledFee uint64 -} - -func (s FilledVolumeFeeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyFilledVolumeAndFee(s) } - -type StaticAssetInfoSnapshot struct { - AssetID crypto.Digest - SourceTransactionID crypto.Digest - IssuerPublicKey crypto.PublicKey - Decimals uint8 - IsNFT bool -} - -func (s StaticAssetInfoSnapshot) Apply(a SnapshotApplier) error { return a.ApplyStaticAssetInfo(s) } - -type AssetVolumeSnapshot struct { // AssetVolume in pb - AssetID crypto.Digest - TotalQuantity big.Int // volume in protobuf - IsReissuable bool -} - -func (s AssetVolumeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetVolume(s) } - -type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb - AssetID crypto.Digest - AssetName string - AssetDescription string - ChangeHeight proto.Height // last_updated in pb -} - -func (s AssetDescriptionSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetDescription(s) } - -type SnapshotApplier interface { - ApplyWavesBalance(snapshot WavesBalanceSnapshot) error - ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) error - ApplyAssetBalance(snapshot AssetBalanceSnapshot) error - ApplyAlias(snapshot AliasSnapshot) error - ApplyStaticAssetInfo(snapshot StaticAssetInfoSnapshot) error - ApplyAssetDescription(snapshot AssetDescriptionSnapshot) error - ApplyAssetVolume(snapshot AssetVolumeSnapshot) error - ApplyAssetScript(snapshot AssetScriptSnapshot) error - ApplySponsorship(snapshot SponsorshipSnapshot) error - ApplyAccountScript(snapshot AccountScriptSnapshot) error - ApplyFilledVolumeAndFee(snapshot FilledVolumeFeeSnapshot) error - ApplyDataEntries(snapshot DataEntriesSnapshot) error - ApplyLeaseState(snapshot LeaseStateSnapshot) error -} diff --git a/pkg/state/state.go b/pkg/state/state.go index f2400755b..3f2aa1899 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -1280,7 +1280,7 @@ func (s *stateManager) needToCancelLeases(blockchainHeight uint64) (bool, error) } } -// TODO generate snapshots here too +// TODO what to do with stolen aliases in snapshots? func (s *stateManager) blockchainHeightAction(blockchainHeight uint64, lastBlock, nextBlock proto.BlockID) error { cancelLeases, err := s.needToCancelLeases(blockchainHeight) if err != nil { @@ -1530,6 +1530,7 @@ func (s *stateManager) addBlocks() (*proto.Block, error) { if err := s.appender.applyAllDiffs(); err != nil { return nil, err } + // Retrieve and store state hashes for each of new blocks. if err := s.stor.handleStateHashes(height, ids); err != nil { return nil, wrapErr(ModificationError, err) diff --git a/pkg/state/transaction_checker.go b/pkg/state/transaction_checker.go index ff091dc5e..f099573d8 100644 --- a/pkg/state/transaction_checker.go +++ b/pkg/state/transaction_checker.go @@ -183,9 +183,6 @@ func (tc *transactionChecker) checkDAppCallables(tree *ast.Tree, rideV6Activated return nil } -// TODO remove it -//type treeEstimations map[int]ride.TreeEstimation - func (tc *transactionChecker) checkScript( script proto.Script, estimatorVersion int, @@ -218,6 +215,7 @@ func (tc *transactionChecker) checkScript( if err != nil { return ride.TreeEstimation{}, errs.Extend(err, "failed to estimate script complexity") } + if scErr := tc.checkScriptComplexity(tree.LibVersion, est, tree.IsDApp(), reducedVerifierComplexity); scErr != nil { return ride.TreeEstimation{}, errors.Wrap(scErr, "failed to check script complexity") } diff --git a/pkg/state/transaction_checker_test.go b/pkg/state/transaction_checker_test.go index 6b6aab304..075f484ed 100644 --- a/pkg/state/transaction_checker_test.go +++ b/pkg/state/transaction_checker_test.go @@ -22,19 +22,43 @@ var ( ) type checkerTestObjects struct { - stor *testStorageObjects - tc *transactionChecker - tp *transactionPerformer + stor *testStorageObjects + tc *transactionChecker + tp *transactionPerformer + stateActionsCounter *proto.StateActionsCounter } -func createCheckerTestObjects(t *testing.T) *checkerTestObjects { +func createCheckerTestObjects(t *testing.T, checkerInfo *checkerInfo) *checkerTestObjects { stor := createStorageObjects(t, true) tc, err := newTransactionChecker(proto.NewBlockIDFromSignature(genSig), stor.entities, settings.MainNetSettings) require.NoError(t, err, "newTransactionChecker() failed") - snapshotGenerator := &snapshotGenerator{stor: stor.entities, settings: settings.MainNetSettings} - tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) + + actionsCounter := new(proto.StateActionsCounter) + snapshotApplier := newBlockSnapshotsApplier( + blockSnapshotsApplierInfo{ + ci: checkerInfo, + scheme: settings.MainNetSettings.AddressSchemeCharacter, + stateActionsCounter: actionsCounter, + }, + snapshotApplierStorages{ + balances: stor.entities.balances, + aliases: stor.entities.aliases, + assets: stor.entities.assets, + scriptsStorage: stor.entities.scriptsStorage, + scriptsComplexity: stor.entities.scriptsComplexity, + sponsoredAssets: stor.entities.sponsoredAssets, + ordersVolumes: stor.entities.ordersVolumes, + accountsDataStor: stor.entities.accountsDataStor, + leases: stor.entities.leases, + }, + ) + snapshotGen := snapshotGenerator{stor: stor.entities, scheme: settings.MainNetSettings.AddressSchemeCharacter} + + tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings) + tp.snapshotApplier = &snapshotApplier + tp.snapshotGenerator = &snapshotGen require.NoError(t, err, "newTransactionPerformer() failed") - return &checkerTestObjects{stor, tc, tp} + return &checkerTestObjects{stor, tc, tp, actionsCounter} } func defaultCheckerInfo() *checkerInfo { @@ -48,10 +72,11 @@ func defaultCheckerInfo() *checkerInfo { } func TestCheckGenesis(t *testing.T) { - to := createCheckerTestObjects(t) - tx := createGenesis() info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) + + tx := createGenesis() _, err := to.tc.checkGenesis(tx, info) assert.EqualError(t, err, "genesis transaction inside of non-genesis block") @@ -70,10 +95,11 @@ func TestCheckGenesis(t *testing.T) { } func TestCheckPayment(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createPayment(t) - info := defaultCheckerInfo() + info.height = settings.MainNetSettings.BlockVersion3AfterHeight _, err := to.tc.checkPayment(tx, info) assert.Error(t, err, "checkPayment accepted payment tx after Block v3 height") @@ -87,10 +113,10 @@ func TestCheckPayment(t *testing.T) { } func TestCheckTransferWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createTransferWithSig(t) - info := defaultCheckerInfo() assetId := tx.FeeAsset.ID @@ -125,10 +151,10 @@ func TestCheckTransferWithSig(t *testing.T) { } func TestCheckTransferWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createTransferWithProofs(t) - info := defaultCheckerInfo() assetId := tx.FeeAsset.ID @@ -170,7 +196,8 @@ func TestCheckTransferWithProofs(t *testing.T) { } func TestCheckIsValidUtf8(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) err := to.tc.isValidUtf8("just a normal string") assert.NoError(t, err) @@ -188,10 +215,11 @@ func TestCheckIsValidUtf8(t *testing.T) { } func TestCheckIssueWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createIssueWithSig(t, 1000) - info := defaultCheckerInfo() + _, err := to.tc.checkIssueWithSig(tx, info) assert.NoError(t, err, "checkIssueWithSig failed with valid issue tx") @@ -201,10 +229,11 @@ func TestCheckIssueWithSig(t *testing.T) { } func TestCheckIssueWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createIssueWithProofs(t, 1000) - info := defaultCheckerInfo() + to.stor.addBlock(t, blockID0) _, err := to.tc.checkIssueWithProofs(tx, info) @@ -216,13 +245,14 @@ func TestCheckIssueWithProofs(t *testing.T) { } func TestCheckReissueWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithSig(t, 1000) tx.SenderPK = assetInfo.issuer - info := defaultCheckerInfo() + info.currentTimestamp = settings.MainNetSettings.ReissueBugWindowTimeEnd + 1 _, err := to.tc.checkReissueWithSig(tx, info) assert.NoError(t, err, "checkReissueWithSig failed with valid reissue tx") @@ -247,7 +277,7 @@ func TestCheckReissueWithSig(t *testing.T) { tx.SenderPK = assetInfo.issuer tx.Reissuable = false - _, err = to.tp.performReissueWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performReissueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performReissueWithSig failed") to.stor.addBlock(t, blockID0) to.stor.flush(t) @@ -258,13 +288,14 @@ func TestCheckReissueWithSig(t *testing.T) { } func TestCheckReissueWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithProofs(t, 1000) tx.SenderPK = assetInfo.issuer - info := defaultCheckerInfo() + info.currentTimestamp = settings.MainNetSettings.ReissueBugWindowTimeEnd + 1 _, err := to.tc.checkReissueWithProofs(tx, info) @@ -295,7 +326,7 @@ func TestCheckReissueWithProofs(t *testing.T) { tx.SenderPK = assetInfo.issuer tx.Reissuable = false - _, err = to.tp.performReissueWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performReissueWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performReissueWithProofs failed") to.stor.addBlock(t, blockID0) to.stor.flush(t) @@ -306,12 +337,12 @@ func TestCheckReissueWithProofs(t *testing.T) { } func TestCheckBurnWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithSig(t) tx.SenderPK = assetInfo.issuer - info := defaultCheckerInfo() _, err := to.tc.checkBurnWithSig(tx, info) assert.NoError(t, err, "checkBurnWithSig failed with valid burn tx") @@ -340,12 +371,12 @@ func TestCheckBurnWithSig(t *testing.T) { } func TestCheckBurnWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithProofs(t) tx.SenderPK = assetInfo.issuer - info := defaultCheckerInfo() _, err := to.tc.checkBurnWithProofs(tx, info) assert.Error(t, err, "checkBurnWithProofs did not fail prior to SmartAccounts activation") @@ -379,10 +410,11 @@ func TestCheckBurnWithProofs(t *testing.T) { } func TestCheckExchangeWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createExchangeWithSig(t) - info := defaultCheckerInfo() + _, err := to.tc.checkExchangeWithSig(tx, info) assert.Error(t, err, "checkExchangeWithSig did not fail with exchange with unknown assets") @@ -445,10 +477,11 @@ func TestCheckExchangeWithSig(t *testing.T) { } func TestCheckExchangeWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) txOV2 := createExchangeWithProofs(t) - info := defaultCheckerInfo() + _, err := to.tc.checkExchangeWithProofs(txOV2, info) assert.Error(t, err, "checkExchangeWithProofs did not fail with exchange with unknown assets") @@ -540,10 +573,10 @@ func TestCheckExchangeWithProofs(t *testing.T) { } func TestCheckUnorderedExchangeV2WithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createUnorderedExchangeWithProofs(t, 2) - info := defaultCheckerInfo() to.stor.createAsset(t, testGlobal.asset0.asset.ID) to.stor.createAsset(t, testGlobal.asset1.asset.ID) @@ -559,10 +592,10 @@ func TestCheckUnorderedExchangeV2WithProofs(t *testing.T) { } func TestCheckUnorderedExchangeV3WithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createUnorderedExchangeWithProofs(t, 3) - info := defaultCheckerInfo() to.stor.createAsset(t, testGlobal.asset0.asset.ID) to.stor.createAsset(t, testGlobal.asset1.asset.ID) @@ -578,10 +611,11 @@ func TestCheckUnorderedExchangeV3WithProofs(t *testing.T) { } func TestCheckLeaseWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createLeaseWithSig(t) - info := defaultCheckerInfo() + tx.Recipient = proto.NewRecipientFromAddress(testGlobal.senderInfo.addr) _, err := to.tc.checkLeaseWithSig(tx, info) assert.Error(t, err, "checkLeaseWithSig did not fail when leasing to self") @@ -592,10 +626,11 @@ func TestCheckLeaseWithSig(t *testing.T) { } func TestCheckLeaseWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createLeaseWithProofs(t) - info := defaultCheckerInfo() + tx.Recipient = proto.NewRecipientFromAddress(testGlobal.senderInfo.addr) _, err := to.tc.checkLeaseWithProofs(tx, info) assert.Error(t, err, "checkLeaseWithProofs did not fail when leasing to self") @@ -612,10 +647,11 @@ func TestCheckLeaseWithProofs(t *testing.T) { } func TestCheckLeaseCancelWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) leaseTx := createLeaseWithSig(t) - info := defaultCheckerInfo() + info.currentTimestamp = settings.MainNetSettings.AllowMultipleLeaseCancelUntilTime + 1 tx := createLeaseCancelWithSig(t, *leaseTx.ID) @@ -623,7 +659,7 @@ func TestCheckLeaseCancelWithSig(t *testing.T) { assert.Error(t, err, "checkLeaseCancelWithSig did not fail when cancelling nonexistent lease") to.stor.addBlock(t, blockID0) - _, err = to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseWithSig failed") to.stor.flush(t) @@ -640,10 +676,11 @@ func TestCheckLeaseCancelWithSig(t *testing.T) { } func TestCheckLeaseCancelWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) leaseTx := createLeaseWithProofs(t) - info := defaultCheckerInfo() + info.currentTimestamp = settings.MainNetSettings.AllowMultipleLeaseCancelUntilTime + 1 tx := createLeaseCancelWithProofs(t, *leaseTx.ID) @@ -651,7 +688,7 @@ func TestCheckLeaseCancelWithProofs(t *testing.T) { assert.Error(t, err, "checkLeaseCancelWithProofs did not fail when cancelling nonexistent lease") to.stor.addBlock(t, blockID0) - _, err = to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseWithProofs failed") to.stor.flush(t) @@ -667,7 +704,7 @@ func TestCheckLeaseCancelWithProofs(t *testing.T) { _, err = to.tc.checkLeaseCancelWithProofs(tx, info) assert.NoError(t, err, "checkLeaseCancelWithProofs failed with valid leaseCancel tx") - _, err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseCancelWithProofs() failed") _, err = to.tc.checkLeaseCancelWithProofs(tx, info) @@ -675,16 +712,16 @@ func TestCheckLeaseCancelWithProofs(t *testing.T) { } func TestCheckCreateAliasWithSig(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createCreateAliasWithSig(t) - info := defaultCheckerInfo() _, err := to.tc.checkCreateAliasWithSig(tx, info) assert.NoError(t, err, "checkCreateAliasWithSig failed with valid createAlias tx") to.stor.addBlock(t, blockID0) - _, err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performCreateAliasWithSig failed") to.stor.flush(t) @@ -698,10 +735,10 @@ func TestCheckCreateAliasWithSig(t *testing.T) { } func TestCheckCreateAliasWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createCreateAliasWithProofs(t) - info := defaultCheckerInfo() _, err := to.tc.checkCreateAliasWithProofs(tx, info) assert.Error(t, err, "checkCreateAliasWithProofs did not fail prior to SmartAccounts activation") @@ -712,7 +749,7 @@ func TestCheckCreateAliasWithProofs(t *testing.T) { assert.NoError(t, err, "checkCreateAliasWithProofs failed with valid createAlias tx") to.stor.addBlock(t, blockID0) - _, err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performCreateAliasWithProofs failed") to.stor.flush(t) @@ -726,12 +763,12 @@ func TestCheckCreateAliasWithProofs(t *testing.T) { } func TestCheckMassTransferWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) entriesNum := 50 entries := generateMassTransferEntries(t, entriesNum) tx := createMassTransferWithProofs(t, entries) - info := defaultCheckerInfo() _, err := to.tc.checkMassTransferWithProofs(tx, info) assert.Error(t, err, "checkMassTransferWithProofs did not fail prior to feature activation") @@ -757,10 +794,10 @@ func TestCheckMassTransferWithProofs(t *testing.T) { } func TestCheckDataWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createDataWithProofs(t, 1) - info := defaultCheckerInfo() _, err := to.tc.checkDataWithProofs(tx, info) assert.Error(t, err, "checkDataWithProofs did not fail prior to feature activation") @@ -803,12 +840,12 @@ func TestCheckDataWithProofs(t *testing.T) { } func TestCheckSponsorshipWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createSponsorshipWithProofs(t, 1000) assetInfo := to.stor.createAsset(t, tx.AssetID) tx.SenderPK = assetInfo.issuer - info := defaultCheckerInfo() _, err := to.tc.checkSponsorshipWithProofs(tx, info) assert.Error(t, err, "checkSponsorshipWithProofs did not fail prior to feature activation") @@ -846,10 +883,10 @@ func TestCheckSponsorshipWithProofs(t *testing.T) { } func TestCheckSetScriptWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createSetScriptWithProofs(t) - info := defaultCheckerInfo() // Activate sponsorship. to.stor.activateSponsorship(t) @@ -1344,10 +1381,10 @@ func TestCheckSetScriptWithProofsCheckDAppCallables(t *testing.T) { } func TestCheckSetAssetScriptWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createSetAssetScriptWithProofs(t) - info := defaultCheckerInfo() assetInfo := defaultAssetInfo(proto.DigestTail(tx.AssetID), true) assetInfo.issuer = tx.SenderPK @@ -1358,7 +1395,7 @@ func TestCheckSetAssetScriptWithProofs(t *testing.T) { assert.Error(t, err, "checkSetAssetScriptWithProofs did not fail with non-smart asset") // Make it smart. - err = to.stor.entities.scriptsStorage.setAssetScript(tx.AssetID, tx.Script, tx.SenderPK, blockID0) + err = to.stor.entities.scriptsStorage.setAssetScript(tx.AssetID, tx.Script, blockID0) assert.NoError(t, err, "setAssetScript failed") // Now should pass. @@ -1380,13 +1417,14 @@ func TestCheckSetAssetScriptWithProofs(t *testing.T) { } func TestCheckInvokeScriptWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) payments := []proto.ScriptPayment{ {Amount: 1, Asset: *testGlobal.asset0.asset}, } tx := createInvokeScriptWithProofs(t, payments, proto.FunctionCall{}, proto.OptionalAsset{}, 1) - info := defaultCheckerInfo() + to.stor.addBlock(t, blockID0) assetId := tx.Payments[0].Asset.ID to.stor.createAsset(t, assetId) @@ -1420,7 +1458,8 @@ func TestCheckInvokeScriptWithProofs(t *testing.T) { } func TestCheckUpdateAssetInfoWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createUpdateAssetInfoWithProofs(t) // We create asset using random block here on purpose, this way @@ -1429,7 +1468,6 @@ func TestCheckUpdateAssetInfoWithProofs(t *testing.T) { to.stor.createAsset(t, tx.FeeAsset.ID) tx.SenderPK = assetInfo.issuer - info := defaultCheckerInfo() info.height = 100001 // Check fail prior to activation. @@ -1462,10 +1500,10 @@ func TestCheckUpdateAssetInfoWithProofs(t *testing.T) { } func TestCheckInvokeExpressionWithProofs(t *testing.T) { - to := createCheckerTestObjects(t) + info := defaultCheckerInfo() + to := createCheckerTestObjects(t, info) tx := createInvokeExpressionWithProofs(t, make([]byte, 1), proto.OptionalAsset{}, 1) - info := defaultCheckerInfo() // Check activation. _, err := to.tc.checkInvokeScriptWithProofs(tx, info) diff --git a/pkg/state/transaction_differ.go b/pkg/state/transaction_differ.go index 467ed6e05..b4450f1ea 100644 --- a/pkg/state/transaction_differ.go +++ b/pkg/state/transaction_differ.go @@ -81,7 +81,7 @@ func (diff *balanceDiff) applyTo(profile balanceProfile) (balanceProfile, error) // Check min intermediate change. minBalance, err := common.AddInt(diff.minBalance, int64(profile.balance)) if err != nil { - return balanceProfile{}, errors.Errorf("failed to add balance and min balance diff: %v\n", err) + return balanceProfile{}, errors.Errorf("failed to add balance and min balance diff: %v", err) } if minBalance < 0 { return balanceProfile{}, errors.Errorf( @@ -93,19 +93,19 @@ func (diff *balanceDiff) applyTo(profile balanceProfile) (balanceProfile, error) // Check main balance diff. newBalance, err := common.AddInt(diff.balance, int64(profile.balance)) if err != nil { - return balanceProfile{}, errors.Errorf("failed to add balance and balance diff: %v\n", err) + return balanceProfile{}, errors.Errorf("failed to add balance and balance diff: %v", err) } if newBalance < 0 { return balanceProfile{}, errors.New("negative result balance (Attempt to transfer unavailable funds)") } newLeaseIn, err := common.AddInt(diff.leaseIn, profile.leaseIn) if err != nil { - return balanceProfile{}, errors.Errorf("failed to add leaseIn and leaseIn diff: %v\n", err) + return balanceProfile{}, errors.Errorf("failed to add leaseIn and leaseIn diff: %v", err) } // Check leasing change. newLeaseOut, err := common.AddInt(diff.leaseOut, profile.leaseOut) if err != nil { - return balanceProfile{}, errors.Errorf("failed to add leaseOut and leaseOut diff: %v\n", err) + return balanceProfile{}, errors.Errorf("failed to add leaseOut and leaseOut diff: %v", err) } if (newBalance < newLeaseOut) && !diff.allowLeasedTransfer { return balanceProfile{}, errs.NewTxValidationError("Reason: Cannot lease more than own") diff --git a/pkg/state/transaction_differ_test.go b/pkg/state/transaction_differ_test.go index 7f5e312d1..32246a3a6 100644 --- a/pkg/state/transaction_differ_test.go +++ b/pkg/state/transaction_differ_test.go @@ -26,19 +26,44 @@ var ( ) type differTestObjects struct { - stor *testStorageObjects - td *transactionDiffer - tp *transactionPerformer + stor *testStorageObjects + td *transactionDiffer + tp *transactionPerformer + stateActionsCounter *proto.StateActionsCounter } -func createDifferTestObjects(t *testing.T) *differTestObjects { +func createDifferTestObjects(t *testing.T, checkerInfo *checkerInfo) *differTestObjects { stor := createStorageObjects(t, true) td, err := newTransactionDiffer(stor.entities, settings.MainNetSettings) require.NoError(t, err, "newTransactionDiffer() failed") - snapshotGenerator := &snapshotGenerator{stor: stor.entities, settings: settings.MainNetSettings} - tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) + + actionsCounter := new(proto.StateActionsCounter) + + snapshotApplier := newBlockSnapshotsApplier( + blockSnapshotsApplierInfo{ + ci: checkerInfo, + scheme: settings.MainNetSettings.AddressSchemeCharacter, + stateActionsCounter: actionsCounter, + }, + snapshotApplierStorages{ + balances: stor.entities.balances, + aliases: stor.entities.aliases, + assets: stor.entities.assets, + scriptsStorage: stor.entities.scriptsStorage, + scriptsComplexity: stor.entities.scriptsComplexity, + sponsoredAssets: stor.entities.sponsoredAssets, + ordersVolumes: stor.entities.ordersVolumes, + accountsDataStor: stor.entities.accountsDataStor, + leases: stor.entities.leases, + }, + ) + snapshotGen := snapshotGenerator{stor: stor.entities, scheme: settings.MainNetSettings.AddressSchemeCharacter, + IsFullNodeMode: true} + tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings) + tp.snapshotApplier = &snapshotApplier + tp.snapshotGenerator = &snapshotGen require.NoError(t, err, "newTransactionPerformer() failed") - return &differTestObjects{stor, td, tp} + return &differTestObjects{stor, td, tp, actionsCounter} } func createGenesis() *proto.Genesis { @@ -46,7 +71,8 @@ func createGenesis() *proto.Genesis { } func TestCreateDiffGenesis(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createGenesis() ch, err := to.td.createDiffGenesis(tx, defaultDifferInfo()) @@ -67,7 +93,8 @@ func createPayment(t *testing.T) *proto.Payment { } func TestCreateDiffPayment(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createPayment(t) ch, err := to.td.createDiffPayment(tx, defaultDifferInfo()) @@ -94,7 +121,8 @@ func createTransferWithSig(t *testing.T) *proto.TransferWithSig { } func TestCreateDiffTransferWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createTransferWithSig(t) feeFullAssetID := tx.FeeAsset.ID @@ -151,7 +179,8 @@ func createTransferWithProofs(t *testing.T) *proto.TransferWithProofs { } func TestCreateDiffTransferWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createTransferWithProofs(t) feeFullAssetID := tx.FeeAsset.ID @@ -215,7 +244,8 @@ func createNFTIssueWithSig(t *testing.T) *proto.IssueWithSig { } func TestCreateDiffIssueWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createIssueWithSig(t, 1000) ch, err := to.td.createDiffIssueWithSig(tx, defaultDifferInfo()) @@ -249,7 +279,8 @@ func createNFTIssueWithProofs(t *testing.T) *proto.IssueWithProofs { } func TestCreateDiffIssueWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createIssueWithProofs(t, 1000) ch, err := to.td.createDiffIssueWithProofs(tx, defaultDifferInfo()) @@ -276,7 +307,8 @@ func createReissueWithSig(t *testing.T, feeUnits int) *proto.ReissueWithSig { } func TestCreateDiffReissueWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createReissueWithSig(t, 1000) ch, err := to.td.createDiffReissueWithSig(tx, defaultDifferInfo()) @@ -302,7 +334,8 @@ func createReissueWithProofs(t *testing.T, feeUnits int) *proto.ReissueWithProof } func TestCreateDiffReissueWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createReissueWithProofs(t, 1000) ch, err := to.td.createDiffReissueWithProofs(tx, defaultDifferInfo()) @@ -328,7 +361,8 @@ func createBurnWithSig(t *testing.T) *proto.BurnWithSig { } func TestCreateDiffBurnWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createBurnWithSig(t) ch, err := to.td.createDiffBurnWithSig(tx, defaultDifferInfo()) @@ -354,7 +388,8 @@ func createBurnWithProofs(t *testing.T) *proto.BurnWithProofs { } func TestCreateDiffBurnWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createBurnWithProofs(t) ch, err := to.td.createDiffBurnWithProofs(tx, defaultDifferInfo()) @@ -400,7 +435,8 @@ func createExchangeWithSig(t *testing.T) *proto.ExchangeWithSig { //} func TestCreateDiffExchangeWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createExchangeWithSig(t) ch, err := to.td.createDiffExchange(tx, defaultDifferInfo()) @@ -453,7 +489,8 @@ func createUnorderedExchangeWithProofs(t *testing.T, v int) *proto.ExchangeWithP } func TestCreateDiffExchangeWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createExchangeWithProofs(t) ch, err := to.td.createDiffExchange(tx, defaultDifferInfo()) @@ -562,7 +599,8 @@ func createExchangeV2WithProofsWithOrdersV3(t *testing.T, info orderBuildInfo) * } func TestCreateDiffExchangeV2WithProofsWithOrdersV3(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createExchangeV2WithProofsWithOrdersV3(t, orderBuildInfo{ price: 10e8, @@ -593,7 +631,8 @@ func TestCreateDiffExchangeV2WithProofsWithOrdersV3(t *testing.T) { } func TestCreateDiffExchangeV3WithProofsWithMixedOrders(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) const ( asset0Decimals = 5 @@ -700,7 +739,7 @@ func TestCreateDiffExchangeV3WithProofsWithMixedOrders(t *testing.T) { // and produces an incorrect or unexpected diff, should be fixes some how // // func TestCreateDiffExchangeWithSignature(t *testing.T) { -// to, path := createDifferTestObjects(t) +// to, path := createDifferTestObjects(t, checkerInfo // // to.stor.createAssetWithDecimals(t, testGlobal.asset0.asset.ID, 8) // to.stor.createAssetWithDecimals(t, testGlobal.asset1.asset.ID, 8) @@ -734,7 +773,8 @@ func TestCreateDiffExchangeV3WithProofsWithMixedOrders(t *testing.T) { // assert.Equal(t, correctAddrs, ch.addrs) // } func TestCreateDiffExchangeV3WithProofsWithOrdersV4(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) to.stor.createAssetWithDecimals(t, testGlobal.asset0.asset.ID, 0) to.stor.createAssetWithDecimals(t, testGlobal.asset1.asset.ID, 8) @@ -807,7 +847,8 @@ func createLeaseWithSig(t *testing.T) *proto.LeaseWithSig { } func TestCreateDiffLeaseWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createLeaseWithSig(t) ch, err := to.td.createDiffLeaseWithSig(tx, defaultDifferInfo()) @@ -834,7 +875,8 @@ func createLeaseWithProofs(t *testing.T) *proto.LeaseWithProofs { } func TestCreateDiffLeaseWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createLeaseWithProofs(t) ch, err := to.td.createDiffLeaseWithProofs(tx, defaultDifferInfo()) @@ -861,10 +903,11 @@ func createLeaseCancelWithSig(t *testing.T, leaseID crypto.Digest) *proto.LeaseC } func TestCreateDiffLeaseCancelWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) leaseTx := createLeaseWithSig(t) - info := defaultPerformerInfo() + info := defaultPerformerInfo(to.stateActionsCounter) to.stor.addBlock(t, blockID0) _, err := to.tp.performLeaseWithSig(leaseTx, info, nil, nil) assert.NoError(t, err, "performLeaseWithSig failed") @@ -894,10 +937,11 @@ func createLeaseCancelWithProofs(t *testing.T, leaseID crypto.Digest) *proto.Lea } func TestCreateDiffLeaseCancelWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) leaseTx := createLeaseWithProofs(t) - info := defaultPerformerInfo() + info := defaultPerformerInfo(to.stateActionsCounter) to.stor.addBlock(t, blockID0) _, err := to.tp.performLeaseWithProofs(leaseTx, info, nil, nil) assert.NoError(t, err, "performLeaseWithProofs failed") @@ -931,7 +975,8 @@ func createCreateAliasWithSig(t *testing.T) *proto.CreateAliasWithSig { } func TestCreateDiffCreateAliasWithSig(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createCreateAliasWithSig(t) ch, err := to.td.createDiffCreateAliasWithSig(tx, defaultDifferInfo()) @@ -960,7 +1005,8 @@ func createCreateAliasWithProofs(t *testing.T) *proto.CreateAliasWithProofs { } func TestCreateDiffCreateAliasWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createCreateAliasWithProofs(t) ch, err := to.td.createDiffCreateAliasWithProofs(tx, defaultDifferInfo()) @@ -996,7 +1042,8 @@ func createMassTransferWithProofs(t *testing.T, transfers []proto.MassTransferEn } func TestCreateDiffMassTransferWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) entriesNum := 66 entries := generateMassTransferEntries(t, entriesNum) @@ -1036,7 +1083,8 @@ func createDataWithProofs(t *testing.T, entriesNum int) *proto.DataWithProofs { } func TestCreateDiffDataWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createDataWithProofs(t, 1) ch, err := to.td.createDiffDataWithProofs(tx, defaultDifferInfo()) @@ -1061,7 +1109,8 @@ func createSponsorshipWithProofs(t *testing.T, fee uint64) *proto.SponsorshipWit } func TestCreateDiffSponsorshipWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createSponsorshipWithProofs(t, 1000) ch, err := to.td.createDiffSponsorshipWithProofs(tx, defaultDifferInfo()) @@ -1093,7 +1142,8 @@ func createSetScriptWithProofs(t *testing.T, customScriptBytes ...[]byte) *proto } func TestCreateDiffSetScriptWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createSetScriptWithProofs(t) ch, err := to.td.createDiffSetScriptWithProofs(tx, defaultDifferInfo()) @@ -1120,7 +1170,8 @@ func createSetAssetScriptWithProofs(t *testing.T) *proto.SetAssetScriptWithProof } func TestCreateDiffSetAssetScriptWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createSetAssetScriptWithProofs(t) ch, err := to.td.createDiffSetAssetScriptWithProofs(tx, defaultDifferInfo()) @@ -1145,7 +1196,8 @@ func createInvokeScriptWithProofs(t *testing.T, pmts proto.ScriptPayments, fc pr } func TestCreateDiffInvokeScriptWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) feeConst, ok := feeConstants[proto.InvokeScriptTransaction] assert.Equal(t, ok, true) @@ -1207,7 +1259,8 @@ func createUpdateAssetInfoWithProofs(t *testing.T) *proto.UpdateAssetInfoWithPro } func TestCreateDiffUpdateAssetInfoWithProofs(t *testing.T) { - to := createDifferTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createDifferTestObjects(t, checkerInfo) tx := createUpdateAssetInfoWithProofs(t) ch, err := to.td.createDiffUpdateAssetInfoWithProofs(tx, defaultDifferInfo()) diff --git a/pkg/state/transaction_handler.go b/pkg/state/transaction_handler.go index ca87af3e9..00b840d09 100644 --- a/pkg/state/transaction_handler.go +++ b/pkg/state/transaction_handler.go @@ -24,7 +24,7 @@ type scriptEstimation struct { func (e *scriptEstimation) isPresent() bool { return e != nil } type txCheckFunc func(proto.Transaction, *checkerInfo) (txCheckerData, error) -type txPerformFunc func(proto.Transaction, *performerInfo, *invocationResult, txDiff) (TransactionSnapshot, error) +type txPerformFunc func(proto.Transaction, *performerInfo, *invocationResult, txDiff) (proto.TransactionSnapshot, error) type txCreateDiffFunc func(proto.Transaction, *differInfo) (txBalanceChanges, error) type txCountFeeFunc func(proto.Transaction, *feeDistribution) error @@ -51,85 +51,112 @@ type transactionHandler struct { func buildHandles(tc *transactionChecker, tp *transactionPerformer, td *transactionDiffer, tf *transactionFeeCounter) handles { return handles{ proto.TransactionTypeInfo{Type: proto.GenesisTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkGenesis, tp.performGenesis, td.createDiffGenesis, nil, + tc.checkGenesis, tp.performGenesis, + td.createDiffGenesis, nil, }, proto.TransactionTypeInfo{Type: proto.PaymentTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkPayment, tp.performPayment, td.createDiffPayment, tf.minerFeePayment, + tc.checkPayment, tp.performPayment, + td.createDiffPayment, tf.minerFeePayment, }, proto.TransactionTypeInfo{Type: proto.TransferTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkTransferWithSig, tp.performTransferWithSig, td.createDiffTransferWithSig, tf.minerFeeTransferWithSig, + tc.checkTransferWithSig, tp.performTransferWithSig, + td.createDiffTransferWithSig, tf.minerFeeTransferWithSig, }, proto.TransactionTypeInfo{Type: proto.TransferTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkTransferWithProofs, tp.performTransferWithProofs, 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, + tc.checkIssueWithSig, tp.performIssueWithSig, + td.createDiffIssueWithSig, tf.minerFeeIssueWithSig, }, proto.TransactionTypeInfo{Type: proto.IssueTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkIssueWithProofs, tp.performIssueWithProofs, td.createDiffIssueWithProofs, tf.minerFeeIssueWithProofs, + tc.checkIssueWithProofs, tp.performIssueWithProofs, + td.createDiffIssueWithProofs, tf.minerFeeIssueWithProofs, }, proto.TransactionTypeInfo{Type: proto.ReissueTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkReissueWithSig, tp.performReissueWithSig, td.createDiffReissueWithSig, tf.minerFeeReissueWithSig, + tc.checkReissueWithSig, tp.performReissueWithSig, + td.createDiffReissueWithSig, tf.minerFeeReissueWithSig, }, proto.TransactionTypeInfo{Type: proto.ReissueTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkReissueWithProofs, tp.performReissueWithProofs, td.createDiffReissueWithProofs, tf.minerFeeReissueWithProofs, + tc.checkReissueWithProofs, tp.performReissueWithProofs, + td.createDiffReissueWithProofs, tf.minerFeeReissueWithProofs, }, proto.TransactionTypeInfo{Type: proto.BurnTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkBurnWithSig, tp.performBurnWithSig, td.createDiffBurnWithSig, tf.minerFeeBurnWithSig, + tc.checkBurnWithSig, tp.performBurnWithSig, + td.createDiffBurnWithSig, tf.minerFeeBurnWithSig, }, proto.TransactionTypeInfo{Type: proto.BurnTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkBurnWithProofs, tp.performBurnWithProofs, td.createDiffBurnWithProofs, tf.minerFeeBurnWithProofs, + tc.checkBurnWithProofs, tp.performBurnWithProofs, + td.createDiffBurnWithProofs, tf.minerFeeBurnWithProofs, }, proto.TransactionTypeInfo{Type: proto.ExchangeTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkExchangeWithSig, tp.performExchange, td.createDiffExchange, tf.minerFeeExchange, + tc.checkExchangeWithSig, tp.performExchange, + td.createDiffExchange, tf.minerFeeExchange, }, proto.TransactionTypeInfo{Type: proto.ExchangeTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkExchangeWithProofs, tp.performExchange, td.createDiffExchange, tf.minerFeeExchange, + tc.checkExchangeWithProofs, tp.performExchange, + td.createDiffExchange, tf.minerFeeExchange, }, proto.TransactionTypeInfo{Type: proto.LeaseTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkLeaseWithSig, tp.performLeaseWithSig, td.createDiffLeaseWithSig, tf.minerFeeLeaseWithSig, + tc.checkLeaseWithSig, tp.performLeaseWithSig, + td.createDiffLeaseWithSig, tf.minerFeeLeaseWithSig, }, proto.TransactionTypeInfo{Type: proto.LeaseTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkLeaseWithProofs, tp.performLeaseWithProofs, td.createDiffLeaseWithProofs, tf.minerFeeLeaseWithProofs, + tc.checkLeaseWithProofs, tp.performLeaseWithProofs, + td.createDiffLeaseWithProofs, tf.minerFeeLeaseWithProofs, }, proto.TransactionTypeInfo{Type: proto.LeaseCancelTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkLeaseCancelWithSig, tp.performLeaseCancelWithSig, td.createDiffLeaseCancelWithSig, tf.minerFeeLeaseCancelWithSig, + tc.checkLeaseCancelWithSig, tp.performLeaseCancelWithSig, + td.createDiffLeaseCancelWithSig, tf.minerFeeLeaseCancelWithSig, }, proto.TransactionTypeInfo{Type: proto.LeaseCancelTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkLeaseCancelWithProofs, tp.performLeaseCancelWithProofs, td.createDiffLeaseCancelWithProofs, tf.minerFeeLeaseCancelWithProofs, + tc.checkLeaseCancelWithProofs, tp.performLeaseCancelWithProofs, + td.createDiffLeaseCancelWithProofs, tf.minerFeeLeaseCancelWithProofs, }, proto.TransactionTypeInfo{Type: proto.CreateAliasTransaction, ProofVersion: proto.Signature}: txHandleFuncs{ - tc.checkCreateAliasWithSig, tp.performCreateAliasWithSig, td.createDiffCreateAliasWithSig, tf.minerFeeCreateAliasWithSig, + tc.checkCreateAliasWithSig, tp.performCreateAliasWithSig, + td.createDiffCreateAliasWithSig, tf.minerFeeCreateAliasWithSig, }, proto.TransactionTypeInfo{Type: proto.CreateAliasTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkCreateAliasWithProofs, tp.performCreateAliasWithProofs, td.createDiffCreateAliasWithProofs, tf.minerFeeCreateAliasWithProofs, + tc.checkCreateAliasWithProofs, tp.performCreateAliasWithProofs, + td.createDiffCreateAliasWithProofs, tf.minerFeeCreateAliasWithProofs, }, proto.TransactionTypeInfo{Type: proto.MassTransferTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkMassTransferWithProofs, tp.performMassTransferWithProofs, 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, + tc.checkDataWithProofs, tp.performDataWithProofs, + td.createDiffDataWithProofs, tf.minerFeeDataWithProofs, }, proto.TransactionTypeInfo{Type: proto.SponsorshipTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkSponsorshipWithProofs, tp.performSponsorshipWithProofs, td.createDiffSponsorshipWithProofs, tf.minerFeeSponsorshipWithProofs, + tc.checkSponsorshipWithProofs, tp.performSponsorshipWithProofs, + td.createDiffSponsorshipWithProofs, tf.minerFeeSponsorshipWithProofs, }, proto.TransactionTypeInfo{Type: proto.SetScriptTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkSetScriptWithProofs, tp.performSetScriptWithProofs, td.createDiffSetScriptWithProofs, tf.minerFeeSetScriptWithProofs, + tc.checkSetScriptWithProofs, tp.performSetScriptWithProofs, + td.createDiffSetScriptWithProofs, tf.minerFeeSetScriptWithProofs, }, proto.TransactionTypeInfo{Type: proto.SetAssetScriptTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkSetAssetScriptWithProofs, tp.performSetAssetScriptWithProofs, td.createDiffSetAssetScriptWithProofs, tf.minerFeeSetAssetScriptWithProofs, + tc.checkSetAssetScriptWithProofs, tp.performSetAssetScriptWithProofs, + td.createDiffSetAssetScriptWithProofs, tf.minerFeeSetAssetScriptWithProofs, }, proto.TransactionTypeInfo{Type: proto.InvokeScriptTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkInvokeScriptWithProofs, tp.performInvokeScriptWithProofs, td.createDiffInvokeScriptWithProofs, tf.minerFeeInvokeScriptWithProofs, + tc.checkInvokeScriptWithProofs, tp.performInvokeScriptWithProofs, + td.createDiffInvokeScriptWithProofs, tf.minerFeeInvokeScriptWithProofs, }, proto.TransactionTypeInfo{Type: proto.InvokeExpressionTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkInvokeExpressionWithProofs, tp.performInvokeExpressionWithProofs, td.createDiffInvokeExpressionWithProofs, tf.minerFeeInvokeExpressionWithProofs, + tc.checkInvokeExpressionWithProofs, tp.performInvokeExpressionWithProofs, + td.createDiffInvokeExpressionWithProofs, tf.minerFeeInvokeExpressionWithProofs, }, proto.TransactionTypeInfo{Type: proto.UpdateAssetInfoTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkUpdateAssetInfoWithProofs, tp.performUpdateAssetInfoWithProofs, td.createDiffUpdateAssetInfoWithProofs, tf.minerFeeUpdateAssetInfoWithProofs, + tc.checkUpdateAssetInfoWithProofs, tp.performUpdateAssetInfoWithProofs, + td.createDiffUpdateAssetInfoWithProofs, tf.minerFeeUpdateAssetInfoWithProofs, }, proto.TransactionTypeInfo{Type: proto.EthereumMetamaskTransaction, ProofVersion: proto.Proof}: txHandleFuncs{ - tc.checkEthereumTransactionWithProofs, tp.performEthereumTransactionWithProofs, td.createDiffEthereumTransactionWithProofs, tf.minerFeeEthereumTxWithProofs, + tc.checkEthereumTransactionWithProofs, tp.performEthereumTransactionWithProofs, + td.createDiffEthereumTransactionWithProofs, tf.minerFeeEthereumTxWithProofs, }, } } @@ -143,8 +170,7 @@ func newTransactionHandler( if err != nil { return nil, err } - snapshotGenerator := &snapshotGenerator{stor: stor, settings: settings} - tp, err := newTransactionPerformer(stor, settings, snapshotGenerator) + tp, err := newTransactionPerformer(stor, settings) if err != nil { return nil, err } @@ -172,11 +198,12 @@ func (h *transactionHandler) checkTx(tx proto.Transaction, info *checkerInfo) (t return funcs.check(tx, info) } -func (h *transactionHandler) performTx(tx proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (h *transactionHandler) performTx(tx proto.Transaction, info *performerInfo, + invocationRes *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tv := tx.GetTypeInfo() funcs, ok := h.funcs[tv] if !ok { - return nil, 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", tx) } if funcs.perform == nil { // No perform func for this combination of transaction type and version. diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 0c50350ef..3dbe6bdf8 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -14,46 +14,66 @@ type performerInfo struct { height uint64 blockID proto.BlockID currentMinerAddress proto.WavesAddress - stateActionsCounter *proto.StateActionsCounter - // TODO put one into another - checkerData txCheckerData + checkerData txCheckerData } -func newPerformerInfo(height proto.Height, stateActionsCounter *proto.StateActionsCounter, blockID proto.BlockID, currentMinerAddress proto.WavesAddress, checkerData txCheckerData) *performerInfo { - return &performerInfo{height, blockID, currentMinerAddress, stateActionsCounter, checkerData} // all fields must be initialized +func newPerformerInfo(height proto.Height, + blockID proto.BlockID, currentMinerAddress proto.WavesAddress, + checkerData txCheckerData) *performerInfo { + return &performerInfo{height, blockID, + currentMinerAddress, + checkerData} // all fields must be initialized } type transactionPerformer struct { stor *blockchainEntitiesStorage settings *settings.BlockchainSettings - snapshotGenerator *snapshotGenerator + snapshotGenerator *snapshotGenerator // initialized in appendTx + snapshotApplier proto.SnapshotApplier // initialized in appendTx } -func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings.BlockchainSettings, snapshotGenerator *snapshotGenerator) (*transactionPerformer, error) { - return &transactionPerformer{stor, settings, snapshotGenerator}, nil +func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings.BlockchainSettings) (*transactionPerformer, error) { + return &transactionPerformer{stor: stor, settings: settings}, nil } -func (tp *transactionPerformer) performGenesis(transaction proto.Transaction, _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performGenesis( + transaction proto.Transaction, + _ *performerInfo, _ *invocationResult, + balanceChanges txDiff) (proto.TransactionSnapshot, error) { _, ok := transaction.(*proto.Genesis) if !ok { return nil, errors.New("failed to convert interface to genesis transaction") } - return tp.snapshotGenerator.generateSnapshotForGenesisTx(balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForGenesisTx(balanceChanges) + if err != nil { + return nil, err + } + return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performPayment(transaction proto.Transaction, _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performPayment(transaction proto.Transaction, _ *performerInfo, + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { _, ok := transaction.(*proto.Payment) if !ok { return nil, errors.New("failed to convert interface to payment transaction") } - return tp.snapshotGenerator.generateSnapshotForPaymentTx(balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForPaymentTx(balanceChanges) + if err != nil { + return nil, err + } + return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performTransfer(balanceChanges txDiff) (TransactionSnapshot, error) { - return tp.snapshotGenerator.generateSnapshotForTransferTx(balanceChanges) +func (tp *transactionPerformer) performTransfer(balanceChanges txDiff) (proto.TransactionSnapshot, error) { + snapshot, err := tp.snapshotGenerator.generateSnapshotForTransferTx(balanceChanges) + if err != nil { + return nil, err + } + return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transaction, _ *performerInfo, + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { _, ok := transaction.(*proto.TransferWithSig) if !ok { return nil, errors.New("failed to convert interface to transfer with sig transaction") @@ -61,7 +81,8 @@ func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transac return tp.performTransfer(balanceChanges) } -func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Transaction, _ *performerInfo, + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { _, ok := transaction.(*proto.TransferWithProofs) if !ok { return nil, errors.New("failed to convert interface to transfer with proofs transaction") @@ -69,16 +90,17 @@ func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Tran return tp.performTransfer(balanceChanges) } -func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest, assetID crypto.Digest, info *performerInfo, balanceChanges txDiff, scriptInformation *scriptInformation) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest, + assetID crypto.Digest, info *performerInfo, + balanceChanges txDiff, scriptInformation *scriptInformation) (proto.TransactionSnapshot, error) { blockHeight := info.height + 1 // Create new asset. assetInfo := &assetInfo{ assetConstInfo: assetConstInfo{ - tail: proto.DigestTail(assetID), - issuer: tx.SenderPK, - decimals: tx.Decimals, - issueHeight: blockHeight, - issueSequenceInBlock: info.stateActionsCounter.NextIssueActionNumber(), + tail: proto.DigestTail(assetID), + issuer: tx.SenderPK, + decimals: tx.Decimals, + issueHeight: blockHeight, }, assetChangeableInfo: assetChangeableInfo{ quantity: *big.NewInt(int64(tx.Quantity)), @@ -88,64 +110,58 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest reissuable: tx.Reissuable, }, } - - snapshot, err := tp.snapshotGenerator.generateSnapshotForIssueTx(assetID, txID, tx.SenderPK, *assetInfo, balanceChanges, scriptInformation) + snapshot, err := tp.snapshotGenerator.generateSnapshotForIssueTx(assetID, txID, tx.SenderPK, + *assetInfo, balanceChanges, scriptInformation) if err != nil { return nil, err } - - 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 + return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.IssueWithSig) if !ok { return nil, errors.New("failed to convert interface to IssueWithSig transaction") } txID, err := tx.GetID(tp.settings.AddressSchemeCharacter) if err != nil { - return nil, errors.Errorf("failed to get transaction ID: %v\n", err) + return nil, errors.Errorf("failed to get transaction ID: %v", err) } assetID, err := crypto.NewDigestFromBytes(txID) if err != nil { return nil, err } - if err := tp.stor.scriptsStorage.setAssetScript(assetID, proto.Script{}, tx.SenderPK, info.blockID); err != nil { - return nil, err - } return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges, nil) } -func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.IssueWithProofs) if !ok { return nil, errors.New("failed to convert interface to IssueWithProofs transaction") } txID, err := tx.GetID(tp.settings.AddressSchemeCharacter) if err != nil { - return nil, errors.Errorf("failed to get transaction ID: %v\n", err) + return nil, errors.Errorf("failed to get transaction ID: %v", err) } assetID, err := crypto.NewDigestFromBytes(txID) if err != nil { return nil, err } - if err := tp.stor.scriptsStorage.setAssetScript(assetID, tx.Script, tx.SenderPK, info.blockID); err != nil { - return nil, err - } - if se := info.checkerData.scriptEstimation; se.isPresent() { // script estimation is present and not nil - // Save complexities to storage, so we won't have to calculate it every time the script is called. - if scErr := tp.stor.scriptsComplexity.saveComplexitiesForAsset(assetID, *se, info.blockID); scErr != nil { - return nil, scErr + var se *scriptEstimation + var scriptInfo *scriptInformation + if se = info.checkerData.scriptEstimation; se.isPresent() { // script estimation is present and not nil + scriptInfo = &scriptInformation{ + script: tx.Script, + complexity: se.estimation.Verifier, } } return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges, scriptInfo) } -func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performReissue(tx *proto.Reissue, _ *performerInfo, + balanceChanges txDiff) (proto.TransactionSnapshot, error) { // Modify asset. change := &assetReissueChange{ reissuable: tx.Reissuable, @@ -156,14 +172,11 @@ func (tp *transactionPerformer) performReissue(tx *proto.Reissue, info *performe if err != nil { return nil, err } - - 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 + return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.ReissueWithSig) if !ok { return nil, errors.New("failed to convert interface to ReissueWithSig transaction") @@ -171,7 +184,8 @@ func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transact return tp.performReissue(&tx.Reissue, info, balanceChanges) } -func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Transaction, + info *performerInfo, _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.ReissueWithProofs) if !ok { return nil, errors.New("failed to convert interface to ReissueWithProofs transaction") @@ -179,7 +193,8 @@ func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Trans return tp.performReissue(&tx.Reissue, info, balanceChanges) } -func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performBurn(tx *proto.Burn, _ *performerInfo, + balanceChanges txDiff) (proto.TransactionSnapshot, error) { // Modify asset. change := &assetBurnChange{ diff: int64(tx.Amount), @@ -189,15 +204,11 @@ func (tp *transactionPerformer) performBurn(tx *proto.Burn, info *performerInfo, if err != nil { return nil, err } - - 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 + return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.BurnWithSig) if !ok { return nil, errors.New("failed to convert interface to BurnWithSig transaction") @@ -205,7 +216,8 @@ func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction return tp.performBurn(&tx.Burn, info, balanceChanges) } -func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.BurnWithProofs) if !ok { return nil, errors.New("failed to convert interface to BurnWithProofs transaction") @@ -213,15 +225,8 @@ func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transact return tp.performBurn(&tx.Burn, info, balanceChanges) } -func (tp *transactionPerformer) increaseOrderVolume(order proto.Order, fee uint64, volume uint64, info *performerInfo) error { - orderID, err := order.GetID() - if err != nil { - return err - } - return tp.stor.ordersVolumes.increaseFilled(orderID, volume, fee, info.blockID) -} - -func (tp *transactionPerformer) performExchange(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performExchange(transaction proto.Transaction, _ *performerInfo, + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(proto.Exchange) if !ok { return nil, errors.New("failed to convert interface to Exchange transaction") @@ -239,23 +244,16 @@ func (tp *transactionPerformer) performExchange(transaction proto.Transaction, i buyFee := tx.GetBuyMatcherFee() // snapshot must be generated before the state with orders is changed - snapshot, err := tp.snapshotGenerator.generateSnapshotForExchangeTx(sellOrder, sellFee, buyOrder, buyFee, volume, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForExchangeTx(sellOrder, + sellFee, buyOrder, buyFee, volume, balanceChanges) if err != nil { return nil, err } - - err = tp.increaseOrderVolume(sellOrder, sellFee, volume, info) - if err != nil { - return nil, err - } - err = tp.increaseOrderVolume(buyOrder, buyFee, volume, info) - if err != nil { - return nil, err - } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest, info *performerInfo, + balanceChanges txDiff) (proto.TransactionSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { return nil, err @@ -264,7 +262,7 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest if addr := tx.Recipient.Address(); addr == nil { recipientAddr, err = tp.stor.aliases.newestAddrByAlias(tx.Recipient.Alias().Alias) if err != nil { - return nil, errors.Errorf("invalid alias: %v\n", err) + return nil, errors.Errorf("invalid alias: %v", err) } } else { recipientAddr = *addr @@ -275,20 +273,17 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest Recipient: recipientAddr, Amount: tx.Amount, Height: info.height, - Status: LeaseActive, + Status: proto.LeaseActive, } snapshot, err := tp.snapshotGenerator.generateSnapshotForLeaseTx(*l, txID, txID, balanceChanges) if err != nil { - return nil, nil - } - - if err := tp.stor.leases.addLeasing(txID, l, info.blockID); err != nil { - return nil, errors.Wrap(err, "failed to add leasing") + return nil, err } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseWithSig) if !ok { return nil, errors.New("failed to convert interface to LeaseWithSig transaction") @@ -296,7 +291,8 @@ func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transactio return tp.performLease(&tx.Lease, *tx.ID, info, balanceChanges) } -func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseWithProofs) if !ok { return nil, errors.New("failed to convert interface to LeaseWithProofs transaction") @@ -304,23 +300,24 @@ func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transac return tp.performLease(&tx.Lease, *tx.ID, info, balanceChanges) } -func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID *crypto.Digest, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID *crypto.Digest, info *performerInfo, + balanceChanges txDiff) (proto.TransactionSnapshot, error) { oldLease, err := tp.stor.leases.newestLeasingInfo(tx.LeaseID) if err != nil { return nil, errors.Wrap(err, "failed to receiver leasing info") } - snapshot, err := tp.snapshotGenerator.generateSnapshotForLeaseCancelTx(txID, *oldLease, tx.LeaseID, *oldLease.OriginTransactionID, info.height, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForLeaseCancelTx(txID, + *oldLease, tx.LeaseID, *oldLease.OriginTransactionID, + info.height, balanceChanges) if err != nil { return nil, err } - 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 + return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseCancelWithSig) if !ok { return nil, errors.New("failed to convert interface to LeaseCancelWithSig transaction") @@ -328,7 +325,8 @@ func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Tran return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info, balanceChanges) } -func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.LeaseCancelWithProofs) if !ok { return nil, errors.New("failed to convert interface to LeaseCancelWithProofs transaction") @@ -336,7 +334,8 @@ func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.T return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info, balanceChanges) } -func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info *performerInfo, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, + _ *performerInfo, balanceChanges txDiff) (proto.TransactionSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { return nil, err @@ -346,13 +345,11 @@ func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, info * if err != nil { return nil, err } - if err := tp.stor.aliases.createAlias(tx.Alias.Alias, senderAddr, info.blockID); err != nil { - return nil, err - } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.CreateAliasWithSig) if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithSig transaction") @@ -360,7 +357,8 @@ func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Tran return tp.performCreateAlias(&tx.CreateAlias, info, balanceChanges) } -func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.CreateAliasWithProofs) if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") @@ -368,16 +366,21 @@ func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.T return tp.performCreateAlias(&tx.CreateAlias, info, balanceChanges) } -func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto.Transaction, _ *performerInfo, + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { _, ok := transaction.(*proto.MassTransferWithProofs) if !ok { return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") } - return tp.snapshotGenerator.generateSnapshotForMassTransferTx(balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForMassTransferTx(balanceChanges) + if err != nil { + return nil, err + } + return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { - +func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, + _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.DataWithProofs) if !ok { return nil, errors.New("failed to convert interface to DataWithProofs transaction") @@ -391,15 +394,11 @@ func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transact if err != nil { return nil, err } - for _, entry := range tx.Entries { - if err := tp.stor.accountsDataStor.appendEntry(senderAddr, entry, info.blockID); err != nil { - return nil, err - } - } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.Transaction, _ *performerInfo, + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.SponsorshipWithProofs) if !ok { return nil, errors.New("failed to convert interface to SponsorshipWithProofs transaction") @@ -409,13 +408,11 @@ func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.T if err != nil { return nil, err } - 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 + return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Transaction, info *performerInfo, + _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.SetScriptWithProofs) if !ok { return nil, errors.New("failed to convert interface to SetScriptWithProofs transaction") @@ -426,45 +423,17 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra return nil, errors.New("script estimations must be set for SetScriptWithProofs tx") } - snapshot, err := tp.snapshotGenerator.generateSnapshotForSetScriptTx(tx.SenderPK, tx.Script, complexity, info, balanceChanges) - if err != nil { - return nil, err - } - - if !se.isPresent() { - return nil, errors.New("script estimations must be set for SetScriptWithProofs tx") - } - // script estimation is present and not nil - err = storeScriptByAddress(tp.stor, tp.settings.AddressSchemeCharacter, tx.SenderPK, tx.Script, *se, info.blockID) + snapshot, err := tp.snapshotGenerator.generateSnapshotForSetScriptTx(tx.SenderPK, + tx.Script, *se, balanceChanges) if err != nil { - return nil, errors.Wrapf(err, "failed to perform SetScriptWithProofs tx %q", tx.ID.String()) + return nil, errors.Wrap(err, "failed to generate snapshot for set script tx") } - return snapshot, nil -} -func storeScriptByAddress( - stor *blockchainEntitiesStorage, - scheme proto.Scheme, - senderPK crypto.PublicKey, - script proto.Script, - se scriptEstimation, - blockID proto.BlockID, -) error { - senderAddr, err := proto.NewAddressFromPublicKey(scheme, senderPK) - if err != nil { - return errors.Wrapf(err, "failed to create addr from PK %q", senderPK.String()) - } - if setErr := stor.scriptsStorage.setAccountScript(senderAddr, script, senderPK, blockID); setErr != nil { - return errors.Wrapf(setErr, "failed to set account script on addr %q", senderAddr.String()) - } - // Save complexity to storage, so we won't have to calculate it every time the script is called. - if setErr := stor.scriptsComplexity.saveComplexitiesForAddr(senderAddr, se, blockID); setErr != nil { - return errors.Wrapf(setErr, "failed to save script complexities for addr %q", senderAddr.String()) - } - return nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction proto.Transaction, + info *performerInfo, _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.SetAssetScriptWithProofs) if !ok { return nil, errors.New("failed to convert interface to SetAssetScriptWithProofs transaction") @@ -475,194 +444,95 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot return nil, errors.New("script estimations must be set for SetAssetScriptWithProofs tx") } - snapshot, err := tp.snapshotGenerator.generateSnapshotForSetAssetScriptTx(tx.AssetID, tx.Script, se, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForSetAssetScriptTx(tx.AssetID, tx.Script, balanceChanges) if err != nil { return nil, err } - 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") - } + // TODO: generate special complexities snapshot for asset - 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") - } - // Save complexity to storage, so we won't have to calculate it every time the script is called. - if err = tp.stor.scriptsComplexity.saveComplexitiesForAsset(tx.AssetID, *se, info.blockID); err != nil { - return nil, errors.Wrapf(err, "failed to save script complexity for asset %q", tx.AssetID.String()) - } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } -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 _, ok := addrWavesBalanceDiff[recipientAddress]; ok { - prevRecipientBalance := addrWavesBalanceDiff[recipientAddress] - prevRecipientBalance.balance += amount - addrWavesBalanceDiff[recipientAddress] = prevRecipientBalance - } else { - addrWavesBalanceDiff[recipientAddress] = balanceDiff{balance: amount} - } -} - -// subtracts the amount from the sender's balance and add it to the recipient's balance. -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) performInvokeScriptWithProofs(transaction proto.Transaction, info *performerInfo) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto.Transaction, + info *performerInfo, + invocationRes *invocationResult, + balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.InvokeScriptWithProofs) if !ok { return nil, errors.New("failed to convert interface to InvokeScriptWithProofs transaction") } + if err := tp.stor.commitUncertain(info.blockID); err != nil { + return nil, errors.Wrapf(err, "failed to commit invoke changes for tx %q", tx.ID.String()) + } se := info.checkerData.scriptEstimation - if se.isPresent() { - // script estimation is present an not nil - - // we've pulled up an old script which estimation had been done by an old estimator - // in txChecker we've estimated script with a new estimator - // this is the place where we have to store new estimation - scriptAddr, err := recipientToAddress(tx.ScriptRecipient, tp.stor.aliases) - if err != nil { - return nil, errors.Wrap(err, "failed to get sender for InvokeScriptWithProofs") - } - // update callable and summary complexity, verifier complexity remains the same - if scErr := tp.stor.scriptsComplexity.updateCallableComplexitiesForAddr(scriptAddr, *se, info.blockID); scErr != nil { - return nil, errors.Wrapf(scErr, "failed to save complexity for addr %q in tx %q", - scriptAddr.String(), tx.ID.String(), - ) - } + if !se.isPresent() { // nothing to do, no estimation to save + return nil, nil } + // script estimation is present an not nil - txIDBytes, err := transaction.GetID(tp.settings.AddressSchemeCharacter) + // we've pulled up an old script which estimation had been done by an old estimator + // in txChecker we've estimated script with a new estimator + // this is the place where we have to store new estimation + scriptAddr, err := recipientToAddress(tx.ScriptRecipient, tp.stor.aliases) 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 + return nil, errors.Wrap(err, "failed to get sender for InvokeScriptWithProofs") } - - snapshot, err := tp.snapshotGenerator.generateSnapshotForInvokeScriptTx(txID, info, invocationRes, balanceChanges) - if err != nil { - return nil, errors.Wrap(err, "failed to generate a snapshot for an invoke transaction") + // update callable and summary complexity, verifier complexity remains the same + if scErr := tp.stor.scriptsComplexity.updateCallableComplexitiesForAddr(scriptAddr, *se, info.blockID); scErr != nil { + return nil, errors.Wrapf(scErr, "failed to save complexity for addr %q in tx %q", + scriptAddr.String(), tx.ID.String(), + ) } - - return snapshot, nil + _ = invocationRes + _ = balanceChanges + return nil, nil } -func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, + info *performerInfo, invocationRes *invocationResult, + balanceChanges txDiff) (proto.TransactionSnapshot, error) { if _, ok := transaction.(*proto.InvokeExpressionTransactionWithProofs); !ok { return nil, errors.New("failed to convert interface to InvokeExpressionWithProofs 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 - } - - return tp.snapshotGenerator.generateSnapshotForInvokeExpressionTx(txID, info, invocationRes, balanceChanges) + _ = invocationRes + _ = balanceChanges + return nil, nil } -func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo, + invocationRes *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { ethTx, ok := transaction.(*proto.EthereumTransaction) if !ok { 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 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.snapshotGenerator.generateSnapshotForEthereumInvokeScriptTx(txID, info, invocationRes, balanceChanges) - if err != nil { - return nil, errors.Wrap(err, "failed to generate a snapshot for an invoke transaction") - } - - return snapshot, nil + _ = invocationRes + _ = balanceChanges + // nothing to do for proto.EthereumTransferWavesTxKind and proto.EthereumTransferAssetsErc20TxKind + return nil, nil } -func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction proto.Transaction, info *performerInfo, _ *invocationResult, balanceChanges txDiff) (TransactionSnapshot, error) { +func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction proto.Transaction, + info *performerInfo, _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { tx, ok := transaction.(*proto.UpdateAssetInfoWithProofs) if !ok { return nil, errors.New("failed to convert interface to UpdateAssetInfoWithProofs transaction") } blockHeight := info.height + 1 - ch := &assetInfoChange{ - newName: tx.Name, - newDescription: tx.Description, - newHeight: blockHeight, - } - snapshot, err := tp.snapshotGenerator.generateSnapshotForUpdateAssetInfoTx(tx.AssetID, tx.Name, tx.Description, blockHeight, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForUpdateAssetInfoTx(tx.AssetID, + tx.Name, tx.Description, blockHeight, balanceChanges) if err != nil { return nil, err } - if err := tp.stor.assets.updateAssetInfo(tx.AssetID, ch, info.blockID); err != nil { - return nil, errors.Wrap(err, "failed to update asset info") - } - return snapshot, nil + return snapshot, snapshot.Apply(tp.snapshotApplier) } diff --git a/pkg/state/transaction_performer_test.go b/pkg/state/transaction_performer_test.go index e8338f357..cdd8f183c 100644 --- a/pkg/state/transaction_performer_test.go +++ b/pkg/state/transaction_performer_test.go @@ -8,7 +8,6 @@ import ( "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" @@ -16,28 +15,63 @@ import ( ) type performerTestObjects struct { - stor *testStorageObjects - tp *transactionPerformer + stor *testStorageObjects + tp *transactionPerformer + stateActionsCounter *proto.StateActionsCounter } -func createPerformerTestObjects(t *testing.T) *performerTestObjects { +func createPerformerTestObjects(t *testing.T, checkerInfo *checkerInfo) *performerTestObjects { stor := createStorageObjects(t, true) - snapshotGenerator := &snapshotGenerator{stor.entities, settings.MainNetSettings} - tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings, snapshotGenerator) + tp, err := newTransactionPerformer(stor.entities, settings.MainNetSettings) + + actionsCounter := new(proto.StateActionsCounter) + + snapshotApplier := newBlockSnapshotsApplier( + blockSnapshotsApplierInfo{ + ci: checkerInfo, + scheme: settings.MainNetSettings.AddressSchemeCharacter, + stateActionsCounter: actionsCounter, + }, + snapshotApplierStorages{ + balances: stor.entities.balances, + aliases: stor.entities.aliases, + assets: stor.entities.assets, + scriptsStorage: stor.entities.scriptsStorage, + scriptsComplexity: stor.entities.scriptsComplexity, + sponsoredAssets: stor.entities.sponsoredAssets, + ordersVolumes: stor.entities.ordersVolumes, + accountsDataStor: stor.entities.accountsDataStor, + leases: stor.entities.leases, + }, + ) + snapshotGen := snapshotGenerator{stor: stor.entities, scheme: settings.MainNetSettings.AddressSchemeCharacter} + tp.snapshotApplier = &snapshotApplier + tp.snapshotGenerator = &snapshotGen require.NoError(t, err, "newTransactionPerformer() failed") - return &performerTestObjects{stor, tp} + return &performerTestObjects{stor, tp, actionsCounter} } -func defaultPerformerInfo() *performerInfo { - return newPerformerInfo(0, new(proto.StateActionsCounter), blockID0, proto.WavesAddress{}, txCheckerData{}) +func defaultPerformerInfo(stateActionsCounter *proto.StateActionsCounter) *performerInfo { + _ = stateActionsCounter + return newPerformerInfo(0, blockID0, proto.WavesAddress{}, txCheckerData{}) } -func TestPerformIssueWithSig(t *testing.T) { - to := createPerformerTestObjects(t) +func defaultCheckerInfoHeight0() *checkerInfo { + return &checkerInfo{ + currentTimestamp: defaultTimestamp, + parentTimestamp: defaultTimestamp - settings.MainNetSettings.MaxTxTimeBackOffset/2, + blockID: blockID0, + blockVersion: 1, + height: 0, + } +} +func TestPerformIssueWithSig(t *testing.T) { + checkerInfo := defaultCheckerInfoHeight0() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createIssueWithSig(t, 1000) - _, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performIssueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performIssueWithSig() failed") to.stor.flush(t) expectedAssetInfo := assetInfo{ @@ -64,12 +98,12 @@ func TestPerformIssueWithSig(t *testing.T) { } func TestPerformIssueWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) - + checkerInfo := defaultCheckerInfoHeight0() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createIssueWithProofs(t, 1000) - _, err := to.tp.performIssueWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performIssueWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performIssueWithProofs() failed") to.stor.flush(t) expectedAssetInfo := assetInfo{ @@ -96,11 +130,13 @@ func TestPerformIssueWithProofs(t *testing.T) { } func TestPerformReissueWithSig(t *testing.T) { - to := createPerformerTestObjects(t) + + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithSig(t, 1000) - _, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performReissueWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performReissueWithSig() failed") to.stor.flush(t) assetInfo.reissuable = tx.Reissuable @@ -113,11 +149,12 @@ func TestPerformReissueWithSig(t *testing.T) { } func TestPerformReissueWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createReissueWithProofs(t, 1000) - _, err := to.tp.performReissueWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performReissueWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performReissueWithProofs() failed") to.stor.flush(t) assetInfo.reissuable = tx.Reissuable @@ -130,11 +167,12 @@ func TestPerformReissueWithProofs(t *testing.T) { } func TestPerformBurnWithSig(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithSig(t) - _, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performBurnWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performBurnWithSig() failed") to.stor.flush(t) assetInfo.quantity.Sub(&assetInfo.quantity, big.NewInt(int64(tx.Amount))) @@ -146,11 +184,12 @@ func TestPerformBurnWithSig(t *testing.T) { } func TestPerformBurnWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createBurnWithProofs(t) - _, err := to.tp.performBurnWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performBurnWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performBurnWithProofs() failed") to.stor.flush(t) assetInfo.quantity.Sub(&assetInfo.quantity, big.NewInt(int64(tx.Amount))) @@ -162,11 +201,12 @@ func TestPerformBurnWithProofs(t *testing.T) { } func TestPerformExchange(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createExchangeWithSig(t) - _, err := to.tp.performExchange(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performExchange(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performExchange() failed") sellOrderID, err := tx.GetOrder2().GetID() @@ -199,16 +239,17 @@ func TestPerformExchange(t *testing.T) { } func TestPerformLeaseWithSig(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createLeaseWithSig(t) - _, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performLeaseWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseWithSig() failed") to.stor.flush(t) leasingInfo := &leasing{ OriginTransactionID: tx.ID, - Status: LeaseActive, + Status: proto.LeaseActive, Amount: tx.Amount, Recipient: *tx.Recipient.Address(), Sender: testGlobal.senderInfo.addr, @@ -220,16 +261,17 @@ func TestPerformLeaseWithSig(t *testing.T) { } func TestPerformLeaseWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createLeaseWithProofs(t) - _, err := to.tp.performLeaseWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performLeaseWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseWithProofs() failed") to.stor.flush(t) leasingInfo := &leasing{ OriginTransactionID: tx.ID, - Status: LeaseActive, + Status: proto.LeaseActive, Amount: tx.Amount, Recipient: *tx.Recipient.Address(), Sender: testGlobal.senderInfo.addr, @@ -241,23 +283,24 @@ func TestPerformLeaseWithProofs(t *testing.T) { } func TestPerformLeaseCancelWithSig(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) leaseTx := createLeaseWithSig(t) - _, err := to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performLeaseWithSig(leaseTx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseWithSig() failed") to.stor.flush(t) tx := createLeaseCancelWithSig(t, *leaseTx.ID) leasingInfo := &leasing{ OriginTransactionID: leaseTx.ID, - Status: LeaseCanceled, + Status: proto.LeaseCanceled, Amount: leaseTx.Amount, Recipient: *leaseTx.Recipient.Address(), Sender: testGlobal.senderInfo.addr, CancelTransactionID: tx.ID, } - _, err = to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performLeaseCancelWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseCancelWithSig() failed") to.stor.flush(t) info, err := to.stor.entities.leases.leasingInfo(*leaseTx.ID) @@ -266,23 +309,24 @@ func TestPerformLeaseCancelWithSig(t *testing.T) { } func TestPerformLeaseCancelWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) leaseTx := createLeaseWithProofs(t) - _, err := to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performLeaseWithProofs(leaseTx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseWithProofs() failed") to.stor.flush(t) tx := createLeaseCancelWithProofs(t, *leaseTx.ID) leasingInfo := &leasing{ OriginTransactionID: leaseTx.ID, - Status: LeaseCanceled, + Status: proto.LeaseCanceled, Amount: leaseTx.Amount, Recipient: *leaseTx.Recipient.Address(), Sender: testGlobal.senderInfo.addr, CancelTransactionID: tx.ID, } - _, err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performLeaseCancelWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performLeaseCancelWithProofs() failed") to.stor.flush(t) info, err := to.stor.entities.leases.leasingInfo(*leaseTx.ID) @@ -291,11 +335,12 @@ func TestPerformLeaseCancelWithProofs(t *testing.T) { } func TestPerformCreateAliasWithSig(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createCreateAliasWithSig(t) - _, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performCreateAliasWithSig() failed") to.stor.flush(t) addr, err := to.stor.entities.aliases.addrByAlias(tx.Alias.Alias) @@ -303,7 +348,7 @@ func TestPerformCreateAliasWithSig(t *testing.T) { assert.Equal(t, testGlobal.senderInfo.addr, addr, "invalid address by alias after performing CreateAliasWithSig transaction") // Test stealing aliases. - _, err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performCreateAliasWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performCreateAliasWithSig() failed") to.stor.flush(t) err = to.stor.entities.aliases.disableStolenAliases(blockID0) @@ -314,11 +359,12 @@ func TestPerformCreateAliasWithSig(t *testing.T) { } func TestPerformCreateAliasWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createCreateAliasWithProofs(t) - _, err := to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performCreateAliasWithProofs() failed") to.stor.flush(t) addr, err := to.stor.entities.aliases.addrByAlias(tx.Alias.Alias) @@ -326,7 +372,7 @@ func TestPerformCreateAliasWithProofs(t *testing.T) { assert.Equal(t, testGlobal.senderInfo.addr, addr, "invalid address by alias after performing CreateAliasWithProofs transaction") // Test stealing aliases. - _, err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err = to.tp.performCreateAliasWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performCreateAliasWithProofs() failed") to.stor.flush(t) err = to.stor.entities.aliases.disableStolenAliases(blockID0) @@ -337,7 +383,8 @@ func TestPerformCreateAliasWithProofs(t *testing.T) { } func TestPerformDataWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) @@ -345,7 +392,7 @@ func TestPerformDataWithProofs(t *testing.T) { entry := &proto.IntegerDataEntry{Key: "TheKey", Value: int64(666)} tx.Entries = []proto.DataEntry{entry} - _, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performDataWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performDataWithProofs() failed") to.stor.flush(t) @@ -355,12 +402,13 @@ func TestPerformDataWithProofs(t *testing.T) { } func TestPerformSponsorshipWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createSponsorshipWithProofs(t, 1000) - _, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performSponsorshipWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performSponsorshipWithProofs() failed") assetID := proto.AssetIDFromDigest(tx.AssetID) @@ -398,7 +446,8 @@ func TestPerformSponsorshipWithProofs(t *testing.T) { } func TestPerformSetScriptWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) @@ -420,10 +469,10 @@ func TestPerformSetScriptWithProofs(t *testing.T) { require.NoError(t, err) tx := createSetScriptWithProofs(t, scriptBytes) - pi := *defaultPerformerInfo() - + pi := *defaultPerformerInfo(to.stateActionsCounter) pi.checkerData.scriptEstimation = &scriptEstimation{} - _, err = to.tp.performSetScriptWithProofs(tx, &pi) + _, err = to.tp.performSetScriptWithProofs(tx, &pi, nil, nil) + assert.NoError(t, err, "performSetScriptWithProofs() failed") addr := testGlobal.senderInfo.addr @@ -487,12 +536,13 @@ func TestPerformSetScriptWithProofs(t *testing.T) { } func TestPerformSetAssetScriptWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) to.stor.addBlock(t, blockID0) tx := createSetAssetScriptWithProofs(t) - pi := *defaultPerformerInfo() + pi := *defaultPerformerInfo(to.stateActionsCounter) currentEstimatorVersion := 4 tree, err := serialization.Parse(tx.Script) @@ -505,6 +555,7 @@ func TestPerformSetAssetScriptWithProofs(t *testing.T) { scriptIsEmpty: false, estimation: estimation, } + checkerInfo.blockID = blockID0 _, err = to.tp.performSetAssetScriptWithProofs(tx, &pi, nil, nil) assert.NoError(t, err, "performSetAssetScriptWithProofs() failed") @@ -545,7 +596,7 @@ func TestPerformSetAssetScriptWithProofs(t *testing.T) { assert.Equal(t, testGlobal.scriptAst, scriptAst) // Test discarding script. - err = to.stor.entities.scriptsStorage.setAssetScript(fullAssetID, proto.Script{}, crypto.PublicKey{}, blockID0) + err = to.stor.entities.scriptsStorage.setAssetScript(fullAssetID, proto.Script{}, blockID0) assert.NoError(t, err, "setAssetScript() failed") // Test newest before flushing. @@ -581,11 +632,12 @@ func TestPerformSetAssetScriptWithProofs(t *testing.T) { } func TestPerformUpdateAssetInfoWithProofs(t *testing.T) { - to := createPerformerTestObjects(t) + checkerInfo := defaultCheckerInfo() + to := createPerformerTestObjects(t, checkerInfo) assetInfo := to.stor.createAsset(t, testGlobal.asset0.asset.ID) tx := createUpdateAssetInfoWithProofs(t) - _, err := to.tp.performUpdateAssetInfoWithProofs(tx, defaultPerformerInfo(), nil, nil) + _, err := to.tp.performUpdateAssetInfoWithProofs(tx, defaultPerformerInfo(to.stateActionsCounter), nil, nil) assert.NoError(t, err, "performUpdateAssetInfoWithProofs() failed") to.stor.flush(t) assetInfo.name = tx.Name From d664e8045a0f98ccdf42940826ca6a49187d63fe Mon Sep 17 00:00:00 2001 From: esuwu Date: Sun, 29 Oct 2023 17:10:37 -0500 Subject: [PATCH 080/139] Added asset script special snapshot --- pkg/state/internal_snapshots_types.go | 71 +++++++++++++++++++ pkg/state/snapshot_applier.go | 56 +++++++++------ pkg/state/snapshot_generator.go | 38 +++------- pkg/state/snapshot_generator_internal_test.go | 12 +++- pkg/state/transaction_performer.go | 4 +- 5 files changed, 122 insertions(+), 59 deletions(-) create mode 100644 pkg/state/internal_snapshots_types.go diff --git a/pkg/state/internal_snapshots_types.go b/pkg/state/internal_snapshots_types.go new file mode 100644 index 000000000..0bbdc2304 --- /dev/null +++ b/pkg/state/internal_snapshots_types.go @@ -0,0 +1,71 @@ +package state + +import ( + "github.com/wavesplatform/gowaves/pkg/crypto" + "github.com/wavesplatform/gowaves/pkg/proto" + "github.com/wavesplatform/gowaves/pkg/ride" +) + +/* +Below are internal snapshots only. +They are not necessary and used for optimization, initialized in the full node mode only. +*/ +type InternalDAppComplexitySnapshot struct { + ScriptAddress proto.WavesAddress + Estimation ride.TreeEstimation + ScriptIsEmpty bool +} + +func (s InternalDAppComplexitySnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s InternalDAppComplexitySnapshot) Apply(a proto.SnapshotApplier) error { + return a.ApplyInternalSnapshot(&s) +} + +func (s InternalDAppComplexitySnapshot) IsInternal() bool { + return true +} + +func (s InternalDAppComplexitySnapshot) InternalSnapshotMarker() {} + +type InternalDAppUpdateComplexitySnapshot struct { + ScriptAddress proto.WavesAddress + Estimation ride.TreeEstimation + ScriptIsEmpty bool +} + +func (s InternalDAppUpdateComplexitySnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s InternalDAppUpdateComplexitySnapshot) Apply(a proto.SnapshotApplier) error { + return a.ApplyInternalSnapshot(&s) +} + +func (s InternalDAppUpdateComplexitySnapshot) IsInternal() bool { + return true +} + +func (s InternalDAppUpdateComplexitySnapshot) InternalSnapshotMarker() {} + +type InternalAssetScriptComplexitySnapshot struct { + AssetID crypto.Digest + Estimation ride.TreeEstimation + ScriptIsEmpty bool +} + +func (s InternalAssetScriptComplexitySnapshot) IsGeneratedByTxDiff() bool { + return false +} + +func (s InternalAssetScriptComplexitySnapshot) Apply(a proto.SnapshotApplier) error { + return a.ApplyInternalSnapshot(&s) +} + +func (s InternalAssetScriptComplexitySnapshot) IsInternal() bool { + return true +} + +func (s InternalAssetScriptComplexitySnapshot) InternalSnapshotMarker() {} diff --git a/pkg/state/snapshot_applier.go b/pkg/state/snapshot_applier.go index 339bebeeb..96e2db2a9 100644 --- a/pkg/state/snapshot_applier.go +++ b/pkg/state/snapshot_applier.go @@ -240,35 +240,45 @@ func (a *blockSnapshotsApplier) ApplyTransactionsStatus(_ proto.TransactionStatu func (a *blockSnapshotsApplier) ApplyInternalSnapshot( internalSnapshot proto.InternalSnapshot) error { - /* If you want to add more internal snapshots, - //you should add a switch here iterating through all possible internal snapshots. */ - internalDappComplexitySnapshot, ok := internalSnapshot.(*InternalDAppComplexitySnapshot) - if !ok { - return errors.New("failed to convert interface to internal dapp complexity snapshot") - } - scriptEstimation := scriptEstimation{currentEstimatorVersion: a.info.EstimatorVersion(), - scriptIsEmpty: internalDappComplexitySnapshot.ScriptIsEmpty, estimation: internalDappComplexitySnapshot.Estimation} - if !internalDappComplexitySnapshot.Update { + switch snapshot := internalSnapshot.(type) { + case *InternalDAppComplexitySnapshot: + scriptEstimation := scriptEstimation{currentEstimatorVersion: a.info.EstimatorVersion(), + scriptIsEmpty: snapshot.ScriptIsEmpty, estimation: snapshot.Estimation} // Save full complexity of both callable and verifier when the script is set first time - if setErr := a.stor.scriptsComplexity.saveComplexitiesForAddr(internalDappComplexitySnapshot.ScriptAddress, + if setErr := a.stor.scriptsComplexity.saveComplexitiesForAddr(snapshot.ScriptAddress, scriptEstimation, a.info.BlockID()); setErr != nil { return errors.Wrapf(setErr, "failed to save script complexities for addr %q", - internalDappComplexitySnapshot.ScriptAddress.String()) + snapshot.ScriptAddress.String()) } return nil - } - // we've pulled up an old script which estimation had been done by an old estimator - // in txChecker we've estimated script with a new estimator - // this is the place where we have to store new estimation - - // update callable and summary complexity, verifier complexity remains the same - if scErr := a.stor.scriptsComplexity.updateCallableComplexitiesForAddr( - internalDappComplexitySnapshot.ScriptAddress, - scriptEstimation, a.info.BlockID()); scErr != nil { - return errors.Wrapf(scErr, "failed to save complexity for addr %q", - internalDappComplexitySnapshot.ScriptAddress, - ) + case InternalDAppUpdateComplexitySnapshot: + scriptEstimation := scriptEstimation{currentEstimatorVersion: a.info.EstimatorVersion(), + scriptIsEmpty: snapshot.ScriptIsEmpty, estimation: snapshot.Estimation} + // we've pulled up an old script which estimation had been done by an old estimator + // in txChecker we've estimated script with a new estimator + // this is the place where we have to store new estimation + // update callable and summary complexity, verifier complexity remains the same + if scErr := a.stor.scriptsComplexity.updateCallableComplexitiesForAddr( + snapshot.ScriptAddress, + scriptEstimation, a.info.BlockID()); scErr != nil { + return errors.Wrapf(scErr, "failed to save complexity for addr %q", + snapshot.ScriptAddress, + ) + } + case *InternalAssetScriptComplexitySnapshot: + scriptEstimation := scriptEstimation{currentEstimatorVersion: a.info.EstimatorVersion(), + scriptIsEmpty: snapshot.ScriptIsEmpty, estimation: snapshot.Estimation} + // Save full complexity of both callable and verifier when the script is set first time + if setErr := a.stor.scriptsComplexity.saveComplexitiesForAsset(snapshot.AssetID, + scriptEstimation, a.info.BlockID()); setErr != nil { + return errors.Wrapf(setErr, "failed to save script complexities for asset ID %q", + snapshot.AssetID.String()) + } + return nil + default: + return errors.New("failed to apply internal snapshot, unknown type") } + return nil } diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index c32a75c76..4797fbd3e 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -7,7 +7,6 @@ import ( "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" - "github.com/wavesplatform/gowaves/pkg/ride" ) type snapshotGenerator struct { @@ -26,31 +25,6 @@ type assetBalanceDiffKey struct { } type addressAssetBalanceDiff map[assetBalanceDiffKey]int64 -/* -Below are internal snapshots only. -They are not necessary and used for optimization, initialized in the full node mode only. -*/ -type InternalDAppComplexitySnapshot struct { - ScriptAddress proto.WavesAddress - Estimation ride.TreeEstimation - ScriptIsEmpty bool - Update bool -} - -func (s InternalDAppComplexitySnapshot) IsGeneratedByTxDiff() bool { - return false -} - -func (s InternalDAppComplexitySnapshot) Apply(a proto.SnapshotApplier) error { - return a.ApplyInternalSnapshot(&s) -} - -func (s InternalDAppComplexitySnapshot) IsInternal() bool { - return true -} - -func (s InternalDAppComplexitySnapshot) InternalSnapshotMarker() {} - func (sg *snapshotGenerator) generateSnapshotForGenesisTx(balanceChanges txDiff) (proto.TransactionSnapshot, error) { return sg.generateBalancesSnapshot(balanceChanges) } @@ -333,8 +307,7 @@ func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.Publ return nil, errors.Wrap(cnvrtErr, "failed to get sender for InvokeScriptWithProofs") } internalComplexitySnapshot := InternalDAppComplexitySnapshot{ - Estimation: scriptEstimation.estimation, ScriptAddress: scriptAddr, - Update: false, ScriptIsEmpty: scriptEstimation.scriptIsEmpty} + Estimation: scriptEstimation.estimation, ScriptAddress: scriptAddr, ScriptIsEmpty: scriptEstimation.scriptIsEmpty} snapshot = append(snapshot, &internalComplexitySnapshot) } @@ -342,7 +315,7 @@ func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.Publ } func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, - balanceChanges txDiff) (proto.TransactionSnapshot, error) { + balanceChanges txDiff, scriptEstimation scriptEstimation) (proto.TransactionSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { return nil, err @@ -352,8 +325,13 @@ func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto. AssetID: assetID, Script: script, } - // TODO generate a special snapshot complexity here snapshot = append(snapshot, assetScrptSnapshot) + if sg.IsFullNodeMode { + internalComplexitySnapshot := InternalAssetScriptComplexitySnapshot{ + Estimation: scriptEstimation.estimation, AssetID: assetID, + ScriptIsEmpty: scriptEstimation.scriptIsEmpty} + snapshot = append(snapshot, &internalComplexitySnapshot) + } return snapshot, nil } diff --git a/pkg/state/snapshot_generator_internal_test.go b/pkg/state/snapshot_generator_internal_test.go index 3cc227b83..eb999c8be 100644 --- a/pkg/state/snapshot_generator_internal_test.go +++ b/pkg/state/snapshot_generator_internal_test.go @@ -892,7 +892,6 @@ func TestDefaultSetDappScriptSnapshot(t *testing.T) { ScriptAddress: testGlobal.senderInfo.addr, Estimation: ride.TreeEstimation{Estimation: 36, Verifier: 0, Functions: map[string]int{"call": 36}}, ScriptIsEmpty: false, - Update: false, }, } @@ -962,7 +961,6 @@ func TestDefaultSetScriptSnapshot(t *testing.T) { &InternalDAppComplexitySnapshot{ ScriptAddress: testGlobal.senderInfo.addr, Estimation: ride.TreeEstimation{Estimation: 340, Verifier: 340}, - Update: false, }, } @@ -1032,7 +1030,6 @@ func TestDefaultSetEmptyScriptSnapshot(t *testing.T) { &InternalDAppComplexitySnapshot{ ScriptAddress: testGlobal.senderInfo.addr, Estimation: ride.TreeEstimation{Estimation: 0, Verifier: 0}, - Update: false, ScriptIsEmpty: true, }, } @@ -1110,6 +1107,15 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.T) { AssetID: testGlobal.asset0.assetID, Script: testGlobal.scriptBytes, }, + &InternalAssetScriptComplexitySnapshot{ + AssetID: testGlobal.asset0.assetID, + Estimation: ride.TreeEstimation{ + Estimation: 340, + Verifier: 340, + Functions: nil, + }, + ScriptIsEmpty: false, + }, } var snapshotI []byte diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 3dbe6bdf8..a40ec431e 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -444,12 +444,10 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot return nil, errors.New("script estimations must be set for SetAssetScriptWithProofs tx") } - snapshot, err := tp.snapshotGenerator.generateSnapshotForSetAssetScriptTx(tx.AssetID, tx.Script, balanceChanges) + snapshot, err := tp.snapshotGenerator.generateSnapshotForSetAssetScriptTx(tx.AssetID, tx.Script, balanceChanges, *se) if err != nil { return nil, err } - // TODO: generate special complexities snapshot for asset - return snapshot, snapshot.Apply(tp.snapshotApplier) } From d2dc9bae5b83c9115d7c93c9d1cb19ab26c392ff Mon Sep 17 00:00:00 2001 From: esuwu Date: Sun, 29 Oct 2023 19:40:57 -0500 Subject: [PATCH 081/139] Added internal snapshot for script for issue tx --- pkg/state/snapshot_generator.go | 18 +++++++++--------- pkg/state/transaction_performer.go | 17 +++++------------ 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index 4797fbd3e..fb354b873 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -37,14 +37,9 @@ func (sg *snapshotGenerator) generateSnapshotForTransferTx(balanceChanges txDiff return sg.generateBalancesSnapshot(balanceChanges) } -type scriptInformation struct { - script proto.Script - complexity int -} - func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, txID crypto.Digest, senderPK crypto.PublicKey, assetInfo assetInfo, balanceChanges txDiff, - scriptInformation *scriptInformation) (proto.TransactionSnapshot, error) { + scriptEstimation *scriptEstimation, script *proto.Script) (proto.TransactionSnapshot, error) { var snapshot proto.TransactionSnapshot addrWavesBalanceDiff, addrAssetBalanceDiff, err := balanceDiffFromTxDiff(balanceChanges, sg.scheme) if err != nil { @@ -89,7 +84,7 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) - if scriptInformation == nil { + if script == nil { assetScriptSnapshot := &proto.AssetScriptSnapshot{ AssetID: assetID, Script: proto.Script{}, @@ -98,9 +93,14 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t } else { assetScriptSnapshot := &proto.AssetScriptSnapshot{ AssetID: assetID, - Script: scriptInformation.script, + Script: *script, + } + if sg.IsFullNodeMode && scriptEstimation.isPresent() { + internalComplexitySnapshot := InternalAssetScriptComplexitySnapshot{ + Estimation: scriptEstimation.estimation, AssetID: assetID, + ScriptIsEmpty: scriptEstimation.scriptIsEmpty} + snapshot = append(snapshot, &internalComplexitySnapshot) } - // TODO: special snapshot for complexity should be generated here snapshot = append(snapshot, assetScriptSnapshot) } wavesBalancesSnapshot, assetBalancesSnapshot, err := diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index a40ec431e..09d14c593 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -92,7 +92,7 @@ func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Tran func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest, assetID crypto.Digest, info *performerInfo, - balanceChanges txDiff, scriptInformation *scriptInformation) (proto.TransactionSnapshot, error) { + balanceChanges txDiff, scriptEstimation *scriptEstimation, script *proto.Script) (proto.TransactionSnapshot, error) { blockHeight := info.height + 1 // Create new asset. assetInfo := &assetInfo{ @@ -111,7 +111,7 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest }, } snapshot, err := tp.snapshotGenerator.generateSnapshotForIssueTx(assetID, txID, tx.SenderPK, - *assetInfo, balanceChanges, scriptInformation) + *assetInfo, balanceChanges, scriptEstimation, script) if err != nil { return nil, err } @@ -132,7 +132,7 @@ func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transactio if err != nil { return nil, err } - return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges, nil) + return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges, nil, nil) } func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transaction, info *performerInfo, @@ -149,15 +149,8 @@ func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transac if err != nil { return nil, err } - var se *scriptEstimation - var scriptInfo *scriptInformation - if se = info.checkerData.scriptEstimation; se.isPresent() { // script estimation is present and not nil - scriptInfo = &scriptInformation{ - script: tx.Script, - complexity: se.estimation.Verifier, - } - } - return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges, scriptInfo) + return tp.performIssue(&tx.Issue, assetID, assetID, info, + balanceChanges, info.checkerData.scriptEstimation, &tx.Script) } func (tp *transactionPerformer) performReissue(tx *proto.Reissue, _ *performerInfo, From 2487314ccfc9741fc43d3e808c92c6c4db462572 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Mon, 30 Oct 2023 12:13:41 +0300 Subject: [PATCH 082/139] add tx status snapshot to proto func --- pkg/proto/snapshot_types.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pkg/proto/snapshot_types.go b/pkg/proto/snapshot_types.go index 14ca728f6..86e787206 100644 --- a/pkg/proto/snapshot_types.go +++ b/pkg/proto/snapshot_types.go @@ -463,6 +463,20 @@ func (s TransactionStatusSnapshot) IsGeneratedByTxDiff() bool { return false } +func (s TransactionStatusSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) error { + switch s.Status { + case TransactionSucceeded: + txSnapshots.TransactionStatus = g.TransactionStatus_SUCCEEDED + case TransactionElided: + txSnapshots.TransactionStatus = g.TransactionStatus_ELIDED + case TransactionFailed: + txSnapshots.TransactionStatus = g.TransactionStatus_FAILED + default: + return errors.Errorf("Undefined tx status %d", s.Status) + } + return nil +} + type SnapshotApplier interface { ApplyWavesBalance(snapshot WavesBalanceSnapshot) error ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) error From bb0a9ee3fa3798e3349a084d3df3c4d11d30dc63 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Mon, 30 Oct 2023 14:24:49 +0300 Subject: [PATCH 083/139] remove unnecessary changes --- pkg/state/snapshot_applier.go | 2 -- pkg/state/snapshot_generator_internal_test.go | 2 ++ pkg/state/transaction_performer.go | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/state/snapshot_applier.go b/pkg/state/snapshot_applier.go index 840183a6e..96e2db2a9 100644 --- a/pkg/state/snapshot_applier.go +++ b/pkg/state/snapshot_applier.go @@ -4,7 +4,6 @@ import ( "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/proto" - "github.com/wavesplatform/gowaves/pkg/ride" ) @@ -163,7 +162,6 @@ func (a *blockSnapshotsApplier) ApplyAssetScript(snapshot proto.AssetScriptSnaps return a.stor.scriptsStorage.setAssetScript(snapshot.AssetID, proto.Script{}, a.info.BlockID()) } - return a.stor.scriptsStorage.setAssetScript(snapshot.AssetID, snapshot.Script, a.info.BlockID()) } diff --git a/pkg/state/snapshot_generator_internal_test.go b/pkg/state/snapshot_generator_internal_test.go index a64f7a532..eb999c8be 100644 --- a/pkg/state/snapshot_generator_internal_test.go +++ b/pkg/state/snapshot_generator_internal_test.go @@ -116,6 +116,7 @@ func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { } // TODO send only txBalanceChanges to perfomer + func TestDefaultIssueTransactionSnapshot(t *testing.T) { checkerInfo := customCheckerInfo() to := createDifferTestObjects(t, checkerInfo) @@ -1101,6 +1102,7 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.T) { Address: testGlobal.senderInfo.addr, Balance: 299900000, }, + &proto.AssetScriptSnapshot{ AssetID: testGlobal.asset0.assetID, Script: testGlobal.scriptBytes, diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index f41cb5b87..09d14c593 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -415,11 +415,13 @@ func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Tra if !se.isPresent() { return nil, errors.New("script estimations must be set for SetScriptWithProofs tx") } + snapshot, err := tp.snapshotGenerator.generateSnapshotForSetScriptTx(tx.SenderPK, tx.Script, *se, balanceChanges) if err != nil { return nil, errors.Wrap(err, "failed to generate snapshot for set script tx") } + return snapshot, snapshot.Apply(tp.snapshotApplier) } From 80ec830c280aee7630a2affcce193ae6b934aa49 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Mon, 30 Oct 2023 14:49:52 +0300 Subject: [PATCH 084/139] fix test --- pkg/state/history_storage.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/state/history_storage.go b/pkg/state/history_storage.go index 3448a36ed..cc26ee1d9 100644 --- a/pkg/state/history_storage.go +++ b/pkg/state/history_storage.go @@ -189,6 +189,11 @@ var properties = map[blockchainEntity]blockchainEntityProperties{ needToCut: true, fixedSize: false, }, + snapshots: { + needToFilter: true, + needToCut: true, + fixedSize: false, + }, } type historyEntry struct { From d525410024200128733a7527cfd21e8bf4c14e00 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Mon, 30 Oct 2023 20:34:44 +0300 Subject: [PATCH 085/139] Separated internal tx snapshots. --- pkg/proto/snapshot_types.go | 40 - pkg/state/appender.go | 40 +- pkg/state/internal_snapshots_types.go | 29 +- pkg/state/snapshot_applier.go | 83 +- pkg/state/snapshot_generator.go | 140 +-- pkg/state/snapshot_generator_internal_test.go | 907 +++++++----------- pkg/state/transaction_handler.go | 11 +- pkg/state/transaction_performer.go | 201 ++-- pkg/state/tx_snapshot.go | 38 + 9 files changed, 667 insertions(+), 822 deletions(-) create mode 100644 pkg/state/tx_snapshot.go diff --git a/pkg/proto/snapshot_types.go b/pkg/proto/snapshot_types.go index f89a2b271..35a264cc9 100644 --- a/pkg/proto/snapshot_types.go +++ b/pkg/proto/snapshot_types.go @@ -3,49 +3,9 @@ package proto import ( "math/big" - "github.com/pkg/errors" - "github.com/wavesplatform/gowaves/pkg/crypto" ) -type TransactionSnapshot []AtomicSnapshot - -func SplitSnapshots(atomicSnapshots []AtomicSnapshot) ([]AtomicSnapshot, []AtomicSnapshot) { - var snapshots []AtomicSnapshot - var internalSnapshots []AtomicSnapshot - for _, snapshot := range atomicSnapshots { - if !snapshot.IsInternal() { - snapshots = append(snapshots, snapshot) - } else { - internalSnapshots = append(internalSnapshots, snapshot) - } - } - return snapshots, internalSnapshots -} - -func (ts TransactionSnapshot) Apply(a SnapshotApplier) error { - mainSnapshots, internalSnapshots := SplitSnapshots(ts) - // internal snapshots must be applied at the end - for _, mainSnapshot := range mainSnapshots { - if !mainSnapshot.IsGeneratedByTxDiff() { - err := mainSnapshot.Apply(a) - if err != nil { - return errors.Wrap(err, "failed to apply main transaction snapshot") - } - } - } - - for _, internalSnapshot := range internalSnapshots { - if !internalSnapshot.IsGeneratedByTxDiff() { - err := internalSnapshot.Apply(a) - if err != nil { - return errors.Wrap(err, "failed to apply internal transaction snapshot") - } - } - } - return nil -} - type AtomicSnapshot interface { Apply(SnapshotApplier) error /* is temporarily used to mark snapshots generated by tx diff that shouldn't be applied, diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 55a1fbb99..552d739dd 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -14,8 +14,6 @@ import ( "github.com/wavesplatform/gowaves/pkg/types" ) -const snapshotLimit = 1000 - type blockInfoProvider interface { NewestBlockInfoByHeight(height proto.Height) (*proto.BlockInfo, error) } @@ -327,11 +325,11 @@ func (a *txAppender) commitTxApplication( tx proto.Transaction, params *appendTxParams, invocationRes *invocationResult, - applicationRes *applicationResult) (proto.TransactionSnapshot, error) { + applicationRes *applicationResult) (txSnapshot, error) { // Add transaction ID to recent IDs. txID, err := tx.GetID(a.settings.AddressSchemeCharacter) if err != nil { - return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to get tx id: %v", err)) + return txSnapshot{}, wrapErr(TxCommitmentError, errors.Errorf("failed to get tx id: %v", err)) } a.recentTxIds[string(txID)] = empty // Update script runs. @@ -340,11 +338,11 @@ func (a *txAppender) commitTxApplication( a.sc.addRecentTxComplexity() // Save balance diff. if err = a.diffStor.saveTxDiff(applicationRes.changes.diff); err != nil { - return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to save balance diff: %v", err)) + return txSnapshot{}, wrapErr(TxCommitmentError, errors.Errorf("failed to save balance diff: %v", err)) } currentMinerAddress := proto.MustAddressFromPublicKey(a.settings.AddressSchemeCharacter, params.currentMinerPK) - var snapshot proto.TransactionSnapshot + var snapshot txSnapshot if applicationRes.status { // We only perform tx in case it has not failed. performerInfo := &performerInfo{ @@ -355,22 +353,26 @@ func (a *txAppender) commitTxApplication( } snapshot, err = a.txHandler.performTx(tx, performerInfo, invocationRes, applicationRes.changes.diff) if err != nil { - return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to perform: %v", err)) + return txSnapshot{}, wrapErr(TxCommitmentError, errors.Errorf("failed to perform: %v", err)) } } if params.validatingUtx { // Save transaction to in-mem storage. 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)) + return txSnapshot{}, 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 nil, wrapErr(TxCommitmentError, errors.Errorf("failed to count miner fee: %v", err)) + return txSnapshot{}, wrapErr(TxCommitmentError, errors.Errorf("failed to count miner fee: %v", err)) } // Save transaction to storage. if err = a.rw.writeTransaction(tx, !applicationRes.status); err != nil { - return nil, wrapErr(TxCommitmentError, errors.Errorf("failed to write transaction to storage: %v", err)) + return txSnapshot{}, wrapErr(TxCommitmentError, + errors.Errorf("failed to write transaction to storage: %v", err), + ) } } // TODO: transaction status snapshot has to be appended here @@ -421,7 +423,7 @@ type appendTxParams struct { currentMinerPK crypto.PublicKey snapshotGenerator *snapshotGenerator - snapshotApplier proto.SnapshotApplier + snapshotApplier extendedSnapshotApplier } func (a *txAppender) handleInvokeOrExchangeTransaction( @@ -572,10 +574,8 @@ 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) > snapshotLimit { - zap.S().Debug(snapshot) - } + // TODO: a temporary dummy for linters + _ = 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 { @@ -586,24 +586,24 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) erro } // rewards and 60% of the fee to the previous miner. -func (a *txAppender) createInitialBlockSnapshot(minerAndRewardDiff txDiff) (proto.TransactionSnapshot, error) { +func (a *txAppender) createInitialBlockSnapshot(minerAndRewardDiff txDiff) (txSnapshot, error) { addrWavesBalanceDiff, _, err := balanceDiffFromTxDiff(minerAndRewardDiff, a.settings.AddressSchemeCharacter) if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + return txSnapshot{}, errors.Wrap(err, "failed to create balance diff from tx diff") } // add miner address to the diff - var snapshot proto.TransactionSnapshot + var snapshot txSnapshot for wavesAddress, diffAmount := range addrWavesBalanceDiff { var fullBalance balanceProfile fullBalance, err = a.stor.balances.wavesBalance(wavesAddress.ID()) if err != nil { - return nil, errors.Wrap(err, "failed to receive sender's waves balance") + return txSnapshot{}, errors.Wrap(err, "failed to receive sender's waves balance") } newBalance := &proto.WavesBalanceSnapshot{ Address: wavesAddress, Balance: uint64(int64(fullBalance.balance) + diffAmount.balance), } - snapshot = append(snapshot, newBalance) + snapshot.regular = append(snapshot.regular, newBalance) } return snapshot, nil } diff --git a/pkg/state/internal_snapshots_types.go b/pkg/state/internal_snapshots_types.go index 0bbdc2304..6652537ec 100644 --- a/pkg/state/internal_snapshots_types.go +++ b/pkg/state/internal_snapshots_types.go @@ -6,6 +6,17 @@ import ( "github.com/wavesplatform/gowaves/pkg/ride" ) +type internalSnapshot interface { + IsGeneratedByTxDiff() bool + ApplyInternal(internalSnapshotApplier) error +} + +type internalSnapshotApplier interface { + ApplyDAppComplexity(snapshot InternalDAppComplexitySnapshot) error + ApplyDAppUpdateComplexity(snapshot InternalDAppUpdateComplexitySnapshot) error + ApplyAssetScriptComplexity(snapshot InternalAssetScriptComplexitySnapshot) error +} + /* Below are internal snapshots only. They are not necessary and used for optimization, initialized in the full node mode only. @@ -24,11 +35,15 @@ func (s InternalDAppComplexitySnapshot) Apply(a proto.SnapshotApplier) error { return a.ApplyInternalSnapshot(&s) } +func (s InternalDAppComplexitySnapshot) ApplyInternal(a internalSnapshotApplier) error { + return a.ApplyDAppComplexity(s) +} + func (s InternalDAppComplexitySnapshot) IsInternal() bool { return true } -func (s InternalDAppComplexitySnapshot) InternalSnapshotMarker() {} +func (s *InternalDAppComplexitySnapshot) InternalSnapshotMarker() {} type InternalDAppUpdateComplexitySnapshot struct { ScriptAddress proto.WavesAddress @@ -44,11 +59,15 @@ func (s InternalDAppUpdateComplexitySnapshot) Apply(a proto.SnapshotApplier) err return a.ApplyInternalSnapshot(&s) } +func (s InternalDAppUpdateComplexitySnapshot) ApplyInternal(a internalSnapshotApplier) error { + return a.ApplyDAppUpdateComplexity(s) +} + func (s InternalDAppUpdateComplexitySnapshot) IsInternal() bool { return true } -func (s InternalDAppUpdateComplexitySnapshot) InternalSnapshotMarker() {} +func (s *InternalDAppUpdateComplexitySnapshot) InternalSnapshotMarker() {} type InternalAssetScriptComplexitySnapshot struct { AssetID crypto.Digest @@ -64,8 +83,12 @@ func (s InternalAssetScriptComplexitySnapshot) Apply(a proto.SnapshotApplier) er return a.ApplyInternalSnapshot(&s) } +func (s InternalAssetScriptComplexitySnapshot) ApplyInternal(a internalSnapshotApplier) error { + return a.ApplyAssetScriptComplexity(s) +} + func (s InternalAssetScriptComplexitySnapshot) IsInternal() bool { return true } -func (s InternalAssetScriptComplexitySnapshot) InternalSnapshotMarker() {} +func (s *InternalAssetScriptComplexitySnapshot) InternalSnapshotMarker() {} diff --git a/pkg/state/snapshot_applier.go b/pkg/state/snapshot_applier.go index 96e2db2a9..c3bac09ce 100644 --- a/pkg/state/snapshot_applier.go +++ b/pkg/state/snapshot_applier.go @@ -46,7 +46,7 @@ func newSnapshotApplierStorages(stor *blockchainEntitiesStorage) snapshotApplier } } -var _ = proto.SnapshotApplier((*blockSnapshotsApplier)(nil)) +var _ = extendedSnapshotApplier((*blockSnapshotsApplier)(nil)) type blockSnapshotsApplierInfo struct { ci *checkerInfo @@ -238,47 +238,56 @@ func (a *blockSnapshotsApplier) ApplyTransactionsStatus(_ proto.TransactionStatu return nil // no-op } -func (a *blockSnapshotsApplier) ApplyInternalSnapshot( - internalSnapshot proto.InternalSnapshot) error { +func (a *blockSnapshotsApplier) ApplyInternalSnapshot(internalSnapshot proto.InternalSnapshot) error { switch snapshot := internalSnapshot.(type) { case *InternalDAppComplexitySnapshot: - scriptEstimation := scriptEstimation{currentEstimatorVersion: a.info.EstimatorVersion(), - scriptIsEmpty: snapshot.ScriptIsEmpty, estimation: snapshot.Estimation} - // Save full complexity of both callable and verifier when the script is set first time - if setErr := a.stor.scriptsComplexity.saveComplexitiesForAddr(snapshot.ScriptAddress, - scriptEstimation, a.info.BlockID()); setErr != nil { - return errors.Wrapf(setErr, "failed to save script complexities for addr %q", - snapshot.ScriptAddress.String()) - } - return nil - - case InternalDAppUpdateComplexitySnapshot: - scriptEstimation := scriptEstimation{currentEstimatorVersion: a.info.EstimatorVersion(), - scriptIsEmpty: snapshot.ScriptIsEmpty, estimation: snapshot.Estimation} - // we've pulled up an old script which estimation had been done by an old estimator - // in txChecker we've estimated script with a new estimator - // this is the place where we have to store new estimation - // update callable and summary complexity, verifier complexity remains the same - if scErr := a.stor.scriptsComplexity.updateCallableComplexitiesForAddr( - snapshot.ScriptAddress, - scriptEstimation, a.info.BlockID()); scErr != nil { - return errors.Wrapf(scErr, "failed to save complexity for addr %q", - snapshot.ScriptAddress, - ) - } + return a.ApplyDAppComplexity(*snapshot) + case *InternalDAppUpdateComplexitySnapshot: + return a.ApplyDAppUpdateComplexity(*snapshot) case *InternalAssetScriptComplexitySnapshot: - scriptEstimation := scriptEstimation{currentEstimatorVersion: a.info.EstimatorVersion(), - scriptIsEmpty: snapshot.ScriptIsEmpty, estimation: snapshot.Estimation} - // Save full complexity of both callable and verifier when the script is set first time - if setErr := a.stor.scriptsComplexity.saveComplexitiesForAsset(snapshot.AssetID, - scriptEstimation, a.info.BlockID()); setErr != nil { - return errors.Wrapf(setErr, "failed to save script complexities for asset ID %q", - snapshot.AssetID.String()) - } - return nil + return a.ApplyAssetScriptComplexity(*snapshot) default: - return errors.New("failed to apply internal snapshot, unknown type") + return errors.Errorf("failed to apply internal snapshot, unknown type (%T)", snapshot) + } +} + +func (a *blockSnapshotsApplier) ApplyDAppComplexity(snapshot InternalDAppComplexitySnapshot) error { + scriptEstimation := scriptEstimation{currentEstimatorVersion: a.info.EstimatorVersion(), + scriptIsEmpty: snapshot.ScriptIsEmpty, estimation: snapshot.Estimation} + // Save full complexity of both callable and verifier when the script is set first time + if setErr := a.stor.scriptsComplexity.saveComplexitiesForAddr(snapshot.ScriptAddress, + scriptEstimation, a.info.BlockID()); setErr != nil { + return errors.Wrapf(setErr, "failed to save script complexities for addr %q", + snapshot.ScriptAddress.String()) + } + return nil +} + +func (a *blockSnapshotsApplier) ApplyDAppUpdateComplexity(snapshot InternalDAppUpdateComplexitySnapshot) error { + scriptEstimation := scriptEstimation{currentEstimatorVersion: a.info.EstimatorVersion(), + scriptIsEmpty: snapshot.ScriptIsEmpty, estimation: snapshot.Estimation} + // we've pulled up an old script which estimation had been done by an old estimator + // in txChecker we've estimated script with a new estimator + // this is the place where we have to store new estimation + // update callable and summary complexity, verifier complexity remains the same + if scErr := a.stor.scriptsComplexity.updateCallableComplexitiesForAddr( + snapshot.ScriptAddress, + scriptEstimation, a.info.BlockID()); scErr != nil { + return errors.Wrapf(scErr, "failed to save complexity for addr %q", + snapshot.ScriptAddress, + ) } + return nil +} +func (a *blockSnapshotsApplier) ApplyAssetScriptComplexity(snapshot InternalAssetScriptComplexitySnapshot) error { + scriptEstimation := scriptEstimation{currentEstimatorVersion: a.info.EstimatorVersion(), + scriptIsEmpty: snapshot.ScriptIsEmpty, estimation: snapshot.Estimation} + // Save full complexity of both callable and verifier when the script is set first time + if setErr := a.stor.scriptsComplexity.saveComplexitiesForAsset(snapshot.AssetID, + scriptEstimation, a.info.BlockID()); setErr != nil { + return errors.Wrapf(setErr, "failed to save script complexities for asset ID %q", + snapshot.AssetID.String()) + } return nil } diff --git a/pkg/state/snapshot_generator.go b/pkg/state/snapshot_generator.go index fb354b873..3417b4b98 100644 --- a/pkg/state/snapshot_generator.go +++ b/pkg/state/snapshot_generator.go @@ -25,25 +25,25 @@ type assetBalanceDiffKey struct { } type addressAssetBalanceDiff map[assetBalanceDiffKey]int64 -func (sg *snapshotGenerator) generateSnapshotForGenesisTx(balanceChanges txDiff) (proto.TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForGenesisTx(balanceChanges txDiff) (txSnapshot, error) { return sg.generateBalancesSnapshot(balanceChanges) } -func (sg *snapshotGenerator) generateSnapshotForPaymentTx(balanceChanges txDiff) (proto.TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForPaymentTx(balanceChanges txDiff) (txSnapshot, error) { return sg.generateBalancesSnapshot(balanceChanges) } -func (sg *snapshotGenerator) generateSnapshotForTransferTx(balanceChanges txDiff) (proto.TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForTransferTx(balanceChanges txDiff) (txSnapshot, error) { return sg.generateBalancesSnapshot(balanceChanges) } func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, txID crypto.Digest, senderPK crypto.PublicKey, assetInfo assetInfo, balanceChanges txDiff, - scriptEstimation *scriptEstimation, script *proto.Script) (proto.TransactionSnapshot, error) { - var snapshot proto.TransactionSnapshot + scriptEstimation *scriptEstimation, script *proto.Script) (txSnapshot, error) { + var snapshot txSnapshot addrWavesBalanceDiff, addrAssetBalanceDiff, err := balanceDiffFromTxDiff(balanceChanges, sg.scheme) if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + return txSnapshot{}, 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. @@ -82,14 +82,16 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t TotalQuantity: assetInfo.quantity, } - snapshot = append(snapshot, issueStaticInfoSnapshot, assetDescription, assetReissuability) + snapshot.regular = append(snapshot.regular, + issueStaticInfoSnapshot, assetDescription, assetReissuability, + ) if script == nil { assetScriptSnapshot := &proto.AssetScriptSnapshot{ AssetID: assetID, Script: proto.Script{}, } - snapshot = append(snapshot, assetScriptSnapshot) + snapshot.regular = append(snapshot.regular, assetScriptSnapshot) } else { assetScriptSnapshot := &proto.AssetScriptSnapshot{ AssetID: assetID, @@ -99,133 +101,135 @@ func (sg *snapshotGenerator) generateSnapshotForIssueTx(assetID crypto.Digest, t internalComplexitySnapshot := InternalAssetScriptComplexitySnapshot{ Estimation: scriptEstimation.estimation, AssetID: assetID, ScriptIsEmpty: scriptEstimation.scriptIsEmpty} - snapshot = append(snapshot, &internalComplexitySnapshot) + snapshot.internal = append(snapshot.internal, &internalComplexitySnapshot) } - snapshot = append(snapshot, assetScriptSnapshot) + snapshot.regular = append(snapshot.regular, assetScriptSnapshot) } wavesBalancesSnapshot, assetBalancesSnapshot, err := sg.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { - return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + return txSnapshot{}, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } for i := range wavesBalancesSnapshot { - snapshot = append(snapshot, &wavesBalancesSnapshot[i]) + snapshot.regular = append(snapshot.regular, &wavesBalancesSnapshot[i]) } for i := range assetBalancesSnapshot { - snapshot = append(snapshot, &assetBalancesSnapshot[i]) + snapshot.regular = append(snapshot.regular, &assetBalancesSnapshot[i]) } if specialAssetSnapshot != nil { - snapshot = append(snapshot, specialAssetSnapshot) + snapshot.regular = append(snapshot.regular, specialAssetSnapshot) } return snapshot, nil } func (sg *snapshotGenerator) generateSnapshotForReissueTx(assetID crypto.Digest, - change assetReissueChange, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + change assetReissueChange, balanceChanges txDiff) (txSnapshot, error) { quantityDiff := big.NewInt(change.diff) assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) if err != nil { - return nil, err + return txSnapshot{}, err } resQuantity := assetInfo.quantity.Add(&assetInfo.quantity, quantityDiff) snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { - return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") + return txSnapshot{}, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } assetReissuability := &proto.AssetVolumeSnapshot{ AssetID: assetID, TotalQuantity: *resQuantity, IsReissuable: change.reissuable, } - snapshot = append(snapshot, assetReissuability) + snapshot.regular = append(snapshot.regular, assetReissuability) return snapshot, nil } func (sg *snapshotGenerator) generateSnapshotForBurnTx(assetID crypto.Digest, change assetBurnChange, - balanceChanges txDiff) (proto.TransactionSnapshot, error) { + balanceChanges txDiff) (txSnapshot, error) { quantityDiff := big.NewInt(change.diff) assetInfo, err := sg.stor.assets.newestAssetInfo(proto.AssetIDFromDigest(assetID)) if err != nil { - return nil, err + return txSnapshot{}, err } resQuantity := assetInfo.quantity.Sub(&assetInfo.quantity, quantityDiff) snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { - return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") + return txSnapshot{}, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } assetReissuability := &proto.AssetVolumeSnapshot{ AssetID: assetID, TotalQuantity: *resQuantity, IsReissuable: assetInfo.reissuable, } - snapshot = append(snapshot, assetReissuability) + snapshot.regular = append(snapshot.regular, assetReissuability) return snapshot, nil } func (sg *snapshotGenerator) generateSnapshotForExchangeTx(sellOrder proto.Order, sellFee uint64, buyOrder proto.Order, buyFee uint64, volume uint64, - balanceChanges txDiff) (proto.TransactionSnapshot, error) { + balanceChanges txDiff) (txSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { - return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") + return txSnapshot{}, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } sellOrderID, err := sellOrder.GetID() if err != nil { - return nil, err + return txSnapshot{}, err } sellOrderAtomicSnapshot, err := sg.generateOrderAtomicSnapshot(sellOrderID, volume, sellFee) if err != nil { - return nil, err + return txSnapshot{}, err } buyOrderID, err := buyOrder.GetID() if err != nil { - return nil, err + return txSnapshot{}, err } buyOrderAtomicSnapshot, err := sg.generateOrderAtomicSnapshot(buyOrderID, volume, buyFee) if err != nil { - return nil, err + return txSnapshot{}, err } - snapshot = append(snapshot, sellOrderAtomicSnapshot, buyOrderAtomicSnapshot) + snapshot.regular = append(snapshot.regular, sellOrderAtomicSnapshot, buyOrderAtomicSnapshot) return snapshot, nil } func (sg *snapshotGenerator) generateSnapshotForLeaseTx(lease leasing, leaseID crypto.Digest, - originalTxID crypto.Digest, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + originalTxID crypto.Digest, balanceChanges txDiff) (txSnapshot, error) { var err error snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { - return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") + return txSnapshot{}, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } amount := int64(lease.Amount) leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := sg.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") + return txSnapshot{}, errors.Wrap(err, "failed to generate snapshots for a lease transaction") } - snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) + snapshot.regular = append(snapshot.regular, + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, + ) return snapshot, nil } func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Digest, oldLease leasing, leaseID crypto.Digest, originalTxID crypto.Digest, - cancelHeight uint64, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + cancelHeight uint64, balanceChanges txDiff) (txSnapshot, error) { var err error snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { - return nil, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") + return txSnapshot{}, errors.Wrap(err, "failed to generate a snapshot based on transaction's diffs") } negativeAmount := -int64(oldLease.Amount) leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, err := sg.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") + return txSnapshot{}, errors.Wrap(err, "failed to generate snapshots for a lease transaction") } leaseStatusSnapshot.Status = proto.LeaseStateStatus{ Value: proto.LeaseCanceled, @@ -233,63 +237,63 @@ func (sg *snapshotGenerator) generateSnapshotForLeaseCancelTx(txID *crypto.Diges CancelTransactionID: txID, } - snapshot = append(snapshot, leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot) + snapshot.regular = append(snapshot.regular, + leaseStatusSnapshot, senderLeaseBalanceSnapshot, recipientLeaseBalanceSnapshot, + ) return snapshot, nil } func (sg *snapshotGenerator) generateSnapshotForCreateAliasTx(senderAddress proto.WavesAddress, alias proto.Alias, - balanceChanges txDiff) (proto.TransactionSnapshot, error) { + balanceChanges txDiff) (txSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { - return nil, err + return txSnapshot{}, err } aliasSnapshot := &proto.AliasSnapshot{ Address: senderAddress, Alias: alias, } - snapshot = append(snapshot, aliasSnapshot) + snapshot.regular = append(snapshot.regular, aliasSnapshot) return snapshot, nil } -func (sg *snapshotGenerator) generateSnapshotForMassTransferTx( - balanceChanges txDiff, -) (proto.TransactionSnapshot, error) { +func (sg *snapshotGenerator) generateSnapshotForMassTransferTx(balanceChanges txDiff) (txSnapshot, error) { return sg.generateBalancesSnapshot(balanceChanges) } func (sg *snapshotGenerator) generateSnapshotForDataTx(senderAddress proto.WavesAddress, entries []proto.DataEntry, - balanceChanges txDiff) (proto.TransactionSnapshot, error) { + balanceChanges txDiff) (txSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { - return nil, err + return txSnapshot{}, err } dataEntriesSnapshot := &proto.DataEntriesSnapshot{ Address: senderAddress, DataEntries: entries, } - snapshot = append(snapshot, dataEntriesSnapshot) + snapshot.regular = append(snapshot.regular, dataEntriesSnapshot) return snapshot, nil } func (sg *snapshotGenerator) generateSnapshotForSponsorshipTx(assetID crypto.Digest, - minAssetFee uint64, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + minAssetFee uint64, balanceChanges txDiff) (txSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { - return nil, err + return txSnapshot{}, err } sponsorshipSnapshot := &proto.SponsorshipSnapshot{ AssetID: assetID, MinSponsoredFee: minAssetFee, } - snapshot = append(snapshot, sponsorshipSnapshot) + snapshot.regular = append(snapshot.regular, sponsorshipSnapshot) return snapshot, nil } func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.PublicKey, script proto.Script, - scriptEstimation scriptEstimation, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + scriptEstimation scriptEstimation, balanceChanges txDiff) (txSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { - return nil, err + return txSnapshot{}, err } // If the script is empty, it will still be stored in the storage. @@ -299,47 +303,47 @@ func (sg *snapshotGenerator) generateSnapshotForSetScriptTx(senderPK crypto.Publ VerifierComplexity: uint64(scriptEstimation.estimation.Verifier), } - snapshot = append(snapshot, accountScriptSnapshot) + snapshot.regular = append(snapshot.regular, accountScriptSnapshot) if sg.IsFullNodeMode { scriptAddr, cnvrtErr := proto.NewAddressFromPublicKey(sg.scheme, senderPK) if cnvrtErr != nil { - return nil, errors.Wrap(cnvrtErr, "failed to get sender for InvokeScriptWithProofs") + return txSnapshot{}, errors.Wrap(cnvrtErr, "failed to get sender for InvokeScriptWithProofs") } internalComplexitySnapshot := InternalDAppComplexitySnapshot{ Estimation: scriptEstimation.estimation, ScriptAddress: scriptAddr, ScriptIsEmpty: scriptEstimation.scriptIsEmpty} - snapshot = append(snapshot, &internalComplexitySnapshot) + snapshot.internal = append(snapshot.internal, &internalComplexitySnapshot) } return snapshot, nil } func (sg *snapshotGenerator) generateSnapshotForSetAssetScriptTx(assetID crypto.Digest, script proto.Script, - balanceChanges txDiff, scriptEstimation scriptEstimation) (proto.TransactionSnapshot, error) { + balanceChanges txDiff, scriptEstimation scriptEstimation) (txSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { - return nil, err + return txSnapshot{}, err } assetScrptSnapshot := &proto.AssetScriptSnapshot{ AssetID: assetID, Script: script, } - snapshot = append(snapshot, assetScrptSnapshot) + snapshot.regular = append(snapshot.regular, assetScrptSnapshot) if sg.IsFullNodeMode { internalComplexitySnapshot := InternalAssetScriptComplexitySnapshot{ Estimation: scriptEstimation.estimation, AssetID: assetID, ScriptIsEmpty: scriptEstimation.scriptIsEmpty} - snapshot = append(snapshot, &internalComplexitySnapshot) + snapshot.internal = append(snapshot.internal, &internalComplexitySnapshot) } return snapshot, nil } func (sg *snapshotGenerator) generateSnapshotForUpdateAssetInfoTx(assetID crypto.Digest, assetName string, - assetDescription string, changeHeight proto.Height, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + assetDescription string, changeHeight proto.Height, balanceChanges txDiff) (txSnapshot, error) { snapshot, err := sg.generateBalancesSnapshot(balanceChanges) if err != nil { - return nil, err + return txSnapshot{}, err } sponsorshipSnapshot := &proto.AssetDescriptionSnapshot{ AssetID: assetID, @@ -347,7 +351,7 @@ func (sg *snapshotGenerator) generateSnapshotForUpdateAssetInfoTx(assetID crypto AssetDescription: assetDescription, ChangeHeight: changeHeight, } - snapshot = append(snapshot, sponsorshipSnapshot) + snapshot.regular = append(snapshot.regular, sponsorshipSnapshot) return snapshot, nil } @@ -410,24 +414,24 @@ func (sg *snapshotGenerator) generateOrderAtomicSnapshot(orderID []byte, return orderSnapshot, nil } -func (sg *snapshotGenerator) generateBalancesSnapshot(balanceChanges txDiff) (proto.TransactionSnapshot, error) { - var transactionSnapshot proto.TransactionSnapshot +func (sg *snapshotGenerator) generateBalancesSnapshot(balanceChanges txDiff) (txSnapshot, error) { + var snapshot txSnapshot addrWavesBalanceDiff, addrAssetBalanceDiff, err := balanceDiffFromTxDiff(balanceChanges, sg.scheme) if err != nil { - return nil, errors.Wrap(err, "failed to create balance diff from tx diff") + return txSnapshot{}, errors.Wrap(err, "failed to create balance diff from tx diff") } wavesBalancesSnapshot, assetBalancesSnapshot, err := sg.generateBalancesAtomicSnapshots(addrWavesBalanceDiff, addrAssetBalanceDiff) if err != nil { - return nil, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") + return txSnapshot{}, errors.Wrap(err, "failed to build a snapshot from a genesis transaction") } for i := range wavesBalancesSnapshot { - transactionSnapshot = append(transactionSnapshot, &wavesBalancesSnapshot[i]) + snapshot.regular = append(snapshot.regular, &wavesBalancesSnapshot[i]) } for i := range assetBalancesSnapshot { - transactionSnapshot = append(transactionSnapshot, &assetBalancesSnapshot[i]) + snapshot.regular = append(snapshot.regular, &assetBalancesSnapshot[i]) } - return transactionSnapshot, nil + return snapshot, nil } func (sg *snapshotGenerator) generateBalancesAtomicSnapshots(addrWavesBalanceDiff addressWavesBalanceDiff, diff --git a/pkg/state/snapshot_generator_internal_test.go b/pkg/state/snapshot_generator_internal_test.go index eb999c8be..dd29b052d 100644 --- a/pkg/state/snapshot_generator_internal_test.go +++ b/pkg/state/snapshot_generator_internal_test.go @@ -2,9 +2,7 @@ package state import ( "encoding/base64" - "encoding/json" "math/big" - "sort" "testing" "github.com/stretchr/testify/assert" @@ -56,6 +54,11 @@ func createCheckerCustomTestObjects(t *testing.T, differ *differTestObjects) *ch return &checkerTestObjects{differ.stor, tc, differ.tp, differ.stateActionsCounter} } +func txSnapshotsEqual(t *testing.T, expected, actual txSnapshot) { + _ = assert.ElementsMatch(t, expected.regular, actual.regular) + _ = assert.ElementsMatch(t, expected.internal, actual.internal) +} + func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { checkerInfo := customCheckerInfo() to := createDifferTestObjects(t, checkerInfo) @@ -79,39 +82,25 @@ func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { transactionSnapshot, err := to.tp.performTransferWithSig(tx, defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform transfer tx") - expectedSnapshot := proto.TransactionSnapshot{ - &proto.WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - }, - &proto.WavesBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - Balance: 299700000, - }, - &proto.WavesBalanceSnapshot{ - Address: testGlobal.recipientInfo.addr, - Balance: 200000, + expectedSnapshot := txSnapshot{ + regular: []proto.AtomicSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + Balance: 299700000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.recipientInfo.addr, + Balance: 200000, + }, }, + internal: nil, } - var snapshotI []byte - var snapshotJ []byte - 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) + txSnapshotsEqual(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) } @@ -139,61 +128,47 @@ func TestDefaultIssueTransactionSnapshot(t *testing.T) { defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform issue tx") - expectedSnapshot := proto.TransactionSnapshot{ - &proto.StaticAssetInfoSnapshot{ - AssetID: *tx.ID, - SourceTransactionID: *tx.ID, - IssuerPublicKey: testGlobal.issuerInfo.pk, - Decimals: defaultDecimals, - IsNFT: false}, - &proto.AssetDescriptionSnapshot{ - AssetID: *tx.ID, - AssetName: "asset0", - AssetDescription: "description", - ChangeHeight: 1, - }, - &proto.AssetVolumeSnapshot{ - AssetID: *tx.ID, - TotalQuantity: *big.NewInt(int64(defaultQuantity)), - IsReissuable: true, - }, - &proto.WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - }, - &proto.WavesBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - Balance: 299900000, - }, - &proto.AssetBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - AssetID: *tx.ID, - Balance: 1000, - }, - &proto.AssetScriptSnapshot{ - AssetID: *tx.ID, - Script: proto.Script{}, + expectedSnapshot := txSnapshot{ + regular: []proto.AtomicSnapshot{ + &proto.StaticAssetInfoSnapshot{ + AssetID: *tx.ID, + SourceTransactionID: *tx.ID, + IssuerPublicKey: testGlobal.issuerInfo.pk, + Decimals: defaultDecimals, + IsNFT: false}, + &proto.AssetDescriptionSnapshot{ + AssetID: *tx.ID, + AssetName: "asset0", + AssetDescription: "description", + ChangeHeight: 1, + }, + &proto.AssetVolumeSnapshot{ + AssetID: *tx.ID, + TotalQuantity: *big.NewInt(int64(defaultQuantity)), + IsReissuable: true, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + Balance: 299900000, + }, + &proto.AssetBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + AssetID: *tx.ID, + Balance: 1000, + }, + &proto.AssetScriptSnapshot{ + AssetID: *tx.ID, + Script: proto.Script{}, + }, }, + internal: nil, } - var snapshotI []byte - var snapshotJ []byte - 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) + txSnapshotsEqual(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) } @@ -227,45 +202,31 @@ func TestDefaultReissueSnapshot(t *testing.T) { defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform reissue tx") - expectedSnapshot := proto.TransactionSnapshot{ - &proto.WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - }, - &proto.WavesBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - Balance: 299900000, - }, - &proto.AssetBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - AssetID: testGlobal.asset0.assetID, - Balance: 1050, - }, - &proto.AssetVolumeSnapshot{ - AssetID: testGlobal.asset0.assetID, - TotalQuantity: *big.NewInt(int64(defaultQuantity + 50)), - IsReissuable: false, + expectedSnapshot := txSnapshot{ + regular: []proto.AtomicSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + Balance: 299900000, + }, + &proto.AssetBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 1050, + }, + &proto.AssetVolumeSnapshot{ + AssetID: testGlobal.asset0.assetID, + TotalQuantity: *big.NewInt(int64(defaultQuantity + 50)), + IsReissuable: false, + }, }, + internal: nil, } - var snapshotI []byte - var snapshotJ []byte - 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) + txSnapshotsEqual(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) } @@ -298,45 +259,31 @@ func TestDefaultBurnSnapshot(t *testing.T) { defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := proto.TransactionSnapshot{ - &proto.WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - }, - &proto.WavesBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - Balance: 299900000, - }, - &proto.AssetBalanceSnapshot{ - Address: testGlobal.issuerInfo.addr, - AssetID: testGlobal.asset0.assetID, - Balance: 950, - }, - &proto.AssetVolumeSnapshot{ - AssetID: testGlobal.asset0.assetID, - TotalQuantity: *big.NewInt(int64(defaultQuantity - 100)), - IsReissuable: false, + expectedSnapshot := txSnapshot{ + regular: []proto.AtomicSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + Balance: 299900000, + }, + &proto.AssetBalanceSnapshot{ + Address: testGlobal.issuerInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 950, + }, + &proto.AssetVolumeSnapshot{ + AssetID: testGlobal.asset0.assetID, + TotalQuantity: *big.NewInt(int64(defaultQuantity - 100)), + IsReissuable: false, + }, }, + internal: nil, } - var snapshotI []byte - var snapshotJ []byte - 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) + txSnapshotsEqual(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) } @@ -398,73 +345,59 @@ func TestDefaultExchangeTransaction(t *testing.T) { nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := proto.TransactionSnapshot{ - &proto.WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299999999, - }, - &proto.WavesBalanceSnapshot{ - Address: testGlobal.recipientInfo.addr, - Balance: 599999998, - }, - &proto.WavesBalanceSnapshot{ - Address: testGlobal.matcherInfo.addr, - Balance: 899900003, - }, - &proto.WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - }, - &proto.AssetBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - AssetID: testGlobal.asset0.assetID, - Balance: 10, - }, - &proto.AssetBalanceSnapshot{ - Address: testGlobal.recipientInfo.addr, - AssetID: testGlobal.asset0.assetID, - Balance: 590, - }, - &proto.AssetBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - AssetID: testGlobal.asset1.assetID, - Balance: 400, - }, - &proto.AssetBalanceSnapshot{ - Address: testGlobal.recipientInfo.addr, - AssetID: testGlobal.asset1.assetID, - Balance: 100, - }, - &proto.FilledVolumeFeeSnapshot{ - OrderID: *bo.ID, - FilledVolume: 10, - FilledFee: 1, - }, - &proto.FilledVolumeFeeSnapshot{ - OrderID: *so.ID, - FilledVolume: 10, - FilledFee: 2, + expectedSnapshot := txSnapshot{ + regular: []proto.AtomicSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299999999, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.recipientInfo.addr, + Balance: 599999998, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.matcherInfo.addr, + Balance: 899900003, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.AssetBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 10, + }, + &proto.AssetBalanceSnapshot{ + Address: testGlobal.recipientInfo.addr, + AssetID: testGlobal.asset0.assetID, + Balance: 590, + }, + &proto.AssetBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + AssetID: testGlobal.asset1.assetID, + Balance: 400, + }, + &proto.AssetBalanceSnapshot{ + Address: testGlobal.recipientInfo.addr, + AssetID: testGlobal.asset1.assetID, + Balance: 100, + }, + &proto.FilledVolumeFeeSnapshot{ + OrderID: *bo.ID, + FilledVolume: 10, + FilledFee: 1, + }, + &proto.FilledVolumeFeeSnapshot{ + OrderID: *so.ID, + FilledVolume: 10, + FilledFee: 2, + }, }, + internal: nil, } - var snapshotI []byte - var snapshotJ []byte - 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) + txSnapshotsEqual(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) } @@ -490,56 +423,42 @@ func TestDefaultLeaseSnapshot(t *testing.T) { nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := proto.TransactionSnapshot{ - &proto.WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - }, - &proto.WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, - }, - &proto.LeaseStateSnapshot{ - LeaseID: *tx.ID, - Status: proto.LeaseStateStatus{ - Value: proto.LeaseActive, + expectedSnapshot := txSnapshot{ + regular: []proto.AtomicSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &proto.LeaseStateSnapshot{ + LeaseID: *tx.ID, + Status: proto.LeaseStateStatus{ + Value: proto.LeaseActive, + }, + Amount: 50, + Sender: testGlobal.senderInfo.addr, + Recipient: testGlobal.recipientInfo.addr, + OriginTransactionID: tx.ID, + Height: 0, + }, + &proto.LeaseBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + LeaseIn: 0, + LeaseOut: 50, + }, + &proto.LeaseBalanceSnapshot{ + Address: testGlobal.recipientInfo.addr, + LeaseIn: 50, + LeaseOut: 0, }, - Amount: 50, - Sender: testGlobal.senderInfo.addr, - Recipient: testGlobal.recipientInfo.addr, - OriginTransactionID: tx.ID, - Height: 0, - }, - &proto.LeaseBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - LeaseIn: 0, - LeaseOut: 50, - }, - &proto.LeaseBalanceSnapshot{ - Address: testGlobal.recipientInfo.addr, - LeaseIn: 50, - LeaseOut: 0, }, + internal: nil, } - var snapshotI []byte - var snapshotJ []byte - 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) + txSnapshotsEqual(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) } @@ -581,57 +500,44 @@ func TestDefaultLeaseCancelSnapshot(t *testing.T) { nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := proto.TransactionSnapshot{ - &proto.WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - }, - &proto.WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, - }, - &proto.LeaseStateSnapshot{ - LeaseID: leaseID, - Status: proto.LeaseStateStatus{ - Value: proto.LeaseCanceled, - CancelHeight: 0, - CancelTransactionID: tx.ID, + expectedSnapshot := txSnapshot{ + regular: []proto.AtomicSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &proto.LeaseStateSnapshot{ + LeaseID: leaseID, + Status: proto.LeaseStateStatus{ + Value: proto.LeaseCanceled, + CancelHeight: 0, + CancelTransactionID: tx.ID, + }, + Amount: 50, + Sender: testGlobal.senderInfo.addr, + Recipient: testGlobal.recipientInfo.addr, + OriginTransactionID: &leaseID, + Height: 1, + }, + &proto.LeaseBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + LeaseIn: 0, + LeaseOut: 0, + }, + &proto.LeaseBalanceSnapshot{ + Address: testGlobal.recipientInfo.addr, + LeaseIn: 0, + LeaseOut: 0, }, - Amount: 50, - Sender: testGlobal.senderInfo.addr, - Recipient: testGlobal.recipientInfo.addr, - OriginTransactionID: &leaseID, - Height: 1, - }, - &proto.LeaseBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - LeaseIn: 0, - LeaseOut: 0, - }, - &proto.LeaseBalanceSnapshot{ - Address: testGlobal.recipientInfo.addr, - LeaseIn: 0, - LeaseOut: 0, }, + internal: nil, } - var snapshotI []byte - var snapshotJ []byte - 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) + + txSnapshotsEqual(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) } @@ -656,39 +562,25 @@ func TestDefaultCreateAliasSnapshot(t *testing.T) { nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := proto.TransactionSnapshot{ - &proto.WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - }, - &proto.WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, - }, - &proto.AliasSnapshot{ - Address: testGlobal.senderInfo.addr, - Alias: *proto.NewAlias(proto.TestNetScheme, "aliasForSender"), + expectedSnapshot := txSnapshot{ + regular: []proto.AtomicSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &proto.AliasSnapshot{ + Address: testGlobal.senderInfo.addr, + Alias: *proto.NewAlias(proto.TestNetScheme, "aliasForSender"), + }, }, + internal: nil, } - var snapshotI []byte - var snapshotJ []byte - 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) + txSnapshotsEqual(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) } @@ -721,40 +613,26 @@ func TestDefaultDataSnapshot(t *testing.T) { nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := proto.TransactionSnapshot{ - &proto.WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - }, - &proto.WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, - }, - &proto.DataEntriesSnapshot{ - Address: testGlobal.senderInfo.addr, - DataEntries: []proto.DataEntry{&proto.StringDataEntry{Key: "key_str", Value: "value_str"}, - &proto.IntegerDataEntry{Key: "key_int", Value: 2}}, + expectedSnapshot := txSnapshot{ + regular: []proto.AtomicSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &proto.DataEntriesSnapshot{ + Address: testGlobal.senderInfo.addr, + DataEntries: []proto.DataEntry{&proto.StringDataEntry{Key: "key_str", Value: "value_str"}, + &proto.IntegerDataEntry{Key: "key_int", Value: 2}}, + }, }, + internal: nil, } - var snapshotI []byte - var snapshotJ []byte - 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) + txSnapshotsEqual(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) } @@ -780,40 +658,25 @@ func TestDefaultSponsorshipSnapshot(t *testing.T) { defaultPerformerInfo(to.stateActionsCounter), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := proto.TransactionSnapshot{ - &proto.WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - }, - &proto.WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, - }, - &proto.SponsorshipSnapshot{ - AssetID: testGlobal.asset0.assetID, - MinSponsoredFee: 500000, + expectedSnapshot := txSnapshot{ + regular: []proto.AtomicSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &proto.SponsorshipSnapshot{ + AssetID: testGlobal.asset0.assetID, + MinSponsoredFee: 500000, + }, }, + internal: nil, } - var snapshotI []byte - var snapshotJ []byte - 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) + txSnapshotsEqual(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) } @@ -874,45 +737,32 @@ func TestDefaultSetDappScriptSnapshot(t *testing.T) { defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := proto.TransactionSnapshot{ - &proto.WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - }, - &proto.WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, - }, - &proto.AccountScriptSnapshot{ - SenderPublicKey: testGlobal.senderInfo.pk, - Script: scriptsBytes, - VerifierComplexity: 0, + expectedSnapshot := txSnapshot{ + regular: []proto.AtomicSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &proto.AccountScriptSnapshot{ + SenderPublicKey: testGlobal.senderInfo.pk, + Script: scriptsBytes, + VerifierComplexity: 0, + }, }, - &InternalDAppComplexitySnapshot{ - ScriptAddress: testGlobal.senderInfo.addr, - Estimation: ride.TreeEstimation{Estimation: 36, Verifier: 0, Functions: map[string]int{"call": 36}}, - ScriptIsEmpty: false, + internal: []internalSnapshot{ + &InternalDAppComplexitySnapshot{ + ScriptAddress: testGlobal.senderInfo.addr, + Estimation: ride.TreeEstimation{Estimation: 36, Verifier: 0, Functions: map[string]int{"call": 36}}, + ScriptIsEmpty: false, + }, }, } - var snapshotI []byte - var snapshotJ []byte - 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) + txSnapshotsEqual(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) } @@ -944,44 +794,31 @@ func TestDefaultSetScriptSnapshot(t *testing.T) { defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := proto.TransactionSnapshot{ - &proto.WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - }, - &proto.WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, - }, - &proto.AccountScriptSnapshot{ - SenderPublicKey: testGlobal.senderInfo.pk, - Script: testGlobal.scriptBytes, - VerifierComplexity: 340, + expectedSnapshot := txSnapshot{ + regular: []proto.AtomicSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &proto.AccountScriptSnapshot{ + SenderPublicKey: testGlobal.senderInfo.pk, + Script: testGlobal.scriptBytes, + VerifierComplexity: 340, + }, }, - &InternalDAppComplexitySnapshot{ - ScriptAddress: testGlobal.senderInfo.addr, - Estimation: ride.TreeEstimation{Estimation: 340, Verifier: 340}, + internal: []internalSnapshot{ + &InternalDAppComplexitySnapshot{ + ScriptAddress: testGlobal.senderInfo.addr, + Estimation: ride.TreeEstimation{Estimation: 340, Verifier: 340}, + }, }, } - var snapshotI []byte - var snapshotJ []byte - 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) + txSnapshotsEqual(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) } @@ -1013,45 +850,32 @@ func TestDefaultSetEmptyScriptSnapshot(t *testing.T) { defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := proto.TransactionSnapshot{ - &proto.WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - }, - &proto.WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, - }, - &proto.AccountScriptSnapshot{ - SenderPublicKey: testGlobal.senderInfo.pk, - Script: nil, - VerifierComplexity: 0, + expectedSnapshot := txSnapshot{ + regular: []proto.AtomicSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &proto.AccountScriptSnapshot{ + SenderPublicKey: testGlobal.senderInfo.pk, + Script: nil, + VerifierComplexity: 0, + }, }, - &InternalDAppComplexitySnapshot{ - ScriptAddress: testGlobal.senderInfo.addr, - Estimation: ride.TreeEstimation{Estimation: 0, Verifier: 0}, - ScriptIsEmpty: true, + internal: []internalSnapshot{ + &InternalDAppComplexitySnapshot{ + ScriptAddress: testGlobal.senderInfo.addr, + Estimation: ride.TreeEstimation{Estimation: 0, Verifier: 0}, + ScriptIsEmpty: true, + }, }, } - var snapshotI []byte - var snapshotJ []byte - 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) + txSnapshotsEqual(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) } @@ -1093,50 +917,35 @@ func TestDefaultSetAssetScriptSnapshot(t *testing.T) { defaultPerformerInfoWithChecker(checkerData), nil, applicationRes.changes.diff) assert.NoError(t, err, "failed to perform burn tx") - expectedSnapshot := proto.TransactionSnapshot{ - &proto.WavesBalanceSnapshot{ - Address: testGlobal.minerInfo.addr, - Balance: 40000, - }, - &proto.WavesBalanceSnapshot{ - Address: testGlobal.senderInfo.addr, - Balance: 299900000, - }, - - &proto.AssetScriptSnapshot{ - AssetID: testGlobal.asset0.assetID, - Script: testGlobal.scriptBytes, + expectedSnapshot := txSnapshot{ + regular: []proto.AtomicSnapshot{ + &proto.WavesBalanceSnapshot{ + Address: testGlobal.minerInfo.addr, + Balance: 40000, + }, + &proto.WavesBalanceSnapshot{ + Address: testGlobal.senderInfo.addr, + Balance: 299900000, + }, + &proto.AssetScriptSnapshot{ + AssetID: testGlobal.asset0.assetID, + Script: testGlobal.scriptBytes, + }, }, - &InternalAssetScriptComplexitySnapshot{ - AssetID: testGlobal.asset0.assetID, - Estimation: ride.TreeEstimation{ - Estimation: 340, - Verifier: 340, - Functions: nil, + internal: []internalSnapshot{ + &InternalAssetScriptComplexitySnapshot{ + AssetID: testGlobal.asset0.assetID, + Estimation: ride.TreeEstimation{ + Estimation: 340, + Verifier: 340, + Functions: nil, + }, + ScriptIsEmpty: false, }, - ScriptIsEmpty: false, }, } - var snapshotI []byte - var snapshotJ []byte - 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) + txSnapshotsEqual(t, expectedSnapshot, transactionSnapshot) to.stor.flush(t) } diff --git a/pkg/state/transaction_handler.go b/pkg/state/transaction_handler.go index 00b840d09..d4e72170a 100644 --- a/pkg/state/transaction_handler.go +++ b/pkg/state/transaction_handler.go @@ -24,7 +24,7 @@ type scriptEstimation struct { func (e *scriptEstimation) isPresent() bool { return e != nil } type txCheckFunc func(proto.Transaction, *checkerInfo) (txCheckerData, error) -type txPerformFunc func(proto.Transaction, *performerInfo, *invocationResult, txDiff) (proto.TransactionSnapshot, error) +type txPerformFunc func(proto.Transaction, *performerInfo, *invocationResult, txDiff) (txSnapshot, error) type txCreateDiffFunc func(proto.Transaction, *differInfo) (txBalanceChanges, error) type txCountFeeFunc func(proto.Transaction, *feeDistribution) error @@ -199,17 +199,16 @@ func (h *transactionHandler) checkTx(tx proto.Transaction, info *checkerInfo) (t } func (h *transactionHandler) performTx(tx proto.Transaction, info *performerInfo, - invocationRes *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + invocationRes *invocationResult, balanceChanges txDiff) (txSnapshot, error) { tv := tx.GetTypeInfo() funcs, ok := h.funcs[tv] if !ok { - return nil, errors.Errorf("no function handler implemented for tx struct type %T", tx) + return txSnapshot{}, errors.Errorf("no function handler implemented for tx struct type %T", tx) } if funcs.perform == nil { - // No perform func for this combination of transaction type and version. - return nil, nil + // performer function must not be nil + return txSnapshot{}, errors.Errorf("performer function handler is nil for tx struct type %T", tx) } - return funcs.perform(tx, info, invocationRes, balanceChanges) } diff --git a/pkg/state/transaction_performer.go b/pkg/state/transaction_performer.go index 09d14c593..acc81cefd 100644 --- a/pkg/state/transaction_performer.go +++ b/pkg/state/transaction_performer.go @@ -28,8 +28,8 @@ func newPerformerInfo(height proto.Height, type transactionPerformer struct { stor *blockchainEntitiesStorage settings *settings.BlockchainSettings - snapshotGenerator *snapshotGenerator // initialized in appendTx - snapshotApplier proto.SnapshotApplier // initialized in appendTx + snapshotGenerator *snapshotGenerator // initialized in appendTx + snapshotApplier extendedSnapshotApplier // initialized in appendTx } func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings.BlockchainSettings) (*transactionPerformer, error) { @@ -39,60 +39,60 @@ func newTransactionPerformer(stor *blockchainEntitiesStorage, settings *settings func (tp *transactionPerformer) performGenesis( transaction proto.Transaction, _ *performerInfo, _ *invocationResult, - balanceChanges txDiff) (proto.TransactionSnapshot, error) { + balanceChanges txDiff) (txSnapshot, error) { _, ok := transaction.(*proto.Genesis) if !ok { - return nil, errors.New("failed to convert interface to genesis transaction") + return txSnapshot{}, errors.New("failed to convert interface to genesis transaction") } snapshot, err := tp.snapshotGenerator.generateSnapshotForGenesisTx(balanceChanges) if err != nil { - return nil, err + return txSnapshot{}, err } return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performPayment(transaction proto.Transaction, _ *performerInfo, - _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { _, ok := transaction.(*proto.Payment) if !ok { - return nil, errors.New("failed to convert interface to payment transaction") + return txSnapshot{}, errors.New("failed to convert interface to payment transaction") } snapshot, err := tp.snapshotGenerator.generateSnapshotForPaymentTx(balanceChanges) if err != nil { - return nil, err + return txSnapshot{}, err } return snapshot, snapshot.Apply(tp.snapshotApplier) } -func (tp *transactionPerformer) performTransfer(balanceChanges txDiff) (proto.TransactionSnapshot, error) { +func (tp *transactionPerformer) performTransfer(balanceChanges txDiff) (txSnapshot, error) { snapshot, err := tp.snapshotGenerator.generateSnapshotForTransferTx(balanceChanges) if err != nil { - return nil, err + return txSnapshot{}, err } return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performTransferWithSig(transaction proto.Transaction, _ *performerInfo, - _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { _, ok := transaction.(*proto.TransferWithSig) if !ok { - return nil, errors.New("failed to convert interface to transfer with sig transaction") + return txSnapshot{}, errors.New("failed to convert interface to transfer with sig transaction") } return tp.performTransfer(balanceChanges) } func (tp *transactionPerformer) performTransferWithProofs(transaction proto.Transaction, _ *performerInfo, - _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { _, ok := transaction.(*proto.TransferWithProofs) if !ok { - return nil, errors.New("failed to convert interface to transfer with proofs transaction") + return txSnapshot{}, errors.New("failed to convert interface to transfer with proofs transaction") } return tp.performTransfer(balanceChanges) } func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest, assetID crypto.Digest, info *performerInfo, - balanceChanges txDiff, scriptEstimation *scriptEstimation, script *proto.Script) (proto.TransactionSnapshot, error) { + balanceChanges txDiff, scriptEstimation *scriptEstimation, script *proto.Script) (txSnapshot, error) { blockHeight := info.height + 1 // Create new asset. assetInfo := &assetInfo{ @@ -113,48 +113,48 @@ func (tp *transactionPerformer) performIssue(tx *proto.Issue, txID crypto.Digest snapshot, err := tp.snapshotGenerator.generateSnapshotForIssueTx(assetID, txID, tx.SenderPK, *assetInfo, balanceChanges, scriptEstimation, script) if err != nil { - return nil, err + return txSnapshot{}, err } return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performIssueWithSig(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { tx, ok := transaction.(*proto.IssueWithSig) if !ok { - return nil, errors.New("failed to convert interface to IssueWithSig transaction") + return txSnapshot{}, errors.New("failed to convert interface to IssueWithSig transaction") } txID, err := tx.GetID(tp.settings.AddressSchemeCharacter) if err != nil { - return nil, errors.Errorf("failed to get transaction ID: %v", err) + return txSnapshot{}, errors.Errorf("failed to get transaction ID: %v", err) } assetID, err := crypto.NewDigestFromBytes(txID) if err != nil { - return nil, err + return txSnapshot{}, err } return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges, nil, nil) } func (tp *transactionPerformer) performIssueWithProofs(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { tx, ok := transaction.(*proto.IssueWithProofs) if !ok { - return nil, errors.New("failed to convert interface to IssueWithProofs transaction") + return txSnapshot{}, errors.New("failed to convert interface to IssueWithProofs transaction") } txID, err := tx.GetID(tp.settings.AddressSchemeCharacter) if err != nil { - return nil, errors.Errorf("failed to get transaction ID: %v", err) + return txSnapshot{}, errors.Errorf("failed to get transaction ID: %v", err) } assetID, err := crypto.NewDigestFromBytes(txID) if err != nil { - return nil, err + return txSnapshot{}, err } return tp.performIssue(&tx.Issue, assetID, assetID, info, balanceChanges, info.checkerData.scriptEstimation, &tx.Script) } func (tp *transactionPerformer) performReissue(tx *proto.Reissue, _ *performerInfo, - balanceChanges txDiff) (proto.TransactionSnapshot, error) { + balanceChanges txDiff) (txSnapshot, error) { // Modify asset. change := &assetReissueChange{ reissuable: tx.Reissuable, @@ -163,31 +163,31 @@ func (tp *transactionPerformer) performReissue(tx *proto.Reissue, _ *performerIn snapshot, err := tp.snapshotGenerator.generateSnapshotForReissueTx(tx.AssetID, *change, balanceChanges) if err != nil { - return nil, err + return txSnapshot{}, err } return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performReissueWithSig(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { tx, ok := transaction.(*proto.ReissueWithSig) if !ok { - return nil, errors.New("failed to convert interface to ReissueWithSig transaction") + return txSnapshot{}, errors.New("failed to convert interface to ReissueWithSig transaction") } return tp.performReissue(&tx.Reissue, info, balanceChanges) } func (tp *transactionPerformer) performReissueWithProofs(transaction proto.Transaction, - info *performerInfo, _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + info *performerInfo, _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { tx, ok := transaction.(*proto.ReissueWithProofs) if !ok { - return nil, errors.New("failed to convert interface to ReissueWithProofs transaction") + return txSnapshot{}, errors.New("failed to convert interface to ReissueWithProofs transaction") } return tp.performReissue(&tx.Reissue, info, balanceChanges) } func (tp *transactionPerformer) performBurn(tx *proto.Burn, _ *performerInfo, - balanceChanges txDiff) (proto.TransactionSnapshot, error) { + balanceChanges txDiff) (txSnapshot, error) { // Modify asset. change := &assetBurnChange{ diff: int64(tx.Amount), @@ -195,42 +195,42 @@ func (tp *transactionPerformer) performBurn(tx *proto.Burn, _ *performerInfo, snapshot, err := tp.snapshotGenerator.generateSnapshotForBurnTx(tx.AssetID, *change, balanceChanges) if err != nil { - return nil, err + return txSnapshot{}, err } return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performBurnWithSig(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { tx, ok := transaction.(*proto.BurnWithSig) if !ok { - return nil, errors.New("failed to convert interface to BurnWithSig transaction") + return txSnapshot{}, errors.New("failed to convert interface to BurnWithSig transaction") } return tp.performBurn(&tx.Burn, info, balanceChanges) } func (tp *transactionPerformer) performBurnWithProofs(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { tx, ok := transaction.(*proto.BurnWithProofs) if !ok { - return nil, errors.New("failed to convert interface to BurnWithProofs transaction") + return txSnapshot{}, errors.New("failed to convert interface to BurnWithProofs transaction") } return tp.performBurn(&tx.Burn, info, balanceChanges) } func (tp *transactionPerformer) performExchange(transaction proto.Transaction, _ *performerInfo, - _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { tx, ok := transaction.(proto.Exchange) if !ok { - return nil, errors.New("failed to convert interface to Exchange transaction") + return txSnapshot{}, errors.New("failed to convert interface to Exchange transaction") } sellOrder, err := tx.GetSellOrder() if err != nil { - return nil, errors.Wrap(err, "no sell order") + return txSnapshot{}, errors.Wrap(err, "no sell order") } buyOrder, err := tx.GetBuyOrder() if err != nil { - return nil, errors.Wrap(err, "no buy order") + return txSnapshot{}, errors.Wrap(err, "no buy order") } volume := tx.GetAmount() sellFee := tx.GetSellMatcherFee() @@ -240,22 +240,22 @@ func (tp *transactionPerformer) performExchange(transaction proto.Transaction, _ snapshot, err := tp.snapshotGenerator.generateSnapshotForExchangeTx(sellOrder, sellFee, buyOrder, buyFee, volume, balanceChanges) if err != nil { - return nil, err + return txSnapshot{}, err } return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest, info *performerInfo, - balanceChanges txDiff) (proto.TransactionSnapshot, error) { + balanceChanges txDiff) (txSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { - return nil, err + return txSnapshot{}, 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 nil, errors.Errorf("invalid alias: %v", err) + return txSnapshot{}, errors.Errorf("invalid alias: %v", err) } } else { recipientAddr = *addr @@ -270,176 +270,176 @@ func (tp *transactionPerformer) performLease(tx *proto.Lease, txID crypto.Digest } snapshot, err := tp.snapshotGenerator.generateSnapshotForLeaseTx(*l, txID, txID, balanceChanges) if err != nil { - return nil, err + return txSnapshot{}, err } return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performLeaseWithSig(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { tx, ok := transaction.(*proto.LeaseWithSig) if !ok { - return nil, errors.New("failed to convert interface to LeaseWithSig transaction") + return txSnapshot{}, errors.New("failed to convert interface to LeaseWithSig transaction") } return tp.performLease(&tx.Lease, *tx.ID, info, balanceChanges) } func (tp *transactionPerformer) performLeaseWithProofs(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { tx, ok := transaction.(*proto.LeaseWithProofs) if !ok { - return nil, errors.New("failed to convert interface to LeaseWithProofs transaction") + return txSnapshot{}, errors.New("failed to convert interface to LeaseWithProofs transaction") } return tp.performLease(&tx.Lease, *tx.ID, info, balanceChanges) } func (tp *transactionPerformer) performLeaseCancel(tx *proto.LeaseCancel, txID *crypto.Digest, info *performerInfo, - balanceChanges txDiff) (proto.TransactionSnapshot, error) { + balanceChanges txDiff) (txSnapshot, error) { oldLease, err := tp.stor.leases.newestLeasingInfo(tx.LeaseID) if err != nil { - return nil, errors.Wrap(err, "failed to receiver leasing info") + return txSnapshot{}, errors.Wrap(err, "failed to receiver leasing info") } snapshot, err := tp.snapshotGenerator.generateSnapshotForLeaseCancelTx(txID, *oldLease, tx.LeaseID, *oldLease.OriginTransactionID, info.height, balanceChanges) if err != nil { - return nil, err + return txSnapshot{}, err } return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performLeaseCancelWithSig(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { tx, ok := transaction.(*proto.LeaseCancelWithSig) if !ok { - return nil, errors.New("failed to convert interface to LeaseCancelWithSig transaction") + return txSnapshot{}, errors.New("failed to convert interface to LeaseCancelWithSig transaction") } return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info, balanceChanges) } func (tp *transactionPerformer) performLeaseCancelWithProofs(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { tx, ok := transaction.(*proto.LeaseCancelWithProofs) if !ok { - return nil, errors.New("failed to convert interface to LeaseCancelWithProofs transaction") + return txSnapshot{}, errors.New("failed to convert interface to LeaseCancelWithProofs transaction") } return tp.performLeaseCancel(&tx.LeaseCancel, tx.ID, info, balanceChanges) } func (tp *transactionPerformer) performCreateAlias(tx *proto.CreateAlias, - _ *performerInfo, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *performerInfo, balanceChanges txDiff) (txSnapshot, error) { senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { - return nil, err + return txSnapshot{}, err } snapshot, err := tp.snapshotGenerator.generateSnapshotForCreateAliasTx(senderAddr, tx.Alias, balanceChanges) if err != nil { - return nil, err + return txSnapshot{}, err } return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performCreateAliasWithSig(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { tx, ok := transaction.(*proto.CreateAliasWithSig) if !ok { - return nil, errors.New("failed to convert interface to CreateAliasWithSig transaction") + return txSnapshot{}, errors.New("failed to convert interface to CreateAliasWithSig transaction") } return tp.performCreateAlias(&tx.CreateAlias, info, balanceChanges) } func (tp *transactionPerformer) performCreateAliasWithProofs(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { tx, ok := transaction.(*proto.CreateAliasWithProofs) if !ok { - return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") + return txSnapshot{}, errors.New("failed to convert interface to CreateAliasWithProofs transaction") } return tp.performCreateAlias(&tx.CreateAlias, info, balanceChanges) } func (tp *transactionPerformer) performMassTransferWithProofs(transaction proto.Transaction, _ *performerInfo, - _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { _, ok := transaction.(*proto.MassTransferWithProofs) if !ok { - return nil, errors.New("failed to convert interface to CreateAliasWithProofs transaction") + return txSnapshot{}, errors.New("failed to convert interface to CreateAliasWithProofs transaction") } snapshot, err := tp.snapshotGenerator.generateSnapshotForMassTransferTx(balanceChanges) if err != nil { - return nil, err + return txSnapshot{}, err } return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performDataWithProofs(transaction proto.Transaction, - _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *performerInfo, _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { tx, ok := transaction.(*proto.DataWithProofs) if !ok { - return nil, errors.New("failed to convert interface to DataWithProofs transaction") + return txSnapshot{}, errors.New("failed to convert interface to DataWithProofs transaction") } senderAddr, err := proto.NewAddressFromPublicKey(tp.settings.AddressSchemeCharacter, tx.SenderPK) if err != nil { - return nil, err + return txSnapshot{}, err } snapshot, err := tp.snapshotGenerator.generateSnapshotForDataTx(senderAddr, tx.Entries, balanceChanges) if err != nil { - return nil, err + return txSnapshot{}, err } return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performSponsorshipWithProofs(transaction proto.Transaction, _ *performerInfo, - _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { tx, ok := transaction.(*proto.SponsorshipWithProofs) if !ok { - return nil, errors.New("failed to convert interface to SponsorshipWithProofs transaction") + return txSnapshot{}, errors.New("failed to convert interface to SponsorshipWithProofs transaction") } snapshot, err := tp.snapshotGenerator.generateSnapshotForSponsorshipTx(tx.AssetID, tx.MinAssetFee, balanceChanges) if err != nil { - return nil, err + return txSnapshot{}, err } return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performSetScriptWithProofs(transaction proto.Transaction, info *performerInfo, - _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { tx, ok := transaction.(*proto.SetScriptWithProofs) if !ok { - return nil, errors.New("failed to convert interface to SetScriptWithProofs transaction") + return txSnapshot{}, errors.New("failed to convert interface to SetScriptWithProofs transaction") } se := info.checkerData.scriptEstimation if !se.isPresent() { - return nil, errors.New("script estimations must be set for SetScriptWithProofs tx") + return txSnapshot{}, errors.New("script estimations must be set for SetScriptWithProofs tx") } snapshot, err := tp.snapshotGenerator.generateSnapshotForSetScriptTx(tx.SenderPK, tx.Script, *se, balanceChanges) if err != nil { - return nil, errors.Wrap(err, "failed to generate snapshot for set script tx") + return txSnapshot{}, errors.Wrap(err, "failed to generate snapshot for set script tx") } return snapshot, snapshot.Apply(tp.snapshotApplier) } func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction proto.Transaction, - info *performerInfo, _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + info *performerInfo, _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { tx, ok := transaction.(*proto.SetAssetScriptWithProofs) if !ok { - return nil, errors.New("failed to convert interface to SetAssetScriptWithProofs transaction") + return txSnapshot{}, errors.New("failed to convert interface to SetAssetScriptWithProofs transaction") } se := info.checkerData.scriptEstimation if !se.isPresent() { - return nil, errors.New("script estimations must be set for SetAssetScriptWithProofs tx") + return txSnapshot{}, errors.New("script estimations must be set for SetAssetScriptWithProofs tx") } snapshot, err := tp.snapshotGenerator.generateSnapshotForSetAssetScriptTx(tx.AssetID, tx.Script, balanceChanges, *se) if err != nil { - return nil, err + return txSnapshot{}, err } return snapshot, snapshot.Apply(tp.snapshotApplier) } @@ -447,18 +447,18 @@ func (tp *transactionPerformer) performSetAssetScriptWithProofs(transaction prot func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, - balanceChanges txDiff) (proto.TransactionSnapshot, error) { + balanceChanges txDiff) (txSnapshot, error) { tx, ok := transaction.(*proto.InvokeScriptWithProofs) if !ok { - return nil, errors.New("failed to convert interface to InvokeScriptWithProofs transaction") + return txSnapshot{}, errors.New("failed to convert interface to InvokeScriptWithProofs transaction") } if err := tp.stor.commitUncertain(info.blockID); err != nil { - return nil, errors.Wrapf(err, "failed to commit invoke changes for tx %q", tx.ID.String()) + return txSnapshot{}, errors.Wrapf(err, "failed to commit invoke changes for tx %q", tx.ID.String()) } se := info.checkerData.scriptEstimation if !se.isPresent() { // nothing to do, no estimation to save - return nil, nil + return txSnapshot{}, nil } // script estimation is present an not nil @@ -467,63 +467,66 @@ func (tp *transactionPerformer) performInvokeScriptWithProofs(transaction proto. // this is the place where we have to store new estimation scriptAddr, err := recipientToAddress(tx.ScriptRecipient, tp.stor.aliases) if err != nil { - return nil, errors.Wrap(err, "failed to get sender for InvokeScriptWithProofs") + return txSnapshot{}, errors.Wrap(err, "failed to get sender for InvokeScriptWithProofs") } // update callable and summary complexity, verifier complexity remains the same if scErr := tp.stor.scriptsComplexity.updateCallableComplexitiesForAddr(scriptAddr, *se, info.blockID); scErr != nil { - return nil, errors.Wrapf(scErr, "failed to save complexity for addr %q in tx %q", + return txSnapshot{}, errors.Wrapf(scErr, "failed to save complexity for addr %q in tx %q", scriptAddr.String(), tx.ID.String(), ) } + // TODO: ignored _ = invocationRes _ = balanceChanges - return nil, nil + return txSnapshot{}, nil } func (tp *transactionPerformer) performInvokeExpressionWithProofs(transaction proto.Transaction, info *performerInfo, invocationRes *invocationResult, - balanceChanges txDiff) (proto.TransactionSnapshot, error) { + balanceChanges txDiff) (txSnapshot, error) { if _, ok := transaction.(*proto.InvokeExpressionTransactionWithProofs); !ok { - return nil, errors.New("failed to convert interface to InvokeExpressionWithProofs transaction") + return txSnapshot{}, errors.New("failed to convert interface to InvokeExpressionWithProofs transaction") } if err := tp.stor.commitUncertain(info.blockID); err != nil { - return nil, errors.Wrap(err, "failed to commit invoke changes") + return txSnapshot{}, errors.Wrap(err, "failed to commit invoke changes") } + // TODO: ignored _ = invocationRes _ = balanceChanges - return nil, nil + return txSnapshot{}, nil } func (tp *transactionPerformer) performEthereumTransactionWithProofs(transaction proto.Transaction, info *performerInfo, - invocationRes *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + invocationRes *invocationResult, balanceChanges txDiff) (txSnapshot, error) { ethTx, ok := transaction.(*proto.EthereumTransaction) if !ok { - return nil, errors.New("failed to convert interface to EthereumTransaction transaction") + return txSnapshot{}, 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 nil, errors.Wrap(err, "failed to commit invoke changes") + return txSnapshot{}, errors.Wrap(err, "failed to commit invoke changes") } } + // TODO: ignored _ = invocationRes _ = balanceChanges // nothing to do for proto.EthereumTransferWavesTxKind and proto.EthereumTransferAssetsErc20TxKind - return nil, nil + return txSnapshot{}, nil } func (tp *transactionPerformer) performUpdateAssetInfoWithProofs(transaction proto.Transaction, - info *performerInfo, _ *invocationResult, balanceChanges txDiff) (proto.TransactionSnapshot, error) { + info *performerInfo, _ *invocationResult, balanceChanges txDiff) (txSnapshot, error) { tx, ok := transaction.(*proto.UpdateAssetInfoWithProofs) if !ok { - return nil, errors.New("failed to convert interface to UpdateAssetInfoWithProofs transaction") + return txSnapshot{}, errors.New("failed to convert interface to UpdateAssetInfoWithProofs transaction") } blockHeight := info.height + 1 snapshot, err := tp.snapshotGenerator.generateSnapshotForUpdateAssetInfoTx(tx.AssetID, tx.Name, tx.Description, blockHeight, balanceChanges) if err != nil { - return nil, err + return txSnapshot{}, err } return snapshot, snapshot.Apply(tp.snapshotApplier) } diff --git a/pkg/state/tx_snapshot.go b/pkg/state/tx_snapshot.go new file mode 100644 index 000000000..c32f5866c --- /dev/null +++ b/pkg/state/tx_snapshot.go @@ -0,0 +1,38 @@ +package state + +import ( + "github.com/pkg/errors" + + "github.com/wavesplatform/gowaves/pkg/proto" +) + +type extendedSnapshotApplier interface { + proto.SnapshotApplier + internalSnapshotApplier +} + +type txSnapshot struct { + regular []proto.AtomicSnapshot + internal []internalSnapshot +} + +func (ts txSnapshot) Apply(a extendedSnapshotApplier) error { + // internal snapshots must be applied at the end + for _, rs := range ts.regular { + if !rs.IsGeneratedByTxDiff() { + err := rs.Apply(a) + if err != nil { + return errors.Wrap(err, "failed to apply regular transaction snapshot") + } + } + } + for _, is := range ts.internal { + if !is.IsGeneratedByTxDiff() { + err := is.ApplyInternal(a) + if err != nil { + return errors.Wrap(err, "failed to apply internal transaction snapshot") + } + } + } + return nil +} From 73d6e88c1f930eaaafcda0e58479f7087077340f Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Mon, 30 Oct 2023 20:41:59 +0300 Subject: [PATCH 086/139] Reduced 'internalSnapshot' interface, removed unnecessary code. --- pkg/proto/snapshot_types.go | 64 --------------------------- pkg/state/internal_snapshots_types.go | 43 ------------------ pkg/state/snapshot_applier.go | 13 ------ pkg/state/tx_snapshot.go | 8 ++-- 4 files changed, 3 insertions(+), 125 deletions(-) diff --git a/pkg/proto/snapshot_types.go b/pkg/proto/snapshot_types.go index 35a264cc9..bbd1a1acb 100644 --- a/pkg/proto/snapshot_types.go +++ b/pkg/proto/snapshot_types.go @@ -11,7 +11,6 @@ type AtomicSnapshot interface { /* is temporarily used to mark snapshots generated by tx diff that shouldn't be applied, because balances diffs are applied later in the block. */ IsGeneratedByTxDiff() bool - IsInternal() bool } type WavesBalanceSnapshot struct { @@ -31,20 +30,12 @@ type AssetBalanceSnapshot struct { Balance uint64 } -func (s WavesBalanceSnapshot) IsInternal() bool { - return false -} - func (s AssetBalanceSnapshot) IsGeneratedByTxDiff() bool { return true } func (s AssetBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetBalance(s) } -func (s AssetBalanceSnapshot) IsInternal() bool { - return false -} - type DataEntriesSnapshot struct { // AccountData in pb Address WavesAddress DataEntries []DataEntry @@ -56,10 +47,6 @@ func (s DataEntriesSnapshot) IsGeneratedByTxDiff() bool { func (s DataEntriesSnapshot) Apply(a SnapshotApplier) error { return a.ApplyDataEntries(s) } -func (s DataEntriesSnapshot) IsInternal() bool { - return false -} - type AccountScriptSnapshot struct { SenderPublicKey crypto.PublicKey Script Script @@ -72,10 +59,6 @@ func (s AccountScriptSnapshot) IsGeneratedByTxDiff() bool { func (s AccountScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAccountScript(s) } -func (s AccountScriptSnapshot) IsInternal() bool { - return false -} - type AssetScriptSnapshot struct { AssetID crypto.Digest Script Script @@ -87,10 +70,6 @@ func (s AssetScriptSnapshot) IsGeneratedByTxDiff() bool { func (s AssetScriptSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetScript(s) } -func (s AssetScriptSnapshot) IsInternal() bool { - return false -} - type LeaseBalanceSnapshot struct { Address WavesAddress LeaseIn uint64 @@ -103,10 +82,6 @@ func (s LeaseBalanceSnapshot) IsGeneratedByTxDiff() bool { func (s LeaseBalanceSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseBalance(s) } -func (s LeaseBalanceSnapshot) IsInternal() bool { - return false -} - type LeaseStateStatus struct { Value LeaseStatus // can be only LeaseActive or LeaseCanceled CancelHeight Height @@ -129,10 +104,6 @@ func (s LeaseStateSnapshot) IsGeneratedByTxDiff() bool { func (s LeaseStateSnapshot) Apply(a SnapshotApplier) error { return a.ApplyLeaseState(s) } -func (s LeaseStateSnapshot) IsInternal() bool { - return false -} - type SponsorshipSnapshot struct { AssetID crypto.Digest MinSponsoredFee uint64 @@ -144,10 +115,6 @@ func (s SponsorshipSnapshot) IsGeneratedByTxDiff() bool { func (s SponsorshipSnapshot) Apply(a SnapshotApplier) error { return a.ApplySponsorship(s) } -func (s SponsorshipSnapshot) IsInternal() bool { - return false -} - type AliasSnapshot struct { Address WavesAddress Alias Alias @@ -159,10 +126,6 @@ func (s AliasSnapshot) IsGeneratedByTxDiff() bool { func (s AliasSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAlias(s) } -func (s AliasSnapshot) IsInternal() bool { - return false -} - // FilledVolumeFeeSnapshot Filled Volume and Fee. type FilledVolumeFeeSnapshot struct { // OrderFill OrderID crypto.Digest @@ -176,10 +139,6 @@ func (s FilledVolumeFeeSnapshot) IsGeneratedByTxDiff() bool { func (s FilledVolumeFeeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyFilledVolumeAndFee(s) } -func (s FilledVolumeFeeSnapshot) IsInternal() bool { - return false -} - type StaticAssetInfoSnapshot struct { AssetID crypto.Digest SourceTransactionID crypto.Digest @@ -194,10 +153,6 @@ func (s StaticAssetInfoSnapshot) IsGeneratedByTxDiff() bool { func (s StaticAssetInfoSnapshot) Apply(a SnapshotApplier) error { return a.ApplyStaticAssetInfo(s) } -func (s StaticAssetInfoSnapshot) IsInternal() bool { - return false -} - type AssetVolumeSnapshot struct { // AssetVolume in pb AssetID crypto.Digest TotalQuantity big.Int // volume in protobuf @@ -210,10 +165,6 @@ func (s AssetVolumeSnapshot) IsGeneratedByTxDiff() bool { func (s AssetVolumeSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetVolume(s) } -func (s AssetVolumeSnapshot) IsInternal() bool { - return false -} - type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb AssetID crypto.Digest AssetName string @@ -227,10 +178,6 @@ func (s AssetDescriptionSnapshot) IsGeneratedByTxDiff() bool { func (s AssetDescriptionSnapshot) Apply(a SnapshotApplier) error { return a.ApplyAssetDescription(s) } -func (s AssetDescriptionSnapshot) IsInternal() bool { - return false -} - type TransactionStatusSnapshot struct { TransactionID crypto.Digest Status TransactionStatus @@ -244,14 +191,6 @@ func (s TransactionStatusSnapshot) IsGeneratedByTxDiff() bool { return false } -func (s TransactionStatusSnapshot) IsInternal() bool { - return false -} - -type InternalSnapshot interface { - InternalSnapshotMarker() -} - type SnapshotApplier interface { ApplyWavesBalance(snapshot WavesBalanceSnapshot) error ApplyLeaseBalance(snapshot LeaseBalanceSnapshot) error @@ -267,7 +206,4 @@ type SnapshotApplier interface { ApplyDataEntries(snapshot DataEntriesSnapshot) error ApplyLeaseState(snapshot LeaseStateSnapshot) error ApplyTransactionsStatus(snapshot TransactionStatusSnapshot) error - - /* Internal snapshots. Applied only in the full node mode */ - ApplyInternalSnapshot(internalSnapshot InternalSnapshot) error } diff --git a/pkg/state/internal_snapshots_types.go b/pkg/state/internal_snapshots_types.go index 6652537ec..ae523b055 100644 --- a/pkg/state/internal_snapshots_types.go +++ b/pkg/state/internal_snapshots_types.go @@ -7,7 +7,6 @@ import ( ) type internalSnapshot interface { - IsGeneratedByTxDiff() bool ApplyInternal(internalSnapshotApplier) error } @@ -27,68 +26,26 @@ type InternalDAppComplexitySnapshot struct { ScriptIsEmpty bool } -func (s InternalDAppComplexitySnapshot) IsGeneratedByTxDiff() bool { - return false -} - -func (s InternalDAppComplexitySnapshot) Apply(a proto.SnapshotApplier) error { - return a.ApplyInternalSnapshot(&s) -} - func (s InternalDAppComplexitySnapshot) ApplyInternal(a internalSnapshotApplier) error { return a.ApplyDAppComplexity(s) } -func (s InternalDAppComplexitySnapshot) IsInternal() bool { - return true -} - -func (s *InternalDAppComplexitySnapshot) InternalSnapshotMarker() {} - type InternalDAppUpdateComplexitySnapshot struct { ScriptAddress proto.WavesAddress Estimation ride.TreeEstimation ScriptIsEmpty bool } -func (s InternalDAppUpdateComplexitySnapshot) IsGeneratedByTxDiff() bool { - return false -} - -func (s InternalDAppUpdateComplexitySnapshot) Apply(a proto.SnapshotApplier) error { - return a.ApplyInternalSnapshot(&s) -} - func (s InternalDAppUpdateComplexitySnapshot) ApplyInternal(a internalSnapshotApplier) error { return a.ApplyDAppUpdateComplexity(s) } -func (s InternalDAppUpdateComplexitySnapshot) IsInternal() bool { - return true -} - -func (s *InternalDAppUpdateComplexitySnapshot) InternalSnapshotMarker() {} - type InternalAssetScriptComplexitySnapshot struct { AssetID crypto.Digest Estimation ride.TreeEstimation ScriptIsEmpty bool } -func (s InternalAssetScriptComplexitySnapshot) IsGeneratedByTxDiff() bool { - return false -} - -func (s InternalAssetScriptComplexitySnapshot) Apply(a proto.SnapshotApplier) error { - return a.ApplyInternalSnapshot(&s) -} - func (s InternalAssetScriptComplexitySnapshot) ApplyInternal(a internalSnapshotApplier) error { return a.ApplyAssetScriptComplexity(s) } - -func (s InternalAssetScriptComplexitySnapshot) IsInternal() bool { - return true -} - -func (s *InternalAssetScriptComplexitySnapshot) InternalSnapshotMarker() {} diff --git a/pkg/state/snapshot_applier.go b/pkg/state/snapshot_applier.go index c3bac09ce..dc24512b4 100644 --- a/pkg/state/snapshot_applier.go +++ b/pkg/state/snapshot_applier.go @@ -238,19 +238,6 @@ func (a *blockSnapshotsApplier) ApplyTransactionsStatus(_ proto.TransactionStatu return nil // no-op } -func (a *blockSnapshotsApplier) ApplyInternalSnapshot(internalSnapshot proto.InternalSnapshot) error { - switch snapshot := internalSnapshot.(type) { - case *InternalDAppComplexitySnapshot: - return a.ApplyDAppComplexity(*snapshot) - case *InternalDAppUpdateComplexitySnapshot: - return a.ApplyDAppUpdateComplexity(*snapshot) - case *InternalAssetScriptComplexitySnapshot: - return a.ApplyAssetScriptComplexity(*snapshot) - default: - return errors.Errorf("failed to apply internal snapshot, unknown type (%T)", snapshot) - } -} - func (a *blockSnapshotsApplier) ApplyDAppComplexity(snapshot InternalDAppComplexitySnapshot) error { scriptEstimation := scriptEstimation{currentEstimatorVersion: a.info.EstimatorVersion(), scriptIsEmpty: snapshot.ScriptIsEmpty, estimation: snapshot.Estimation} diff --git a/pkg/state/tx_snapshot.go b/pkg/state/tx_snapshot.go index c32f5866c..8949d7f6c 100644 --- a/pkg/state/tx_snapshot.go +++ b/pkg/state/tx_snapshot.go @@ -27,11 +27,9 @@ func (ts txSnapshot) Apply(a extendedSnapshotApplier) error { } } for _, is := range ts.internal { - if !is.IsGeneratedByTxDiff() { - err := is.ApplyInternal(a) - if err != nil { - return errors.Wrap(err, "failed to apply internal transaction snapshot") - } + err := is.ApplyInternal(a) + if err != nil { + return errors.Wrap(err, "failed to apply internal transaction snapshot") } } return nil From f5916f0f3ac0b0061c733cc9d4d197495b6befdd Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Thu, 23 Nov 2023 12:09:58 +0300 Subject: [PATCH 087/139] add new add block with snapshot --- pkg/grpc/generated/waves/amount.pb.go | 2 +- pkg/grpc/generated/waves/amount_vtproto.pb.go | 2 +- pkg/grpc/generated/waves/block.pb.go | 2 +- pkg/grpc/generated/waves/block_vtproto.pb.go | 2 +- pkg/grpc/generated/waves/events/events.pb.go | 2 +- .../events/grpc/blockchain_updates.pb.go | 2 +- .../events/grpc/blockchain_updates_grpc.pb.go | 2 +- .../waves/invoke_script_result.pb.go | 2 +- .../waves/invoke_script_result_vtproto.pb.go | 2 +- .../waves/node/grpc/accounts_api.pb.go | 236 +++++++---- .../waves/node/grpc/accounts_api_grpc.pb.go | 12 +- .../waves/node/grpc/assets_api.pb.go | 2 +- .../waves/node/grpc/assets_api_grpc.pb.go | 2 +- .../waves/node/grpc/blockchain_api.pb.go | 2 +- .../waves/node/grpc/blockchain_api_grpc.pb.go | 2 +- .../waves/node/grpc/blocks_api.pb.go | 2 +- .../waves/node/grpc/blocks_api_grpc.pb.go | 2 +- .../waves/node/grpc/transactions_api.pb.go | 2 +- .../node/grpc/transactions_api_grpc.pb.go | 2 +- pkg/grpc/generated/waves/order.pb.go | 2 +- pkg/grpc/generated/waves/order_vtproto.pb.go | 2 +- pkg/grpc/generated/waves/recipient.pb.go | 2 +- .../generated/waves/recipient_vtproto.pb.go | 2 +- pkg/grpc/generated/waves/reward_share.pb.go | 2 +- .../waves/reward_share_vtproto.pb.go | 2 +- pkg/grpc/generated/waves/state_snapshot.pb.go | 243 +++++++++++ .../waves/state_snapshot_vtproto.pb.go | 401 ++++++++++++++++++ pkg/grpc/generated/waves/transaction.pb.go | 2 +- .../waves/transaction_state_snapshot.pb.go | 12 +- .../transaction_state_snapshot_vtproto.pb.go | 2 +- .../generated/waves/transaction_vtproto.pb.go | 2 +- pkg/grpc/protobuf-schemas | 2 +- pkg/node/actions_by_type.go | 18 +- pkg/node/fsm/fsm.go | 6 + pkg/node/fsm/ng_state.go | 19 +- pkg/node/fsm/wait_snapshot_state.go | 5 +- pkg/proto/block_snapshot.go | 55 +++ pkg/proto/proto.go | 61 ++- pkg/proto/protobuf_converters.go | 129 ++++++ pkg/proto/snapshot_types.go | 261 +++++++++++- pkg/ride/meta/generated/dapp_meta.pb.go | 2 +- pkg/state/appender.go | 91 ++++ pkg/state/state.go | 187 ++++++++ 43 files changed, 1651 insertions(+), 141 deletions(-) create mode 100644 pkg/grpc/generated/waves/state_snapshot.pb.go create mode 100644 pkg/grpc/generated/waves/state_snapshot_vtproto.pb.go create mode 100644 pkg/proto/block_snapshot.go diff --git a/pkg/grpc/generated/waves/amount.pb.go b/pkg/grpc/generated/waves/amount.pb.go index a80c73614..c4510bc6a 100644 --- a/pkg/grpc/generated/waves/amount.pb.go +++ b/pkg/grpc/generated/waves/amount.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v4.24.3 +// protoc v4.24.4 // source: waves/amount.proto package waves diff --git a/pkg/grpc/generated/waves/amount_vtproto.pb.go b/pkg/grpc/generated/waves/amount_vtproto.pb.go index 4ea244d90..5e24e53ea 100644 --- a/pkg/grpc/generated/waves/amount_vtproto.pb.go +++ b/pkg/grpc/generated/waves/amount_vtproto.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-vtproto. DO NOT EDIT. -// protoc-gen-go-vtproto version: v0.4.0 +// protoc-gen-go-vtproto version: v0.5.0 // source: waves/amount.proto package waves diff --git a/pkg/grpc/generated/waves/block.pb.go b/pkg/grpc/generated/waves/block.pb.go index 0249aa7e7..b2f711bde 100644 --- a/pkg/grpc/generated/waves/block.pb.go +++ b/pkg/grpc/generated/waves/block.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v4.24.3 +// protoc v4.24.4 // source: waves/block.proto package waves diff --git a/pkg/grpc/generated/waves/block_vtproto.pb.go b/pkg/grpc/generated/waves/block_vtproto.pb.go index 2849a6751..62702b70c 100644 --- a/pkg/grpc/generated/waves/block_vtproto.pb.go +++ b/pkg/grpc/generated/waves/block_vtproto.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-vtproto. DO NOT EDIT. -// protoc-gen-go-vtproto version: v0.4.0 +// protoc-gen-go-vtproto version: v0.5.0 // source: waves/block.proto package waves diff --git a/pkg/grpc/generated/waves/events/events.pb.go b/pkg/grpc/generated/waves/events/events.pb.go index 357a95314..f5256faea 100644 --- a/pkg/grpc/generated/waves/events/events.pb.go +++ b/pkg/grpc/generated/waves/events/events.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v4.24.3 +// protoc v4.24.4 // source: waves/events/events.proto package events diff --git a/pkg/grpc/generated/waves/events/grpc/blockchain_updates.pb.go b/pkg/grpc/generated/waves/events/grpc/blockchain_updates.pb.go index 459f8a61f..3e1151aed 100644 --- a/pkg/grpc/generated/waves/events/grpc/blockchain_updates.pb.go +++ b/pkg/grpc/generated/waves/events/grpc/blockchain_updates.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v4.24.3 +// protoc v4.24.4 // source: waves/events/grpc/blockchain_updates.proto package grpc diff --git a/pkg/grpc/generated/waves/events/grpc/blockchain_updates_grpc.pb.go b/pkg/grpc/generated/waves/events/grpc/blockchain_updates_grpc.pb.go index 2e7157def..230e81139 100644 --- a/pkg/grpc/generated/waves/events/grpc/blockchain_updates_grpc.pb.go +++ b/pkg/grpc/generated/waves/events/grpc/blockchain_updates_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v4.24.3 +// - protoc v4.24.4 // source: waves/events/grpc/blockchain_updates.proto package grpc diff --git a/pkg/grpc/generated/waves/invoke_script_result.pb.go b/pkg/grpc/generated/waves/invoke_script_result.pb.go index 34c927c4b..5472a3fa3 100644 --- a/pkg/grpc/generated/waves/invoke_script_result.pb.go +++ b/pkg/grpc/generated/waves/invoke_script_result.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v4.24.3 +// protoc v4.24.4 // source: waves/invoke_script_result.proto package waves diff --git a/pkg/grpc/generated/waves/invoke_script_result_vtproto.pb.go b/pkg/grpc/generated/waves/invoke_script_result_vtproto.pb.go index 17e1401c4..bfce98306 100644 --- a/pkg/grpc/generated/waves/invoke_script_result_vtproto.pb.go +++ b/pkg/grpc/generated/waves/invoke_script_result_vtproto.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-vtproto. DO NOT EDIT. -// protoc-gen-go-vtproto version: v0.4.0 +// protoc-gen-go-vtproto version: v0.5.0 // source: waves/invoke_script_result.proto package waves diff --git a/pkg/grpc/generated/waves/node/grpc/accounts_api.pb.go b/pkg/grpc/generated/waves/node/grpc/accounts_api.pb.go index 36d4b7186..1d1265020 100644 --- a/pkg/grpc/generated/waves/node/grpc/accounts_api.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/accounts_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v4.24.3 +// protoc v4.24.4 // source: waves/node/grpc/accounts_api.proto package grpc @@ -378,6 +378,77 @@ func (x *ScriptData) GetComplexity() int64 { return 0 } +type ScriptResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ScriptBytes []byte `protobuf:"bytes,1,opt,name=script_bytes,json=scriptBytes,proto3" json:"script_bytes,omitempty"` + ScriptText string `protobuf:"bytes,2,opt,name=script_text,json=scriptText,proto3" json:"script_text,omitempty"` + Complexity int64 `protobuf:"varint,3,opt,name=complexity,proto3" json:"complexity,omitempty"` + PublicKey []byte `protobuf:"bytes,4,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` +} + +func (x *ScriptResponse) Reset() { + *x = ScriptResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_node_grpc_accounts_api_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ScriptResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ScriptResponse) ProtoMessage() {} + +func (x *ScriptResponse) ProtoReflect() protoreflect.Message { + mi := &file_waves_node_grpc_accounts_api_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ScriptResponse.ProtoReflect.Descriptor instead. +func (*ScriptResponse) Descriptor() ([]byte, []int) { + return file_waves_node_grpc_accounts_api_proto_rawDescGZIP(), []int{6} +} + +func (x *ScriptResponse) GetScriptBytes() []byte { + if x != nil { + return x.ScriptBytes + } + return nil +} + +func (x *ScriptResponse) GetScriptText() string { + if x != nil { + return x.ScriptText + } + return "" +} + +func (x *ScriptResponse) GetComplexity() int64 { + if x != nil { + return x.Complexity + } + return 0 +} + +func (x *ScriptResponse) GetPublicKey() []byte { + if x != nil { + return x.PublicKey + } + return nil +} + type LeaseResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -394,7 +465,7 @@ type LeaseResponse struct { func (x *LeaseResponse) Reset() { *x = LeaseResponse{} if protoimpl.UnsafeEnabled { - mi := &file_waves_node_grpc_accounts_api_proto_msgTypes[6] + mi := &file_waves_node_grpc_accounts_api_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -407,7 +478,7 @@ func (x *LeaseResponse) String() string { func (*LeaseResponse) ProtoMessage() {} func (x *LeaseResponse) ProtoReflect() protoreflect.Message { - mi := &file_waves_node_grpc_accounts_api_proto_msgTypes[6] + mi := &file_waves_node_grpc_accounts_api_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -420,7 +491,7 @@ func (x *LeaseResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use LeaseResponse.ProtoReflect.Descriptor instead. func (*LeaseResponse) Descriptor() ([]byte, []int) { - return file_waves_node_grpc_accounts_api_proto_rawDescGZIP(), []int{6} + return file_waves_node_grpc_accounts_api_proto_rawDescGZIP(), []int{7} } func (x *LeaseResponse) GetLeaseId() []byte { @@ -481,7 +552,7 @@ type BalanceResponse_WavesBalances struct { func (x *BalanceResponse_WavesBalances) Reset() { *x = BalanceResponse_WavesBalances{} if protoimpl.UnsafeEnabled { - mi := &file_waves_node_grpc_accounts_api_proto_msgTypes[7] + mi := &file_waves_node_grpc_accounts_api_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -494,7 +565,7 @@ func (x *BalanceResponse_WavesBalances) String() string { func (*BalanceResponse_WavesBalances) ProtoMessage() {} func (x *BalanceResponse_WavesBalances) ProtoReflect() protoreflect.Message { - mi := &file_waves_node_grpc_accounts_api_proto_msgTypes[7] + mi := &file_waves_node_grpc_accounts_api_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -610,54 +681,64 @@ var file_waves_node_grpc_accounts_api_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x54, 0x65, 0x78, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x74, 0x79, - 0x22, 0xd3, 0x01, 0x0a, 0x0d, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x13, - 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x13, 0x6f, 0x72, 0x69, 0x67, 0x69, - 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x16, - 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, - 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, - 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x77, 0x61, 0x76, 0x65, - 0x73, 0x2e, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x09, 0x72, 0x65, 0x63, - 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16, - 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, - 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x32, 0xa4, 0x03, 0x0a, 0x0b, 0x41, 0x63, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x73, 0x41, 0x70, 0x69, 0x12, 0x53, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, - 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x49, 0x0a, 0x09, 0x47, - 0x65, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1f, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x77, 0x61, 0x76, 0x65, - 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x54, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, - 0x69, 0x76, 0x65, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x77, 0x61, 0x76, 0x65, - 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x63, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x77, 0x61, 0x76, - 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x65, 0x61, - 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x54, 0x0a, 0x0e, - 0x47, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1c, + 0x22, 0x93, 0x01, 0x0a, 0x0e, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x62, 0x79, + 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x5f, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x54, 0x65, 0x78, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x6c, + 0x65, 0x78, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x6f, 0x6d, + 0x70, 0x6c, 0x65, 0x78, 0x69, 0x74, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0xd3, 0x01, 0x0a, 0x0d, 0x4c, 0x65, 0x61, 0x73, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x65, 0x61, 0x73, + 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6c, 0x65, 0x61, 0x73, 0x65, + 0x49, 0x64, 0x12, 0x30, 0x0a, 0x13, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x13, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x09, + 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, + 0x74, 0x52, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, + 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x32, 0xa8, 0x03, 0x0a, + 0x0b, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x41, 0x70, 0x69, 0x12, 0x53, 0x0a, 0x0b, + 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x77, 0x61, + 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, + 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, + 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, + 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, + 0x01, 0x12, 0x4d, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1f, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, - 0x2e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x77, - 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x44, - 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x30, 0x01, 0x12, 0x49, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x41, 0x6c, 0x69, - 0x61, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x1a, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x73, 0x0a, - 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, - 0x72, 0x6d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5a, 0x43, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, - 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, - 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, - 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x67, 0x72, 0x70, 0x63, - 0xaa, 0x02, 0x0f, 0x57, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x47, 0x72, - 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1f, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x54, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4c, 0x65, 0x61, + 0x73, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, 0x65, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, 0x6f, 0x64, + 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x54, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x44, 0x61, 0x74, + 0x61, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x6e, + 0x6f, 0x64, 0x65, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x49, 0x0a, 0x0c, + 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1c, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x79, 0x74, + 0x65, 0x73, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x73, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x77, + 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, + 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, + 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x67, 0x72, 0x70, 0x63, 0xaa, 0x02, 0x0f, 0x57, 0x61, 0x76, + 0x65, 0x73, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x47, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -672,7 +753,7 @@ func file_waves_node_grpc_accounts_api_proto_rawDescGZIP() []byte { return file_waves_node_grpc_accounts_api_proto_rawDescData } -var file_waves_node_grpc_accounts_api_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_waves_node_grpc_accounts_api_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_waves_node_grpc_accounts_api_proto_goTypes = []interface{}{ (*AccountRequest)(nil), // 0: waves.node.grpc.AccountRequest (*DataRequest)(nil), // 1: waves.node.grpc.DataRequest @@ -680,29 +761,30 @@ var file_waves_node_grpc_accounts_api_proto_goTypes = []interface{}{ (*BalanceResponse)(nil), // 3: waves.node.grpc.BalanceResponse (*DataEntryResponse)(nil), // 4: waves.node.grpc.DataEntryResponse (*ScriptData)(nil), // 5: waves.node.grpc.ScriptData - (*LeaseResponse)(nil), // 6: waves.node.grpc.LeaseResponse - (*BalanceResponse_WavesBalances)(nil), // 7: waves.node.grpc.BalanceResponse.WavesBalances - (*waves.Amount)(nil), // 8: waves.Amount - (*waves.DataTransactionData_DataEntry)(nil), // 9: waves.DataTransactionData.DataEntry - (*waves.Recipient)(nil), // 10: waves.Recipient - (*wrapperspb.StringValue)(nil), // 11: google.protobuf.StringValue - (*wrapperspb.BytesValue)(nil), // 12: google.protobuf.BytesValue + (*ScriptResponse)(nil), // 6: waves.node.grpc.ScriptResponse + (*LeaseResponse)(nil), // 7: waves.node.grpc.LeaseResponse + (*BalanceResponse_WavesBalances)(nil), // 8: waves.node.grpc.BalanceResponse.WavesBalances + (*waves.Amount)(nil), // 9: waves.Amount + (*waves.DataTransactionData_DataEntry)(nil), // 10: waves.DataTransactionData.DataEntry + (*waves.Recipient)(nil), // 11: waves.Recipient + (*wrapperspb.StringValue)(nil), // 12: google.protobuf.StringValue + (*wrapperspb.BytesValue)(nil), // 13: google.protobuf.BytesValue } var file_waves_node_grpc_accounts_api_proto_depIdxs = []int32{ - 7, // 0: waves.node.grpc.BalanceResponse.waves:type_name -> waves.node.grpc.BalanceResponse.WavesBalances - 8, // 1: waves.node.grpc.BalanceResponse.asset:type_name -> waves.Amount - 9, // 2: waves.node.grpc.DataEntryResponse.entry:type_name -> waves.DataTransactionData.DataEntry - 10, // 3: waves.node.grpc.LeaseResponse.recipient:type_name -> waves.Recipient + 8, // 0: waves.node.grpc.BalanceResponse.waves:type_name -> waves.node.grpc.BalanceResponse.WavesBalances + 9, // 1: waves.node.grpc.BalanceResponse.asset:type_name -> waves.Amount + 10, // 2: waves.node.grpc.DataEntryResponse.entry:type_name -> waves.DataTransactionData.DataEntry + 11, // 3: waves.node.grpc.LeaseResponse.recipient:type_name -> waves.Recipient 2, // 4: waves.node.grpc.AccountsApi.GetBalances:input_type -> waves.node.grpc.BalancesRequest 0, // 5: waves.node.grpc.AccountsApi.GetScript:input_type -> waves.node.grpc.AccountRequest 0, // 6: waves.node.grpc.AccountsApi.GetActiveLeases:input_type -> waves.node.grpc.AccountRequest 1, // 7: waves.node.grpc.AccountsApi.GetDataEntries:input_type -> waves.node.grpc.DataRequest - 11, // 8: waves.node.grpc.AccountsApi.ResolveAlias:input_type -> google.protobuf.StringValue + 12, // 8: waves.node.grpc.AccountsApi.ResolveAlias:input_type -> google.protobuf.StringValue 3, // 9: waves.node.grpc.AccountsApi.GetBalances:output_type -> waves.node.grpc.BalanceResponse - 5, // 10: waves.node.grpc.AccountsApi.GetScript:output_type -> waves.node.grpc.ScriptData - 6, // 11: waves.node.grpc.AccountsApi.GetActiveLeases:output_type -> waves.node.grpc.LeaseResponse + 6, // 10: waves.node.grpc.AccountsApi.GetScript:output_type -> waves.node.grpc.ScriptResponse + 7, // 11: waves.node.grpc.AccountsApi.GetActiveLeases:output_type -> waves.node.grpc.LeaseResponse 4, // 12: waves.node.grpc.AccountsApi.GetDataEntries:output_type -> waves.node.grpc.DataEntryResponse - 12, // 13: waves.node.grpc.AccountsApi.ResolveAlias:output_type -> google.protobuf.BytesValue + 13, // 13: waves.node.grpc.AccountsApi.ResolveAlias:output_type -> google.protobuf.BytesValue 9, // [9:14] is the sub-list for method output_type 4, // [4:9] is the sub-list for method input_type 4, // [4:4] is the sub-list for extension type_name @@ -789,7 +871,7 @@ func file_waves_node_grpc_accounts_api_proto_init() { } } file_waves_node_grpc_accounts_api_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LeaseResponse); i { + switch v := v.(*ScriptResponse); i { case 0: return &v.state case 1: @@ -801,6 +883,18 @@ func file_waves_node_grpc_accounts_api_proto_init() { } } file_waves_node_grpc_accounts_api_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LeaseResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_node_grpc_accounts_api_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BalanceResponse_WavesBalances); i { case 0: return &v.state @@ -823,7 +917,7 @@ func file_waves_node_grpc_accounts_api_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_waves_node_grpc_accounts_api_proto_rawDesc, NumEnums: 0, - NumMessages: 8, + NumMessages: 9, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/grpc/generated/waves/node/grpc/accounts_api_grpc.pb.go b/pkg/grpc/generated/waves/node/grpc/accounts_api_grpc.pb.go index 6e5040aac..56b0a82a0 100644 --- a/pkg/grpc/generated/waves/node/grpc/accounts_api_grpc.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/accounts_api_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v4.24.3 +// - protoc v4.24.4 // source: waves/node/grpc/accounts_api.proto package grpc @@ -24,7 +24,7 @@ const _ = grpc.SupportPackageIsVersion7 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type AccountsApiClient interface { GetBalances(ctx context.Context, in *BalancesRequest, opts ...grpc.CallOption) (AccountsApi_GetBalancesClient, error) - GetScript(ctx context.Context, in *AccountRequest, opts ...grpc.CallOption) (*ScriptData, error) + GetScript(ctx context.Context, in *AccountRequest, opts ...grpc.CallOption) (*ScriptResponse, error) GetActiveLeases(ctx context.Context, in *AccountRequest, opts ...grpc.CallOption) (AccountsApi_GetActiveLeasesClient, error) GetDataEntries(ctx context.Context, in *DataRequest, opts ...grpc.CallOption) (AccountsApi_GetDataEntriesClient, error) ResolveAlias(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (*wrapperspb.BytesValue, error) @@ -70,8 +70,8 @@ func (x *accountsApiGetBalancesClient) Recv() (*BalanceResponse, error) { return m, nil } -func (c *accountsApiClient) GetScript(ctx context.Context, in *AccountRequest, opts ...grpc.CallOption) (*ScriptData, error) { - out := new(ScriptData) +func (c *accountsApiClient) GetScript(ctx context.Context, in *AccountRequest, opts ...grpc.CallOption) (*ScriptResponse, error) { + out := new(ScriptResponse) err := c.cc.Invoke(ctx, "/waves.node.grpc.AccountsApi/GetScript", in, out, opts...) if err != nil { return nil, err @@ -157,7 +157,7 @@ func (c *accountsApiClient) ResolveAlias(ctx context.Context, in *wrapperspb.Str // for forward compatibility type AccountsApiServer interface { GetBalances(*BalancesRequest, AccountsApi_GetBalancesServer) error - GetScript(context.Context, *AccountRequest) (*ScriptData, error) + GetScript(context.Context, *AccountRequest) (*ScriptResponse, error) GetActiveLeases(*AccountRequest, AccountsApi_GetActiveLeasesServer) error GetDataEntries(*DataRequest, AccountsApi_GetDataEntriesServer) error ResolveAlias(context.Context, *wrapperspb.StringValue) (*wrapperspb.BytesValue, error) @@ -170,7 +170,7 @@ type UnimplementedAccountsApiServer struct { func (UnimplementedAccountsApiServer) GetBalances(*BalancesRequest, AccountsApi_GetBalancesServer) error { return status.Errorf(codes.Unimplemented, "method GetBalances not implemented") } -func (UnimplementedAccountsApiServer) GetScript(context.Context, *AccountRequest) (*ScriptData, error) { +func (UnimplementedAccountsApiServer) GetScript(context.Context, *AccountRequest) (*ScriptResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetScript not implemented") } func (UnimplementedAccountsApiServer) GetActiveLeases(*AccountRequest, AccountsApi_GetActiveLeasesServer) error { diff --git a/pkg/grpc/generated/waves/node/grpc/assets_api.pb.go b/pkg/grpc/generated/waves/node/grpc/assets_api.pb.go index f7d9eb0dc..8bb683fcc 100644 --- a/pkg/grpc/generated/waves/node/grpc/assets_api.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/assets_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v4.24.3 +// protoc v4.24.4 // source: waves/node/grpc/assets_api.proto package grpc diff --git a/pkg/grpc/generated/waves/node/grpc/assets_api_grpc.pb.go b/pkg/grpc/generated/waves/node/grpc/assets_api_grpc.pb.go index e73291aba..c652b8f55 100644 --- a/pkg/grpc/generated/waves/node/grpc/assets_api_grpc.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/assets_api_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v4.24.3 +// - protoc v4.24.4 // source: waves/node/grpc/assets_api.proto package grpc diff --git a/pkg/grpc/generated/waves/node/grpc/blockchain_api.pb.go b/pkg/grpc/generated/waves/node/grpc/blockchain_api.pb.go index 237e76244..473066706 100644 --- a/pkg/grpc/generated/waves/node/grpc/blockchain_api.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/blockchain_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v4.24.3 +// protoc v4.24.4 // source: waves/node/grpc/blockchain_api.proto package grpc diff --git a/pkg/grpc/generated/waves/node/grpc/blockchain_api_grpc.pb.go b/pkg/grpc/generated/waves/node/grpc/blockchain_api_grpc.pb.go index 30c29a5a3..27c2cad16 100644 --- a/pkg/grpc/generated/waves/node/grpc/blockchain_api_grpc.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/blockchain_api_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v4.24.3 +// - protoc v4.24.4 // source: waves/node/grpc/blockchain_api.proto package grpc diff --git a/pkg/grpc/generated/waves/node/grpc/blocks_api.pb.go b/pkg/grpc/generated/waves/node/grpc/blocks_api.pb.go index fdcb63299..e6f60d004 100644 --- a/pkg/grpc/generated/waves/node/grpc/blocks_api.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/blocks_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v4.24.3 +// protoc v4.24.4 // source: waves/node/grpc/blocks_api.proto package grpc diff --git a/pkg/grpc/generated/waves/node/grpc/blocks_api_grpc.pb.go b/pkg/grpc/generated/waves/node/grpc/blocks_api_grpc.pb.go index 4fed31918..edaf27d5f 100644 --- a/pkg/grpc/generated/waves/node/grpc/blocks_api_grpc.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/blocks_api_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v4.24.3 +// - protoc v4.24.4 // source: waves/node/grpc/blocks_api.proto package grpc diff --git a/pkg/grpc/generated/waves/node/grpc/transactions_api.pb.go b/pkg/grpc/generated/waves/node/grpc/transactions_api.pb.go index 25541e078..86e9c476a 100644 --- a/pkg/grpc/generated/waves/node/grpc/transactions_api.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/transactions_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v4.24.3 +// protoc v4.24.4 // source: waves/node/grpc/transactions_api.proto package grpc diff --git a/pkg/grpc/generated/waves/node/grpc/transactions_api_grpc.pb.go b/pkg/grpc/generated/waves/node/grpc/transactions_api_grpc.pb.go index d545421d1..5a95b60b4 100644 --- a/pkg/grpc/generated/waves/node/grpc/transactions_api_grpc.pb.go +++ b/pkg/grpc/generated/waves/node/grpc/transactions_api_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v4.24.3 +// - protoc v4.24.4 // source: waves/node/grpc/transactions_api.proto package grpc diff --git a/pkg/grpc/generated/waves/order.pb.go b/pkg/grpc/generated/waves/order.pb.go index cde88dab8..83fa8cf5c 100644 --- a/pkg/grpc/generated/waves/order.pb.go +++ b/pkg/grpc/generated/waves/order.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v4.24.3 +// protoc v4.24.4 // source: waves/order.proto package waves diff --git a/pkg/grpc/generated/waves/order_vtproto.pb.go b/pkg/grpc/generated/waves/order_vtproto.pb.go index a640e6b4f..b8c88bedc 100644 --- a/pkg/grpc/generated/waves/order_vtproto.pb.go +++ b/pkg/grpc/generated/waves/order_vtproto.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-vtproto. DO NOT EDIT. -// protoc-gen-go-vtproto version: v0.4.0 +// protoc-gen-go-vtproto version: v0.5.0 // source: waves/order.proto package waves diff --git a/pkg/grpc/generated/waves/recipient.pb.go b/pkg/grpc/generated/waves/recipient.pb.go index c019627e1..3018e52ed 100644 --- a/pkg/grpc/generated/waves/recipient.pb.go +++ b/pkg/grpc/generated/waves/recipient.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v4.24.3 +// protoc v4.24.4 // source: waves/recipient.proto package waves diff --git a/pkg/grpc/generated/waves/recipient_vtproto.pb.go b/pkg/grpc/generated/waves/recipient_vtproto.pb.go index c00f07726..c0f33f20d 100644 --- a/pkg/grpc/generated/waves/recipient_vtproto.pb.go +++ b/pkg/grpc/generated/waves/recipient_vtproto.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-vtproto. DO NOT EDIT. -// protoc-gen-go-vtproto version: v0.4.0 +// protoc-gen-go-vtproto version: v0.5.0 // source: waves/recipient.proto package waves diff --git a/pkg/grpc/generated/waves/reward_share.pb.go b/pkg/grpc/generated/waves/reward_share.pb.go index 25a28839c..5297ba721 100644 --- a/pkg/grpc/generated/waves/reward_share.pb.go +++ b/pkg/grpc/generated/waves/reward_share.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v4.24.3 +// protoc v4.24.4 // source: waves/reward_share.proto package waves diff --git a/pkg/grpc/generated/waves/reward_share_vtproto.pb.go b/pkg/grpc/generated/waves/reward_share_vtproto.pb.go index 775c0c887..2af351a0e 100644 --- a/pkg/grpc/generated/waves/reward_share_vtproto.pb.go +++ b/pkg/grpc/generated/waves/reward_share_vtproto.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-vtproto. DO NOT EDIT. -// protoc-gen-go-vtproto version: v0.4.0 +// protoc-gen-go-vtproto version: v0.5.0 // source: waves/reward_share.proto package waves diff --git a/pkg/grpc/generated/waves/state_snapshot.pb.go b/pkg/grpc/generated/waves/state_snapshot.pb.go new file mode 100644 index 000000000..726a882d3 --- /dev/null +++ b/pkg/grpc/generated/waves/state_snapshot.pb.go @@ -0,0 +1,243 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v4.24.4 +// source: waves/state_snapshot.proto + +package waves + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type BlockSnapshot struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + BlockId []byte `protobuf:"bytes,1,opt,name=block_id,json=blockId,proto3" json:"block_id,omitempty"` + Snapshots []*TransactionStateSnapshot `protobuf:"bytes,2,rep,name=snapshots,proto3" json:"snapshots,omitempty"` +} + +func (x *BlockSnapshot) Reset() { + *x = BlockSnapshot{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_state_snapshot_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BlockSnapshot) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BlockSnapshot) ProtoMessage() {} + +func (x *BlockSnapshot) ProtoReflect() protoreflect.Message { + mi := &file_waves_state_snapshot_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BlockSnapshot.ProtoReflect.Descriptor instead. +func (*BlockSnapshot) Descriptor() ([]byte, []int) { + return file_waves_state_snapshot_proto_rawDescGZIP(), []int{0} +} + +func (x *BlockSnapshot) GetBlockId() []byte { + if x != nil { + return x.BlockId + } + return nil +} + +func (x *BlockSnapshot) GetSnapshots() []*TransactionStateSnapshot { + if x != nil { + return x.Snapshots + } + return nil +} + +type MicroBlockSnapshot struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TotalBlockId []byte `protobuf:"bytes,1,opt,name=total_block_id,json=totalBlockId,proto3" json:"total_block_id,omitempty"` + Snapshots []*TransactionStateSnapshot `protobuf:"bytes,2,rep,name=snapshots,proto3" json:"snapshots,omitempty"` +} + +func (x *MicroBlockSnapshot) Reset() { + *x = MicroBlockSnapshot{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_state_snapshot_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MicroBlockSnapshot) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MicroBlockSnapshot) ProtoMessage() {} + +func (x *MicroBlockSnapshot) ProtoReflect() protoreflect.Message { + mi := &file_waves_state_snapshot_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MicroBlockSnapshot.ProtoReflect.Descriptor instead. +func (*MicroBlockSnapshot) Descriptor() ([]byte, []int) { + return file_waves_state_snapshot_proto_rawDescGZIP(), []int{1} +} + +func (x *MicroBlockSnapshot) GetTotalBlockId() []byte { + if x != nil { + return x.TotalBlockId + } + return nil +} + +func (x *MicroBlockSnapshot) GetSnapshots() []*TransactionStateSnapshot { + if x != nil { + return x.Snapshots + } + return nil +} + +var File_waves_state_snapshot_proto protoreflect.FileDescriptor + +var file_waves_state_snapshot_proto_rawDesc = []byte{ + 0x0a, 0x1a, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x77, 0x61, + 0x76, 0x65, 0x73, 0x1a, 0x26, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x69, 0x0a, 0x0d, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x19, 0x0a, 0x08, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x64, 0x12, 0x3d, 0x0a, 0x09, 0x73, 0x6e, 0x61, 0x70, 0x73, + 0x68, 0x6f, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x61, 0x76, + 0x65, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x09, 0x73, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x22, 0x79, 0x0a, 0x12, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x24, 0x0a, 0x0e, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x49, 0x64, 0x12, 0x3d, 0x0a, 0x09, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x09, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, + 0x73, 0x42, 0x68, 0x0a, 0x23, 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, + 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, + 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, + 0x72, 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x77, 0x61, + 0x76, 0x65, 0x73, 0xaa, 0x02, 0x05, 0x57, 0x61, 0x76, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, +} + +var ( + file_waves_state_snapshot_proto_rawDescOnce sync.Once + file_waves_state_snapshot_proto_rawDescData = file_waves_state_snapshot_proto_rawDesc +) + +func file_waves_state_snapshot_proto_rawDescGZIP() []byte { + file_waves_state_snapshot_proto_rawDescOnce.Do(func() { + file_waves_state_snapshot_proto_rawDescData = protoimpl.X.CompressGZIP(file_waves_state_snapshot_proto_rawDescData) + }) + return file_waves_state_snapshot_proto_rawDescData +} + +var file_waves_state_snapshot_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_waves_state_snapshot_proto_goTypes = []interface{}{ + (*BlockSnapshot)(nil), // 0: waves.BlockSnapshot + (*MicroBlockSnapshot)(nil), // 1: waves.MicroBlockSnapshot + (*TransactionStateSnapshot)(nil), // 2: waves.TransactionStateSnapshot +} +var file_waves_state_snapshot_proto_depIdxs = []int32{ + 2, // 0: waves.BlockSnapshot.snapshots:type_name -> waves.TransactionStateSnapshot + 2, // 1: waves.MicroBlockSnapshot.snapshots:type_name -> waves.TransactionStateSnapshot + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_waves_state_snapshot_proto_init() } +func file_waves_state_snapshot_proto_init() { + if File_waves_state_snapshot_proto != nil { + return + } + file_waves_transaction_state_snapshot_proto_init() + if !protoimpl.UnsafeEnabled { + file_waves_state_snapshot_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BlockSnapshot); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_waves_state_snapshot_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MicroBlockSnapshot); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_waves_state_snapshot_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_waves_state_snapshot_proto_goTypes, + DependencyIndexes: file_waves_state_snapshot_proto_depIdxs, + MessageInfos: file_waves_state_snapshot_proto_msgTypes, + }.Build() + File_waves_state_snapshot_proto = out.File + file_waves_state_snapshot_proto_rawDesc = nil + file_waves_state_snapshot_proto_goTypes = nil + file_waves_state_snapshot_proto_depIdxs = nil +} diff --git a/pkg/grpc/generated/waves/state_snapshot_vtproto.pb.go b/pkg/grpc/generated/waves/state_snapshot_vtproto.pb.go new file mode 100644 index 000000000..8dac9c965 --- /dev/null +++ b/pkg/grpc/generated/waves/state_snapshot_vtproto.pb.go @@ -0,0 +1,401 @@ +// Code generated by protoc-gen-go-vtproto. DO NOT EDIT. +// protoc-gen-go-vtproto version: v0.5.0 +// source: waves/state_snapshot.proto + +package waves + +import ( + fmt "fmt" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + io "io" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +func (m *BlockSnapshot) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BlockSnapshot) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *BlockSnapshot) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Snapshots) > 0 { + for iNdEx := len(m.Snapshots) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Snapshots[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + } + } + if len(m.BlockId) > 0 { + i -= len(m.BlockId) + copy(dAtA[i:], m.BlockId) + i = encodeVarint(dAtA, i, uint64(len(m.BlockId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MicroBlockSnapshot) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MicroBlockSnapshot) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *MicroBlockSnapshot) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Snapshots) > 0 { + for iNdEx := len(m.Snapshots) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Snapshots[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + } + } + if len(m.TotalBlockId) > 0 { + i -= len(m.TotalBlockId) + copy(dAtA[i:], m.TotalBlockId) + i = encodeVarint(dAtA, i, uint64(len(m.TotalBlockId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *BlockSnapshot) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.BlockId) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if len(m.Snapshots) > 0 { + for _, e := range m.Snapshots { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + n += len(m.unknownFields) + return n +} + +func (m *MicroBlockSnapshot) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.TotalBlockId) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if len(m.Snapshots) > 0 { + for _, e := range m.Snapshots { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + n += len(m.unknownFields) + return n +} + +func (m *BlockSnapshot) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BlockSnapshot: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BlockSnapshot: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockId", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BlockId = append(m.BlockId[:0], dAtA[iNdEx:postIndex]...) + if m.BlockId == nil { + m.BlockId = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Snapshots", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Snapshots = append(m.Snapshots, &TransactionStateSnapshot{}) + if err := m.Snapshots[len(m.Snapshots)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MicroBlockSnapshot) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MicroBlockSnapshot: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MicroBlockSnapshot: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalBlockId", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TotalBlockId = append(m.TotalBlockId[:0], dAtA[iNdEx:postIndex]...) + if m.TotalBlockId == nil { + m.TotalBlockId = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Snapshots", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Snapshots = append(m.Snapshots, &TransactionStateSnapshot{}) + if err := m.Snapshots[len(m.Snapshots)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} diff --git a/pkg/grpc/generated/waves/transaction.pb.go b/pkg/grpc/generated/waves/transaction.pb.go index 9a06d9268..159f5439b 100644 --- a/pkg/grpc/generated/waves/transaction.pb.go +++ b/pkg/grpc/generated/waves/transaction.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v4.24.3 +// protoc v4.24.4 // source: waves/transaction.proto package waves diff --git a/pkg/grpc/generated/waves/transaction_state_snapshot.pb.go b/pkg/grpc/generated/waves/transaction_state_snapshot.pb.go index 872f23115..fe5e5f8ac 100644 --- a/pkg/grpc/generated/waves/transaction_state_snapshot.pb.go +++ b/pkg/grpc/generated/waves/transaction_state_snapshot.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v4.24.3 +// protoc v4.24.4 // source: waves/transaction_state_snapshot.proto package waves @@ -1025,11 +1025,6 @@ type TransactionStateSnapshot_LeaseState_Active struct { unknownFields protoimpl.UnknownFields } -func (m *TransactionStateSnapshot_LeaseState_Active) isTransactionStateSnapshot_LeaseState_Status() { - //TODO implement me - panic("implement me") -} - func (x *TransactionStateSnapshot_LeaseState_Active) Reset() { *x = TransactionStateSnapshot_LeaseState_Active{} if protoimpl.UnsafeEnabled { @@ -1071,11 +1066,6 @@ type TransactionStateSnapshot_LeaseState_Cancelled struct { TransactionId []byte `protobuf:"bytes,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` } -func (m *TransactionStateSnapshot_LeaseState_Cancelled) isTransactionStateSnapshot_LeaseState_Status() { - //TODO implement me - panic("implement me") -} - func (x *TransactionStateSnapshot_LeaseState_Cancelled) Reset() { *x = TransactionStateSnapshot_LeaseState_Cancelled{} if protoimpl.UnsafeEnabled { diff --git a/pkg/grpc/generated/waves/transaction_state_snapshot_vtproto.pb.go b/pkg/grpc/generated/waves/transaction_state_snapshot_vtproto.pb.go index 553911335..01a44be90 100644 --- a/pkg/grpc/generated/waves/transaction_state_snapshot_vtproto.pb.go +++ b/pkg/grpc/generated/waves/transaction_state_snapshot_vtproto.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-vtproto. DO NOT EDIT. -// protoc-gen-go-vtproto version: v0.4.0 +// protoc-gen-go-vtproto version: v0.5.0 // source: waves/transaction_state_snapshot.proto package waves diff --git a/pkg/grpc/generated/waves/transaction_vtproto.pb.go b/pkg/grpc/generated/waves/transaction_vtproto.pb.go index 0cce8c9ff..85adba128 100644 --- a/pkg/grpc/generated/waves/transaction_vtproto.pb.go +++ b/pkg/grpc/generated/waves/transaction_vtproto.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-vtproto. DO NOT EDIT. -// protoc-gen-go-vtproto version: v0.4.0 +// protoc-gen-go-vtproto version: v0.5.0 // source: waves/transaction.proto package waves diff --git a/pkg/grpc/protobuf-schemas b/pkg/grpc/protobuf-schemas index 111a6641e..64df66a7a 160000 --- a/pkg/grpc/protobuf-schemas +++ b/pkg/grpc/protobuf-schemas @@ -1 +1 @@ -Subproject commit 111a6641e4bf281d36750b7665b01284864d654a +Subproject commit 64df66a7a3f49c033c8c9715adc4bb4e35600484 diff --git a/pkg/node/actions_by_type.go b/pkg/node/actions_by_type.go index f812f4fd2..47502d554 100644 --- a/pkg/node/actions_by_type.go +++ b/pkg/node/actions_by_type.go @@ -1,12 +1,15 @@ package node import ( + g "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" "math/big" "reflect" "github.com/wavesplatform/gowaves/pkg/logging" "github.com/wavesplatform/gowaves/pkg/node/peers/storage" + protobuf "google.golang.org/protobuf/proto" + "go.uber.org/zap" "github.com/wavesplatform/gowaves/pkg/crypto" @@ -273,8 +276,19 @@ func GetSnapshotAction(services services.Services, mess peer.ProtoMessage, fsm * return nil, nil } -func SnapshotAction(_ services.Services, mess peer.ProtoMessage, fsm *fsm.FSM) (fsm.Async, error) { - metricSnapshotMessage.Inc() // TODO(anton): maybe remove some metrics for snapshot +func SnapshotAction(services services.Services, mess peer.ProtoMessage, fsm *fsm.FSM) (fsm.Async, error) { + metricSnapshotMessage.Inc() + m := mess.Message.(*proto.BlockSnapshotMessage) + protoMess := &g.BlockSnapshot{} + if err := protobuf.Unmarshal(m.Bytes, protoMess); err != nil { + return nil, err + } + blockId, err := proto.NewBlockIDFromBytes(protoMess.BlockId) + if err != nil { + return nil, err + } + blockSnapshot, err := proto.BlockSnapshotFromProtobuf(services.Scheme, protoMess.Snapshots) + return fsm.BlockSnapshot(mess.ID, blockId, blockSnapshot) } func createActions() map[reflect.Type]Action { diff --git a/pkg/node/fsm/fsm.go b/pkg/node/fsm/fsm.go index 5ab48f8f3..acb483dcd 100644 --- a/pkg/node/fsm/fsm.go +++ b/pkg/node/fsm/fsm.go @@ -298,3 +298,9 @@ func (f *FSM) ChangeSyncPeer(p peer.Peer) (Async, error) { err := f.fsm.Fire(ChangeSyncPeerEvent, asyncRes, p) return *asyncRes, err } + +func (f *FSM) BlockSnapshot(p peer.Peer, blockID proto.BlockID, snapshots proto.BlockSnapshot) (Async, error) { + asyncRes := &Async{} + err := f.fsm.Fire(BlockSnapshotEvent, asyncRes, p, blockID, snapshots) + return *asyncRes, err +} diff --git a/pkg/node/fsm/ng_state.go b/pkg/node/fsm/ng_state.go index 6feeddded..1a3f32b2e 100644 --- a/pkg/node/fsm/ng_state.go +++ b/pkg/node/fsm/ng_state.go @@ -331,27 +331,36 @@ func (a *NGState) Halt() (State, Async, error) { return newHaltState(a.baseInfo) } +type blockWithSnapshot struct { + Block proto.Block + Snapshot proto.BlockSnapshot +} + type blockStatesCache struct { - blockStates map[proto.BlockID]proto.Block + blockStates map[proto.BlockID]blockWithSnapshot } func (c *blockStatesCache) AddBlockState(block *proto.Block) { - c.blockStates[block.ID] = *block + c.blockStates[block.ID] = blockWithSnapshot{Block: *block} zap.S().Named(logging.FSMNamespace).Debugf("[NG] Block '%s' added to cache, total blocks in cache: %d", block.ID.String(), len(c.blockStates)) } +func (c *blockStatesCache) AddSnapshot(blockID proto.BlockID, snapshot proto.BlockSnapshot) { + c.blockStates[blockID].Snapshot = snapshot +} + func (c *blockStatesCache) Clear() { - c.blockStates = map[proto.BlockID]proto.Block{} + c.blockStates = map[proto.BlockID]blockWithSnapshot{} zap.S().Named(logging.FSMNamespace).Debug("[NG] Block cache is empty") } func (c *blockStatesCache) Get(blockID proto.BlockID) (*proto.Block, bool) { - block, ok := c.blockStates[blockID] + bs, ok := c.blockStates[blockID] if !ok { return nil, false } - return &block, true + return &bs.Block, true } func initNGStateInFSM(state *StateData, fsm *stateless.StateMachine, info BaseInfo) { diff --git a/pkg/node/fsm/wait_snapshot_state.go b/pkg/node/fsm/wait_snapshot_state.go index 72f598557..d3410e8c5 100644 --- a/pkg/node/fsm/wait_snapshot_state.go +++ b/pkg/node/fsm/wait_snapshot_state.go @@ -6,7 +6,6 @@ import ( "github.com/wavesplatform/gowaves/pkg/metrics" "github.com/wavesplatform/gowaves/pkg/p2p/peer" "github.com/wavesplatform/gowaves/pkg/proto" - "github.com/wavesplatform/gowaves/pkg/state" "go.uber.org/zap" ) @@ -60,13 +59,13 @@ func (a *WaitSnapshotState) Block(peer peer.Peer, block *proto.Block) (State, As a.blockCache.AddBlockState(block) } -func (a *WaitSnapshotState) BlockSnapshot(peer peer.Peer, blockID proto.BlockID, snapshots state.TransactionSnapshot) (State, Async, error) { +func (a *WaitSnapshotState) BlockSnapshot(peer peer.Peer, blockID proto.BlockID, snapshots proto.BlockSnapshot) (State, Async, error) { // check if this snapshot for our block if _, ok := a.blockCache.Get(blockID); !ok { return newNGLightState(a.baseInfo), nil, a.Errorf(errors.Errorf("Snapshot for the block '%s' doestn match", blockID)) } - _, err := a.baseInfo.snapshotApplier.Apply(a.baseInfo.storage, []state.TransactionSnapshot{snapshots}, []proto.BlockID{blockID}) + _, err := a.baseInfo.snapshotApplier.Apply(a.baseInfo.storage, []proto.BlockSnapshot{snapshots}, []proto.BlockID{blockID}) if err != nil { //metrics.FSMKeyBlockDeclined("ng", block, err) return a, nil, a.Errorf(errors.Wrapf(err, "peer '%s'", peer.ID())) diff --git a/pkg/proto/block_snapshot.go b/pkg/proto/block_snapshot.go new file mode 100644 index 000000000..79ec07f1e --- /dev/null +++ b/pkg/proto/block_snapshot.go @@ -0,0 +1,55 @@ +package proto + +import ( + "encoding/binary" + "github.com/pkg/errors" + g "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" +) + +type BlockSnapshot struct { + TxSnapshots [][]AtomicSnapshot +} + +func (bs BlockSnapshot) MarshallBinary() ([]byte, error) { + result := []byte{} + var txSnCnt [4]byte + binary.BigEndian.PutUint32(txSnCnt[0:4], uint32(len(bs.TxSnapshots))) + result = append(result, txSnCnt[:]...) + for _, ts := range bs.TxSnapshots { + var res g.TransactionStateSnapshot + for _, atomicSnapshot := range ts { + if err := atomicSnapshot.AppendToProtobuf(&res); err != nil { + return nil, errors.Wrap(err, "failed to marshall TransactionSnapshot to proto") + } + } + tsBytes, err := res.MarshalVTStrict() + if err != nil { + return nil, err + } + var bytesLen [4]byte + binary.BigEndian.PutUint32(bytesLen[0:4], uint32(len(tsBytes))) + result = append(result, bytesLen[:]...) + result = append(result, tsBytes...) + } + return result, nil +} + +func (bs *BlockSnapshot) UnmarshalBinary(data []byte, scheme Scheme) error { + txSnCnt := binary.BigEndian.Uint32(data[0:4]) + data = data[4:] + for i := uint32(0); i <= txSnCnt; i++ { + tsBytesLen := binary.BigEndian.Uint32(data[0:4]) + var tsProto *g.TransactionStateSnapshot + err := tsProto.UnmarshalVT(data[0:tsBytesLen]) + if err != nil { + return err + } + atomicTs, err := TxSnapshotsFromProtobuf(scheme, tsProto) + if err != nil { + return err + } + bs.TxSnapshots = append(bs.TxSnapshots, atomicTs) + data = data[tsBytesLen:] + } + return nil +} diff --git a/pkg/proto/proto.go b/pkg/proto/proto.go index bccf870da..29deac5af 100644 --- a/pkg/proto/proto.go +++ b/pkg/proto/proto.go @@ -2113,24 +2113,67 @@ func (m *GetBlockSnapshotMessage) MarshalBinary() ([]byte, error) { } type BlockSnapshotMessage struct { - BlockID BlockID - Snapshots state.TransactionSnapshot + Bytes []byte } -func (m *BlockSnapshotMessage) ReadFrom(_ io.Reader) (n int64, err error) { - panic("implement me") +func (m *BlockSnapshotMessage) ReadFrom(r io.Reader) (int64, error) { + packet, nn, err := readPacket(r) + if err != nil { + return nn, err + } + + return nn, m.UnmarshalBinary(packet) } -func (m *BlockSnapshotMessage) WriteTo(_ io.Writer) (n int64, err error) { - panic("implement me") +func (m *BlockSnapshotMessage) WriteTo(w io.Writer) (int64, error) { + buf, err := m.MarshalBinary() + if err != nil { + return 0, err + } + nn, err := w.Write(buf) + n := int64(nn) + return n, err } -func (m *BlockSnapshotMessage) UnmarshalBinary(_ []byte) error { - panic("implement me") +func (m *BlockSnapshotMessage) UnmarshalBinary(data []byte) error { + if len(data) < 17 { + return errors.New("BlockSnapshotMessage UnmarshalBinary: invalid data size") + } + var h Header + + if err := h.UnmarshalBinary(data); err != nil { + return err + } + if h.Magic != headerMagic { + return fmt.Errorf("wrong magic in Header: %x", h.Magic) + } + if h.ContentID != ContentIDBlockSnapshot { + return fmt.Errorf("wrong ContentID in Header: %x", h.ContentID) + } + m.Bytes = data[17:] + return nil } func (m *BlockSnapshotMessage) MarshalBinary() (data []byte, err error) { - panic("ads") + body := m.Bytes + + var h Header + h.Length = maxHeaderLength + uint32(len(body)) - 4 + h.Magic = headerMagic + h.ContentID = ContentIDBlockSnapshot + h.PayloadLength = uint32(len(body)) + dig, err := crypto.FastHash(body) + if err != nil { + return nil, err + } + copy(h.PayloadChecksum[:], dig[:4]) + + hdr, err := h.MarshalBinary() + if err != nil { + return nil, err + } + body = append(hdr, body...) + return body, nil } type MicroBlockSnapshotMessage struct { diff --git a/pkg/proto/protobuf_converters.go b/pkg/proto/protobuf_converters.go index 14182debc..858bd215a 100644 --- a/pkg/proto/protobuf_converters.go +++ b/pkg/proto/protobuf_converters.go @@ -60,6 +60,135 @@ func SignedTxFromProtobuf(data []byte) (Transaction, error) { return res, nil } +func TxSnapshotsFromProtobuf(scheme Scheme, txSnapshot *g.TransactionStateSnapshot) ([]AtomicSnapshot, error) { + var txSnapshots []AtomicSnapshot + for _, balance := range txSnapshot.Balances { + if balance.Amount.AssetId == nil { + var sn WavesBalanceSnapshot + err := sn.FromProtobuf(scheme, balance) + if err != nil { + return nil, err + } + txSnapshots = append(txSnapshots, sn) + } else { + var sn AssetBalanceSnapshot + err := sn.FromProtobuf(scheme, balance) + if err != nil { + return nil, err + } + txSnapshots = append(txSnapshots, sn) + } + } + for _, lBalance := range txSnapshot.LeaseBalances { + var sn LeaseBalanceSnapshot + err := sn.FromProtobuf(scheme, lBalance) + if err != nil { + return nil, err + } + txSnapshots = append(txSnapshots, sn) + } + for _, assetStatic := range txSnapshot.AssetStatics { + var sn StaticAssetInfoSnapshot + err := sn.FromProtobuf(scheme, assetStatic) + if err != nil { + return nil, err + } + txSnapshots = append(txSnapshots, sn) + } + for _, assetVolume := range txSnapshot.AssetVolumes { + var sn AssetVolumeSnapshot + err := sn.FromProtobuf(scheme, assetVolume) + if err != nil { + return nil, err + } + txSnapshots = append(txSnapshots, sn) + } + for _, assetNameAndDescr := range txSnapshot.AssetNamesAndDescriptions { + var sn AssetDescriptionSnapshot + err := sn.FromProtobuf(scheme, assetNameAndDescr) + if err != nil { + return nil, err + } + txSnapshots = append(txSnapshots, sn) + } + for _, assetScript := range txSnapshot.AssetScripts { + var sn AssetScriptSnapshot + err := sn.FromProtobuf(scheme, assetScript) + if err != nil { + return nil, err + } + txSnapshots = append(txSnapshots, sn) + } + for _, alias := range txSnapshot.Aliases { + var sn AliasSnapshot + err := sn.FromProtobuf(scheme, alias) + if err != nil { + return nil, err + } + txSnapshots = append(txSnapshots, sn) + } + for _, orderFill := range txSnapshot.OrderFills { + var sn FilledVolumeFeeSnapshot + err := sn.FromProtobuf(scheme, orderFill) + if err != nil { + return nil, err + } + txSnapshots = append(txSnapshots, sn) + } + for _, leaseState := range txSnapshot.LeaseStates { + var sn LeaseStateSnapshot + err := sn.FromProtobuf(scheme, leaseState) + if err != nil { + return nil, err + } + txSnapshots = append(txSnapshots, sn) + } + for _, accountScript := range txSnapshot.AccountScripts { + var sn AccountScriptSnapshot + err := sn.FromProtobuf(scheme, accountScript) + if err != nil { + return nil, err + } + txSnapshots = append(txSnapshots, sn) + } + for _, accountData := range txSnapshot.AccountData { + var sn DataEntriesSnapshot + err := sn.FromProtobuf(scheme, accountData) + if err != nil { + return nil, err + } + txSnapshots = append(txSnapshots, sn) + } + for _, sponsorship := range txSnapshot.Sponsorships { + var sn SponsorshipSnapshot + err := sn.FromProtobuf(scheme, sponsorship) + if err != nil { + return nil, err + } + txSnapshots = append(txSnapshots, sn) + } + var sn TransactionStatusSnapshot + err := sn.FromProtobuf(scheme, txSnapshot.TransactionStatus) + if err != nil { + return nil, err + } + txSnapshots = append(txSnapshots, sn) + return txSnapshots, nil +} + +func BlockSnapshotFromProtobuf(scheme Scheme, blockSnapshot []*g.TransactionStateSnapshot) (BlockSnapshot, error) { + res := BlockSnapshot{TxSnapshots: make([][]AtomicSnapshot, 0, len(blockSnapshot))} + for _, ts := range blockSnapshot { + var txSnapshots []AtomicSnapshot + txSnapshots, err := TxSnapshotsFromProtobuf(scheme, ts) + if err != nil { + return BlockSnapshot{}, err + } + res.TxSnapshots = append(res.TxSnapshots, txSnapshots) + } + return res, nil +} + type ProtobufConverter struct { FallbackChainID byte err error diff --git a/pkg/proto/snapshot_types.go b/pkg/proto/snapshot_types.go index 914404886..0c1e15e98 100644 --- a/pkg/proto/snapshot_types.go +++ b/pkg/proto/snapshot_types.go @@ -47,6 +47,21 @@ func (s WavesBalanceSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSn return nil } +func (s *WavesBalanceSnapshot) FromProtobuf(scheme Scheme, p *g.TransactionStateSnapshot_Balance) error { + var c ProtobufConverter + addr, err := c.Address(scheme, p.Address) + if err != nil { + return err + } + amount := c.amount(p.Amount) + if c.err != nil { + return err + } + s.Address = addr + s.Balance = amount + return nil +} + type AssetBalanceSnapshot struct { Address WavesAddress AssetID crypto.Digest @@ -69,6 +84,27 @@ func (s AssetBalanceSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_Balance, }, nil } +func (s *AssetBalanceSnapshot) FromProtobuf(scheme Scheme, p *g.TransactionStateSnapshot_Balance) error { + var c ProtobufConverter + addr, err := c.Address(scheme, p.Address) + if err != nil { + return err + } + amount := c.amount(p.Amount) + if c.err != nil { + return c.err + } + c.reset() + asset := c.extractOptionalAsset(p.Amount) + if c.err != nil { + return c.err + } + s.Address = addr + s.Balance = amount + s.AssetID = asset.ID + return nil +} + func (s AssetBalanceSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) error { snapshotInProto, err := s.ToProtobuf() if err != nil { @@ -109,6 +145,25 @@ func (s DataEntriesSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSna return nil } +func (s *DataEntriesSnapshot) FromProtobuf(scheme Scheme, p *g.TransactionStateSnapshot_AccountData) error { + var c ProtobufConverter + addr, err := c.Address(scheme, p.Address) + if err != nil { + return err + } + var dataEntries []DataEntry + for _, e := range p.Entries { + dataEntries = append(dataEntries, c.entry(e)) + if c.err != nil { + return c.err + } + c.reset() + } + s.Address = addr + s.DataEntries = dataEntries + return nil +} + type AccountScriptSnapshot struct { SenderPublicKey crypto.PublicKey Script Script @@ -138,6 +193,23 @@ func (s AccountScriptSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateS return nil } +func (s *AccountScriptSnapshot) FromProtobuf(_ Scheme, p *g.TransactionStateSnapshot_AccountScript) error { + var c ProtobufConverter + publicKey := c.publicKey(p.SenderPublicKey) + if c.err != nil { + return c.err + } + c.reset() + script := c.script(p.Script) + if c.err != nil { + return c.err + } + s.SenderPublicKey = publicKey + s.Script = script + s.VerifierComplexity = uint64(p.VerifierComplexity) + return nil +} + type AssetScriptSnapshot struct { AssetID crypto.Digest Script Script @@ -165,6 +237,22 @@ func (s AssetScriptSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSna return nil } +func (s *AssetScriptSnapshot) FromProtobuf(_ Scheme, p *g.TransactionStateSnapshot_AssetScript) error { + var c ProtobufConverter + asset := c.optionalAsset(p.AssetId) + if c.err != nil { + return c.err + } + c.reset() + script := c.script(p.Script) + if c.err != nil { + return c.err + } + s.AssetID = asset.ID + s.Script = script + return nil +} + type LeaseBalanceSnapshot struct { Address WavesAddress LeaseIn uint64 @@ -194,8 +282,18 @@ func (s LeaseBalanceSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSn return nil } -func (s LeaseBalanceSnapshot) IsInternal() bool { - return false +func (s *LeaseBalanceSnapshot) FromProtobuf(scheme Scheme, p *g.TransactionStateSnapshot_LeaseBalance) error { + var c ProtobufConverter + addr, err := c.Address(scheme, p.Address) + if err != nil { + return err + } + c.reset() + + s.Address = addr + s.LeaseIn = uint64(p.In) + s.LeaseOut = uint64(p.Out) + return nil } type LeaseStateStatus struct { @@ -232,11 +330,15 @@ func (s LeaseStateSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_LeaseState } switch s.Status.Value { case LeaseActive: - res.Status = &g.TransactionStateSnapshot_LeaseState_Active{} + res.Status = &g.TransactionStateSnapshot_LeaseState_Active_{ + Active: &g.TransactionStateSnapshot_LeaseState_Active{}, + } case LeaseCanceled: - res.Status = &g.TransactionStateSnapshot_LeaseState_Cancelled{ - Height: int32(s.Status.CancelHeight), - TransactionId: s.Status.CancelTransactionID.Bytes(), + res.Status = &g.TransactionStateSnapshot_LeaseState_Cancelled_{ + Cancelled: &g.TransactionStateSnapshot_LeaseState_Cancelled{ + Height: int32(s.Status.CancelHeight), + TransactionId: s.Status.CancelTransactionID.Bytes(), + }, } default: return nil, errors.Errorf("Failed to serialize LeaseStateSnapshot to Proto: invalid Lease status") @@ -253,6 +355,51 @@ func (s LeaseStateSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnap return nil } +func (s *LeaseStateSnapshot) FromProtobuf(scheme Scheme, p *g.TransactionStateSnapshot_LeaseState) error { + var c ProtobufConverter + leaseId := c.digest(p.LeaseId) + if c.err != nil { + return c.err + } + c.reset() + sender, err := c.Address(scheme, p.Sender) + if err != nil { + return err + } + c.reset() + recipientAddr, err := c.Address(scheme, p.Sender) + if err != nil { + return err + } + c.reset() + txId := c.digest(p.OriginTransactionId) + if c.err != nil { + return c.err + } + c.reset() + var status LeaseStateStatus + if p.GetActive() != nil { + status.Value = LeaseActive + } else if cancel := p.GetCancelled(); cancel != nil { + status.Value = LeaseCanceled + status.CancelHeight = uint64(cancel.Height) + cancelTxId := c.digest(p.OriginTransactionId) + if c.err != nil { + return c.err + } + c.reset() + status.CancelTransactionID = &cancelTxId + } + s.LeaseID = leaseId + s.Amount = uint64(p.Amount) + s.Sender = sender + s.Recipient = recipientAddr + s.OriginTransactionID = &txId + s.Height = uint64(p.Height) + s.Status = status + return nil +} + type SponsorshipSnapshot struct { AssetID crypto.Digest MinSponsoredFee uint64 @@ -280,6 +427,17 @@ func (s SponsorshipSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSna return nil } +func (s *SponsorshipSnapshot) FromProtobuf(_ Scheme, p *g.TransactionStateSnapshot_Sponsorship) error { + var c ProtobufConverter + asset := c.optionalAsset(p.AssetId) + if c.err != nil { + return c.err + } + s.AssetID = asset.ID + s.MinSponsoredFee = uint64(p.MinFee) + return nil +} + type AliasSnapshot struct { Address WavesAddress Alias Alias @@ -307,6 +465,17 @@ func (s AliasSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) return nil } +func (s *AliasSnapshot) FromProtobuf(scheme Scheme, p *g.TransactionStateSnapshot_Alias) error { + var c ProtobufConverter + addr, err := c.Address(scheme, p.Address) + if err != nil { + return err + } + s.Address = addr + s.Alias.Alias = p.Alias + return nil +} + // FilledVolumeFeeSnapshot Filled Volume and Fee. type FilledVolumeFeeSnapshot struct { // OrderFill OrderID crypto.Digest @@ -337,6 +506,20 @@ func (s FilledVolumeFeeSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStat return nil } +func (s *FilledVolumeFeeSnapshot) FromProtobuf(_ Scheme, p *g.TransactionStateSnapshot_OrderFill) error { + var c ProtobufConverter + orderId := c.digest(p.OrderId) + if c.err != nil { + return c.err + } + c.reset() + + s.OrderID = orderId + s.FilledVolume = uint64(p.Volume) + s.FilledFee = uint64(p.Fee) + return nil +} + type StaticAssetInfoSnapshot struct { AssetID crypto.Digest SourceTransactionID crypto.Digest @@ -370,6 +553,31 @@ func (s StaticAssetInfoSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStat return nil } +func (s *StaticAssetInfoSnapshot) FromProtobuf(_ Scheme, p *g.TransactionStateSnapshot_AssetStatic) error { + var c ProtobufConverter + assetId := c.digest(p.AssetId) + if c.err != nil { + return c.err + } + c.reset() + txId := c.digest(p.SourceTransactionId) + if c.err != nil { + return c.err + } + c.reset() + publicKey := c.publicKey(p.IssuerPublicKey) + if c.err != nil { + return c.err + } + c.reset() + s.AssetID = assetId + s.SourceTransactionID = txId + s.IssuerPublicKey = publicKey + s.Decimals = uint8(p.Decimals) + s.IsNFT = p.Nft + return nil +} + type AssetVolumeSnapshot struct { // AssetVolume in pb AssetID crypto.Digest TotalQuantity big.Int // volume in protobuf @@ -399,6 +607,19 @@ func (s AssetVolumeSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSna return nil } +func (s *AssetVolumeSnapshot) FromProtobuf(_ Scheme, p *g.TransactionStateSnapshot_AssetVolume) error { + var c ProtobufConverter + assetId := c.digest(p.AssetId) + if c.err != nil { + return c.err + } + + s.AssetID = assetId + s.TotalQuantity.SetBytes(p.Volume) + s.IsReissuable = p.Reissuable + return nil +} + type AssetDescriptionSnapshot struct { // AssetNameAndDescription in pb AssetID crypto.Digest AssetName string @@ -430,6 +651,20 @@ func (s AssetDescriptionSnapshot) AppendToProtobuf(txSnapshots *g.TransactionSta return nil } +func (s *AssetDescriptionSnapshot) FromProtobuf(_ Scheme, p *g.TransactionStateSnapshot_AssetNameAndDescription) error { + var c ProtobufConverter + assetId := c.digest(p.AssetId) + if c.err != nil { + return c.err + } + + s.AssetID = assetId + s.AssetName = p.Name + s.AssetDescription = p.Description + s.ChangeHeight = uint64(p.LastUpdated) + return nil +} + type TransactionStatusSnapshot struct { TransactionID crypto.Digest Status TransactionStatus @@ -443,6 +678,20 @@ func (s TransactionStatusSnapshot) IsGeneratedByTxDiff() bool { return false } +func (s *TransactionStatusSnapshot) FromProtobuf(_ Scheme, p g.TransactionStatus) error { + switch p { + case g.TransactionStatus_SUCCEEDED: + s.Status = TransactionSucceeded + case g.TransactionStatus_FAILED: + s.Status = TransactionFailed + case g.TransactionStatus_ELIDED: + s.Status = TransactionElided + default: + return errors.Errorf("Undefinded tx status %d", p) + } + return nil +} + func (s TransactionStatusSnapshot) AppendToProtobuf(txSnapshots *g.TransactionStateSnapshot) error { switch s.Status { case TransactionSucceeded: diff --git a/pkg/ride/meta/generated/dapp_meta.pb.go b/pkg/ride/meta/generated/dapp_meta.pb.go index c18ab0294..719b08123 100644 --- a/pkg/ride/meta/generated/dapp_meta.pb.go +++ b/pkg/ride/meta/generated/dapp_meta.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v4.24.3 +// protoc v4.24.4 // source: waves/lang/dapp_meta.proto package generated diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 130b3861a..ef0d5ef5e 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -153,6 +153,7 @@ type appendBlockParams struct { chans *verifierChans block, parent *proto.BlockHeader height uint64 + snapshot proto.BlockSnapshot } func (a *txAppender) orderIsScripted(order proto.Order) (bool, error) { @@ -776,6 +777,96 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { return a.blockDiffer.saveCurFeeDistr(params.block) } +func (a *txAppender) appendBlockWithSnapshot(params *appendBlockParams) error { + // Reset block complexity counter. + defer func() { + a.sc.resetComplexity() + a.totalScriptsRuns = 0 + }() + rideV5Activated, err := a.stor.features.newestIsActivated(int16(settings.RideV5)) + if err != nil { + return err + } + rideV6Activated, err := a.stor.features.newestIsActivated(int16(settings.RideV6)) + if err != nil { + return err + } + blockRewardDistribution, err := a.stor.features.newestIsActivated(int16(settings.BlockRewardDistribution)) + if err != nil { + return err + } + checkerInfo := &checkerInfo{ + currentTimestamp: params.block.Timestamp, + blockID: params.block.BlockID(), + blockVersion: params.block.Version, + height: params.height, + rideV5Activated: rideV5Activated, + rideV6Activated: rideV6Activated, + blockRewardDistribution: blockRewardDistribution, + } + hasParent := params.parent != nil + if hasParent { + checkerInfo.parentTimestamp = params.parent.Timestamp + } + stateActionsCounterInBlockValidation := new(proto.StateActionsCounter) + // stateActionsCounterInSnapshots := new(proto.StateActionsCounter) + + snapshotApplier := newBlockSnapshotsApplier( + blockSnapshotsApplierInfo{ + ci: checkerInfo, + scheme: a.settings.AddressSchemeCharacter, + stateActionsCounter: stateActionsCounterInBlockValidation, + }, + snapshotApplierStorages{ + balances: a.stor.balances, + aliases: a.stor.aliases, + assets: a.stor.assets, + scriptsStorage: a.stor.scriptsStorage, + scriptsComplexity: a.stor.scriptsComplexity, + sponsoredAssets: a.stor.sponsoredAssets, + ordersVolumes: a.stor.ordersVolumes, + accountsDataStor: a.stor.accountsDataStor, + leases: a.stor.leases, + }, + ) + snapshotGenerator := snapshotGenerator{stor: a.stor, scheme: a.settings.AddressSchemeCharacter, IsFullNodeMode: true} + + // 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. + minerAndRewardDiff, err := a.blockDiffer.createMinerAndRewardDiff(params.block, hasParent) + if err != nil { + return err + } + // create the initial snapshot + _, err = a.createInitialBlockSnapshot(minerAndRewardDiff) + if err != nil { + return errors.Wrap(err, "failed to create initial snapshot") + } + + // TODO apply this snapshot when balances are refatored + // err = initialSnapshot.Apply(&snapshotApplier) + + // Save miner diff first (for validation) + if err = a.diffStor.saveTxDiff(minerAndRewardDiff); err != nil { + return err + } + + for _, txs := range params.snapshot.TxSnapshots { + for _, snapshot := range txs { + if errApply := snapshot.Apply(&snapshotApplier); errApply != nil { + return errors.Wrap(errApply, "failed to apply tx snapshot") + } + } + } + if err = a.stor.snapshots.saveSnapshots(params.block.BlockID(), params.height, params.snapshot); err != nil { + return err + } + // Save fee distribution of this block. + // This will be needed for createMinerAndRewardDiff() of next block due to NG. + return a.blockDiffer.saveCurFeeDistr(params.block) +} + // used only in tests now. All diffs are applied in snapshotApplier. func (a *txAppender) applyAllDiffs() error { a.recentTxIds = make(map[string]struct{}) diff --git a/pkg/state/state.go b/pkg/state/state.go index ed593ece3..1dd54882b 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -1105,6 +1105,61 @@ func (s *stateManager) addNewBlock(block, parent *proto.Block, chans *verifierCh return nil } +func (s *stateManager) addNewBlockWithSnapshot(block, parent *proto.Block, snapshots proto.BlockSnapshot, chans *verifierChans, height uint64) error { + blockHeight := height + 1 + // Add score. + if err := s.stor.scores.appendBlockScore(block, blockHeight); err != nil { + return err + } + // Indicate new block for storage. + if err := s.rw.startBlock(block.BlockID()); err != nil { + return err + } + // Save block header to block storage. + if err := s.rw.writeBlockHeader(&block.BlockHeader); err != nil { + return err + } + transactions := block.Transactions + if block.TransactionCount != transactions.Count() { + return errors.Errorf("block.TransactionCount != transactions.Count(), %d != %d", block.TransactionCount, transactions.Count()) + } + var parentHeader *proto.BlockHeader + if parent != nil { + parentHeader = &parent.BlockHeader + } + params := &appendBlockParams{ + transactions: transactions, + chans: chans, + block: &block.BlockHeader, + parent: parentHeader, + height: height, + snapshot: snapshots, + } + // Check and perform block's transactions, create balance diffs, write transactions to storage. + if err := s.appender.appendBlockWithSnapshot(params); err != nil { + return err + } + // Let block storage know that the current block is over. + if err := s.rw.finishBlock(block.BlockID()); err != nil { + return err + } + // when block is finished blockchain height is incremented, so we should use 'blockHeight' as height value in actions below + + // Count features votes. + if err := s.addFeaturesVotes(block); err != nil { + return err + } + blockRewardActivated := s.stor.features.newestIsActivatedAtHeight(int16(settings.BlockReward), blockHeight) + // Count reward vote. + if blockRewardActivated { + err := s.addRewardVote(block, blockHeight) + if err != nil { + return err + } + } + return nil +} + func (s *stateManager) reset() { s.rw.reset() s.stor.reset() @@ -1176,6 +1231,21 @@ func (s *stateManager) AddDeserializedBlocks(blocks []*proto.Block) (*proto.Bloc return lastBlock, nil } +func (s *stateManager) AddDeserializedBlocksWithSnapshots( + blocks []*proto.Block, + snapshots []proto.BlockSnapshot, +) (*proto.Block, error) { + s.newBlocks.setNew(blocks) + lastBlock, err := s.addBlocksWithSnapshots(snapshots) + if err != nil { + if err := s.rw.syncWithDb(); err != nil { + zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) + } + return nil, err + } + return lastBlock, nil +} + func (s *stateManager) needToFinishVotingPeriod(blockchainHeight proto.Height) bool { nextBlockHeight := blockchainHeight + 1 votingFinishHeight := (nextBlockHeight % s.settings.ActivationWindowSize(nextBlockHeight)) == 0 @@ -1556,6 +1626,123 @@ func (s *stateManager) addBlocks() (*proto.Block, error) { return lastAppliedBlock, nil } +func (s *stateManager) addBlocksWithSnapshots(snapshots []proto.BlockSnapshot) (*proto.Block, error) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + defer func() { + // Reset in-memory storages and load last block in defer. + s.reset() + if err := s.loadLastBlock(); err != nil { + zap.S().Fatalf("Failed to load last block: %v", err) + } + s.newBlocks.reset() + }() + + blocksNumber := s.newBlocks.len() + if blocksNumber == 0 { + return nil, wrapErr(InvalidInputError, errors.New("no blocks provided")) + } + + // Read some useful values for later. + lastAppliedBlock, err := s.topBlock() + if err != nil { + return nil, wrapErr(RetrievalError, err) + } + zap.S().Debugf("StateManager: parent (top) block ID: %s, ts: %d", lastAppliedBlock.BlockID().String(), lastAppliedBlock.Timestamp) + height, err := s.Height() + if err != nil { + return nil, wrapErr(RetrievalError, err) + } + headers := make([]proto.BlockHeader, blocksNumber) + + // Launch verifier that checks signatures of blocks and transactions. + chans := launchVerifier(ctx, s.verificationGoroutinesNum, s.settings.AddressSchemeCharacter) + + var ids []proto.BlockID + pos := 0 + for s.newBlocks.next() { + blockchainCurHeight := height + uint64(pos) + block, err := s.newBlocks.current() + if err != nil { + return nil, wrapErr(DeserializationError, err) + } + if err := s.cv.ValidateHeaderBeforeBlockApplying(&block.BlockHeader, blockchainCurHeight); err != nil { + return nil, err + } + // Assign unique block number for this block ID, add this number to the list of valid blocks. + if err := s.stateDB.addBlock(block.BlockID()); err != nil { + return nil, wrapErr(ModificationError, err) + } + // At some blockchain heights specific logic is performed. + // This includes voting for features, block rewards and so on. + if err := s.blockchainHeightAction(blockchainCurHeight, lastAppliedBlock.BlockID(), block.BlockID()); err != nil { + return nil, wrapErr(ModificationError, err) + } + // Send block for signature verification, which works in separate goroutine. + task := &verifyTask{ + taskType: verifyBlock, + parentID: lastAppliedBlock.BlockID(), + block: block, + } + if err := chans.trySend(task); err != nil { + return nil, err + } + hs, err := s.cv.GenerateHitSource(blockchainCurHeight, block.BlockHeader) + if err != nil { + return nil, err + } + if err := s.stor.hitSources.appendBlockHitSource(block, blockchainCurHeight+1, hs); err != nil { + return nil, err + } + // Save block to storage, check its transactions, create and save balance diffs for its transactions. + if err := s.addNewBlockWithSnapshot(block, lastAppliedBlock, snapshots[pos], chans, blockchainCurHeight); err != nil { + return nil, err + } + + if s.needToFinishVotingPeriod(blockchainCurHeight + 1) { + // If we need to finish voting period on the next block (h+1) then + // we have to check that protobuf will be activated on next block + s.checkProtobufActivation(blockchainCurHeight + 2) + } + headers[pos] = block.BlockHeader + pos++ + ids = append(ids, block.BlockID()) + lastAppliedBlock = block + } + // Tasks chan can now be closed, since all the blocks and transactions have been already sent for verification. + // wait for all verifier goroutines + if verifyError := chans.closeAndWait(); verifyError != nil { + return nil, wrapErr(ValidationError, verifyError) + } + + // Apply all the balance diffs accumulated from this blocks batch. + // This also validates diffs for negative balances. + if err := s.appender.applyAllDiffs(); err != nil { + return nil, err + } + + // Retrieve and store state hashes for each of new blocks. + if err := s.stor.handleStateHashes(height, ids); err != nil { + return nil, wrapErr(ModificationError, err) + } + // Validate consensus (i.e. that all the new blocks were mined fairly). + if err := s.cv.ValidateHeadersBatch(headers[:pos], height); err != nil { + return nil, wrapErr(ValidationError, err) + } + // After everything is validated, save all the changes to DB. + if err := s.flush(); err != nil { + return nil, wrapErr(ModificationError, err) + } + zap.S().Infof( + "Height: %d; Block ID: %s, GenSig: %s, ts: %d", + height+uint64(blocksNumber), + lastAppliedBlock.BlockID().String(), + base58.Encode(lastAppliedBlock.GenSignature), + lastAppliedBlock.Timestamp, + ) + return lastAppliedBlock, nil +} + func (s *stateManager) checkRollbackHeight(height uint64) error { maxHeight, err := s.Height() if err != nil { From bce2fa127182892aa934e062e65a8ad85aa301b1 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Tue, 12 Dec 2023 20:56:50 +0300 Subject: [PATCH 088/139] add light node --- cmd/node/node.go | 2 +- itests/config/template.conf | 1 + pkg/grpc/server/blockchain_api_test.go | 2 +- pkg/grpc/server/blocks_api_test.go | 6 +- pkg/libs/microblock_cache/microblock_cache.go | 33 ++- pkg/libs/ordered_blocks/optimistic_load.go | 59 ++-- .../ordered_blocks/optimistic_load_test.go | 20 +- pkg/mock/state.go | 32 +-- pkg/node/actions_by_type.go | 104 +++++-- pkg/node/blocks_applier/blocks_applier.go | 88 ++++-- .../blocks_applier/blocks_applier_test.go | 8 +- pkg/node/blocks_applier/node_mocks.go | 17 +- pkg/node/fsm/fsm.go | 35 ++- pkg/node/fsm/fsm_common.go | 16 +- pkg/node/fsm/halt_state.go | 4 +- pkg/node/fsm/idle_state.go | 7 +- pkg/node/fsm/ng/inv_request.go | 9 +- pkg/node/fsm/ng/inv_request_test.go | 5 +- pkg/node/fsm/ng_light_state.go | 143 ---------- pkg/node/fsm/ng_state.go | 247 ++++++++++++++--- pkg/node/fsm/persist_state.go | 6 + pkg/node/fsm/sync_internal/internal.go | 48 +++- pkg/node/fsm/sync_internal/internal_test.go | 18 +- pkg/node/fsm/sync_state.go | 90 +++++- pkg/node/fsm/tasks/tasks.go | 51 ++++ pkg/node/fsm/wait_snapshot_state.go | 83 ------ pkg/node/metrics.go | 24 -- pkg/node/snapshot_applier/snapshot_applier.go | 25 -- pkg/p2p/peer/extension/extension.go | 8 + pkg/proto/block_snapshot.go | 14 + pkg/proto/proto.go | 107 ++++++-- pkg/services/services.go | 6 +- pkg/state/address_transactions_test.go | 2 +- pkg/state/api.go | 4 +- pkg/state/appender.go | 140 ++++------ pkg/state/state.go | 257 ++++-------------- pkg/state/threadsafe_wrapper.go | 14 +- 37 files changed, 922 insertions(+), 813 deletions(-) delete mode 100644 pkg/node/fsm/ng_light_state.go delete mode 100644 pkg/node/fsm/wait_snapshot_state.go delete mode 100644 pkg/node/snapshot_applier/snapshot_applier.go diff --git a/cmd/node/node.go b/cmd/node/node.go index 24896eabf..123b44274 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -482,7 +482,7 @@ func main() { LoggableRunner: logRunner, Time: ntpTime, Wallet: wal, - MicroBlockCache: microblock_cache.NewMicroblockCache(), + MicroBlockCache: microblock_cache.NewMicroBlockCache(), InternalChannel: messages.NewInternalChannel(), MinPeersMining: nc.minPeersMining, SkipMessageList: parent.SkipMessageList, diff --git a/itests/config/template.conf b/itests/config/template.conf index 9a2f005da..9c3963dde 100644 --- a/itests/config/template.conf +++ b/itests/config/template.conf @@ -2,6 +2,7 @@ waves { blockchain.type = CUSTOM directory = /var/lib/waves/ ntp-server = "localhost:123" + enable-light-mode = false db { store-state-hashes = true } diff --git a/pkg/grpc/server/blockchain_api_test.go b/pkg/grpc/server/blockchain_api_test.go index 0785db6df..588181d85 100644 --- a/pkg/grpc/server/blockchain_api_test.go +++ b/pkg/grpc/server/blockchain_api_test.go @@ -34,7 +34,7 @@ func TestGetBaseTarget(t *testing.T) { newTarget := 171657201 blocks, err := state.ReadMainnetBlocksToHeight(proto.Height(3)) assert.NoError(t, err) - _, err = st.AddDeserializedBlocks(blocks) + _, err = st.AddDeserializedBlocks(blocks, nil) assert.NoError(t, err) // Check new base target. res, err = cl.GetBaseTarget(ctx, &emptypb.Empty{}) diff --git a/pkg/grpc/server/blocks_api_test.go b/pkg/grpc/server/blocks_api_test.go index 14db94c18..eaac2cded 100644 --- a/pkg/grpc/server/blocks_api_test.go +++ b/pkg/grpc/server/blocks_api_test.go @@ -48,7 +48,7 @@ func TestGetBlock(t *testing.T) { blockHeight := proto.Height(99) blocks, err := state.ReadMainnetBlocksToHeight(blockHeight) assert.NoError(t, err) - _, err = st.AddDeserializedBlocks(blocks) + _, err = st.AddDeserializedBlocks(blocks, nil) assert.NoError(t, err) // Retrieve expected block. correctBlockProto := blockFromState(t, blockHeight, st) @@ -95,7 +95,7 @@ func TestGetBlockRange(t *testing.T) { blockHeight := proto.Height(99) blocks, err := state.ReadMainnetBlocksToHeight(blockHeight) assert.NoError(t, err) - _, err = st.AddDeserializedBlocks(blocks) + _, err = st.AddDeserializedBlocks(blocks, nil) assert.NoError(t, err) // With transactions. @@ -169,7 +169,7 @@ func TestGetCurrentHeight(t *testing.T) { blockHeight := proto.Height(99) blocks, err := state.ReadMainnetBlocksToHeight(blockHeight) assert.NoError(t, err) - _, err = st.AddDeserializedBlocks(blocks) + _, err = st.AddDeserializedBlocks(blocks, nil) assert.NoError(t, err) res, err = cl.GetCurrentHeight(ctx, &emptypb.Empty{}) diff --git a/pkg/libs/microblock_cache/microblock_cache.go b/pkg/libs/microblock_cache/microblock_cache.go index f83f0aca0..69f3c8c3a 100644 --- a/pkg/libs/microblock_cache/microblock_cache.go +++ b/pkg/libs/microblock_cache/microblock_cache.go @@ -5,28 +5,43 @@ import ( "github.com/wavesplatform/gowaves/pkg/util/fifo_cache" ) -type MicroblockCache struct { - cache *fifo_cache.FIFOCache +const microBlockCacheSize = 24 + +type MicroBlockCache struct { + blockCache *fifo_cache.FIFOCache + snapshotCache *fifo_cache.FIFOCache } -func NewMicroblockCache() *MicroblockCache { - return &MicroblockCache{ - cache: fifo_cache.New(24), +func NewMicroBlockCache() *MicroBlockCache { + return &MicroBlockCache{ + blockCache: fifo_cache.New(microBlockCacheSize), + snapshotCache: fifo_cache.New(microBlockCacheSize), } } -func (a *MicroblockCache) Add(blockID proto.BlockID, micro *proto.MicroBlock) { - a.cache.Add2(blockID.Bytes(), micro) +func (a *MicroBlockCache) Add(blockID proto.BlockID, micro *proto.MicroBlock) { + a.blockCache.Add2(blockID.Bytes(), micro) } -func (a *MicroblockCache) Get(sig proto.BlockID) (*proto.MicroBlock, bool) { - rs, ok := a.cache.Get(sig.Bytes()) +func (a *MicroBlockCache) Get(sig proto.BlockID) (*proto.MicroBlock, bool) { + rs, ok := a.blockCache.Get(sig.Bytes()) if !ok { return nil, false } return rs.(*proto.MicroBlock), true } +func (a *MicroBlockCache) AddSnapshot(blockID proto.BlockID, snapshot *proto.BlockSnapshot) { + a.snapshotCache.Add2(blockID.Bytes(), snapshot) +} +func (a *MicroBlockCache) GetSnapshot(sig proto.BlockID) (*proto.BlockSnapshot, bool) { + rs, ok := a.snapshotCache.Get(sig.Bytes()) + if !ok { + return nil, false + } + return rs.(*proto.BlockSnapshot), true +} + type MicroblockInvCache struct { cache *fifo_cache.FIFOCache } diff --git a/pkg/libs/ordered_blocks/optimistic_load.go b/pkg/libs/ordered_blocks/optimistic_load.go index 5de85e720..c428ccd20 100644 --- a/pkg/libs/ordered_blocks/optimistic_load.go +++ b/pkg/libs/ordered_blocks/optimistic_load.go @@ -5,14 +5,16 @@ import ( ) type OrderedBlocks struct { - requested []proto.BlockID - blocks map[proto.BlockID]*proto.Block + requestedBlocks []proto.BlockID + blocks map[proto.BlockID]*proto.Block + snapshots map[proto.BlockID]*proto.BlockSnapshot } func NewOrderedBlocks() *OrderedBlocks { return &OrderedBlocks{ - requested: nil, - blocks: make(map[proto.BlockID]*proto.Block), + requestedBlocks: nil, + blocks: make(map[proto.BlockID]*proto.Block), + snapshots: make(map[proto.BlockID]*proto.BlockSnapshot), } } @@ -25,28 +27,36 @@ func (a *OrderedBlocks) SetBlock(b *proto.Block) { a.blocks[b.BlockID()] = b } -func (a *OrderedBlocks) pop() (proto.BlockID, *proto.Block, bool) { - if len(a.requested) == 0 { - return proto.BlockID{}, nil, false +func (a *OrderedBlocks) SetSnapshot(blockID proto.BlockID, snapshot *proto.BlockSnapshot) { + a.snapshots[blockID] = snapshot +} + +func (a *OrderedBlocks) pop() (proto.BlockID, *proto.Block, *proto.BlockSnapshot, bool) { + if len(a.requestedBlocks) == 0 { + return proto.BlockID{}, nil, nil, false } - firstSig := a.requested[0] + firstSig := a.requestedBlocks[0] bts := a.blocks[firstSig] - if bts != nil { + bsn := a.snapshots[firstSig] + if bts != nil && bsn != nil { delete(a.blocks, firstSig) - a.requested = a.requested[1:] - return firstSig, bts, true + delete(a.snapshots, firstSig) + a.requestedBlocks = a.requestedBlocks[1:] + return firstSig, bts, bsn, true } - return proto.BlockID{}, nil, false + return proto.BlockID{}, nil, nil, false } -func (a *OrderedBlocks) PopAll() []*proto.Block { - var out []*proto.Block +func (a *OrderedBlocks) PopAll() ([]*proto.Block, []*proto.BlockSnapshot) { + var outBlocks []*proto.Block + var outSnapshots []*proto.BlockSnapshot for { - _, b, ok := a.pop() + _, b, s, ok := a.pop() if !ok { - return out + return outBlocks, outSnapshots } - out = append(out, b) + outBlocks = append(outBlocks, b) + outSnapshots = append(outSnapshots, s) } } @@ -56,21 +66,24 @@ func (a *OrderedBlocks) Add(sig proto.BlockID) bool { if _, ok := a.blocks[sig]; ok { return false } - a.requested = append(a.requested, sig) + a.requestedBlocks = append(a.requestedBlocks, sig) a.blocks[sig] = nil + a.snapshots[sig] = nil return true } func (a *OrderedBlocks) RequestedCount() int { - return len(a.requested) + return len(a.requestedBlocks) } // blocks count available for pop -func (a *OrderedBlocks) ReceivedCount() int { - for i, sig := range a.requested { - if a.blocks[sig] == nil { +func (a *OrderedBlocks) ReceivedCount(isLightNode bool) int { + for i, sig := range a.requestedBlocks { + if isLightNode && a.blocks[sig] == nil || a.snapshots[sig] == nil { + return i + } else if !isLightNode && a.blocks[sig] == nil { return i } } - return len(a.requested) + return len(a.requestedBlocks) } diff --git a/pkg/libs/ordered_blocks/optimistic_load_test.go b/pkg/libs/ordered_blocks/optimistic_load_test.go index d44907d94..335af63f7 100644 --- a/pkg/libs/ordered_blocks/optimistic_load_test.go +++ b/pkg/libs/ordered_blocks/optimistic_load_test.go @@ -23,34 +23,38 @@ func makeBlock(sig crypto.Signature) *proto.Block { func TestOrderedBlocks(t *testing.T) { o := ordered_blocks.NewOrderedBlocks() o.Add(proto.NewBlockIDFromSignature(sig1)) - require.Len(t, o.PopAll(), 0) + b, _ := o.PopAll() + require.Len(t, b, 0) + b, _ = o.PopAll() o.Add(proto.NewBlockIDFromSignature(sig2)) - require.Len(t, o.PopAll(), 0) + require.Len(t, b, 0) // second block arrived first, no sequence right now o.SetBlock(makeBlock(sig2)) - require.Len(t, o.PopAll(), 0) + b, _ = o.PopAll() + require.Len(t, b, 0) //require.Equal(t, 0, o.ReceivedCount()) // finally arrived first block, so seq contains 2 blocks o.SetBlock(makeBlock(sig1)) //require.Equal(t, 2, o.ReceivedCount()) - require.Len(t, o.PopAll(), 2) + b, _ = o.PopAll() + require.Len(t, b, 2) } func TestOrderedBlocks_AvailableCount(t *testing.T) { o := ordered_blocks.NewOrderedBlocks() o.Add(proto.NewBlockIDFromSignature(sig1)) o.Add(proto.NewBlockIDFromSignature(sig2)) - require.Equal(t, 0, o.ReceivedCount()) + require.Equal(t, 0, o.ReceivedCount(false)) o.SetBlock(makeBlock(sig1)) - require.Equal(t, 1, o.ReceivedCount()) + require.Equal(t, 1, o.ReceivedCount(false)) o.SetBlock(makeBlock(sig2)) - require.Equal(t, 2, o.ReceivedCount()) + require.Equal(t, 2, o.ReceivedCount(false)) o.PopAll() - require.Equal(t, 0, o.ReceivedCount()) + require.Equal(t, 0, o.ReceivedCount(false)) } diff --git a/pkg/mock/state.go b/pkg/mock/state.go index d6ff78d57..13fb1ff83 100644 --- a/pkg/mock/state.go +++ b/pkg/mock/state.go @@ -1086,33 +1086,33 @@ func (mr *MockStateModifierMockRecorder) AddBlocks(blocks interface{}) *gomock.C } // AddDeserializedBlock mocks base method. -func (m *MockStateModifier) AddDeserializedBlock(block *proto.Block) (*proto.Block, error) { +func (m *MockStateModifier) AddDeserializedBlock(block *proto.Block, snapshot *proto.BlockSnapshot) (*proto.Block, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddDeserializedBlock", block) + ret := m.ctrl.Call(m, "AddDeserializedBlock", block, snapshot) ret0, _ := ret[0].(*proto.Block) ret1, _ := ret[1].(error) return ret0, ret1 } // AddDeserializedBlock indicates an expected call of AddDeserializedBlock. -func (mr *MockStateModifierMockRecorder) AddDeserializedBlock(block interface{}) *gomock.Call { +func (mr *MockStateModifierMockRecorder) AddDeserializedBlock(block, snapshot interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlock", reflect.TypeOf((*MockStateModifier)(nil).AddDeserializedBlock), block) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlock", reflect.TypeOf((*MockStateModifier)(nil).AddDeserializedBlock), block, snapshot) } // AddDeserializedBlocks mocks base method. -func (m *MockStateModifier) AddDeserializedBlocks(blocks []*proto.Block) (*proto.Block, error) { +func (m *MockStateModifier) AddDeserializedBlocks(blocks []*proto.Block, snapshots []*proto.BlockSnapshot) (*proto.Block, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddDeserializedBlocks", blocks) + ret := m.ctrl.Call(m, "AddDeserializedBlocks", blocks, snapshots) ret0, _ := ret[0].(*proto.Block) ret1, _ := ret[1].(error) return ret0, ret1 } // AddDeserializedBlocks indicates an expected call of AddDeserializedBlocks. -func (mr *MockStateModifierMockRecorder) AddDeserializedBlocks(blocks interface{}) *gomock.Call { +func (mr *MockStateModifierMockRecorder) AddDeserializedBlocks(blocks, snapshots interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlocks", reflect.TypeOf((*MockStateModifier)(nil).AddDeserializedBlocks), blocks) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlocks", reflect.TypeOf((*MockStateModifier)(nil).AddDeserializedBlocks), blocks, snapshots) } // Close mocks base method. @@ -1344,33 +1344,33 @@ func (mr *MockStateMockRecorder) AddBlocks(blocks interface{}) *gomock.Call { } // AddDeserializedBlock mocks base method. -func (m *MockState) AddDeserializedBlock(block *proto.Block) (*proto.Block, error) { +func (m *MockState) AddDeserializedBlock(block *proto.Block, snapshot *proto.BlockSnapshot) (*proto.Block, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddDeserializedBlock", block) + ret := m.ctrl.Call(m, "AddDeserializedBlock", block, snapshot) ret0, _ := ret[0].(*proto.Block) ret1, _ := ret[1].(error) return ret0, ret1 } // AddDeserializedBlock indicates an expected call of AddDeserializedBlock. -func (mr *MockStateMockRecorder) AddDeserializedBlock(block interface{}) *gomock.Call { +func (mr *MockStateMockRecorder) AddDeserializedBlock(block, snapshot interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlock", reflect.TypeOf((*MockState)(nil).AddDeserializedBlock), block) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlock", reflect.TypeOf((*MockState)(nil).AddDeserializedBlock), block, snapshot) } // AddDeserializedBlocks mocks base method. -func (m *MockState) AddDeserializedBlocks(blocks []*proto.Block) (*proto.Block, error) { +func (m *MockState) AddDeserializedBlocks(blocks []*proto.Block, snapshots []*proto.BlockSnapshot) (*proto.Block, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddDeserializedBlocks", blocks) + ret := m.ctrl.Call(m, "AddDeserializedBlocks", blocks, snapshots) ret0, _ := ret[0].(*proto.Block) ret1, _ := ret[1].(error) return ret0, ret1 } // AddDeserializedBlocks indicates an expected call of AddDeserializedBlocks. -func (mr *MockStateMockRecorder) AddDeserializedBlocks(blocks interface{}) *gomock.Call { +func (mr *MockStateMockRecorder) AddDeserializedBlocks(blocks, snapshots interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlocks", reflect.TypeOf((*MockState)(nil).AddDeserializedBlocks), blocks) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlocks", reflect.TypeOf((*MockState)(nil).AddDeserializedBlocks), blocks, snapshots) } // AddrByAlias mocks base method. diff --git a/pkg/node/actions_by_type.go b/pkg/node/actions_by_type.go index 47502d554..3b95c7b41 100644 --- a/pkg/node/actions_by_type.go +++ b/pkg/node/actions_by_type.go @@ -1,19 +1,18 @@ package node import ( - g "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" "math/big" "reflect" - "github.com/wavesplatform/gowaves/pkg/logging" - "github.com/wavesplatform/gowaves/pkg/node/peers/storage" - - protobuf "google.golang.org/protobuf/proto" - + "github.com/pkg/errors" "go.uber.org/zap" + protobuf "google.golang.org/protobuf/proto" "github.com/wavesplatform/gowaves/pkg/crypto" + g "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" + "github.com/wavesplatform/gowaves/pkg/logging" "github.com/wavesplatform/gowaves/pkg/node/fsm" + "github.com/wavesplatform/gowaves/pkg/node/peers/storage" "github.com/wavesplatform/gowaves/pkg/p2p/peer" "github.com/wavesplatform/gowaves/pkg/p2p/peer/extension" "github.com/wavesplatform/gowaves/pkg/proto" @@ -258,37 +257,95 @@ func PBTransactionAction(_ services.Services, mess peer.ProtoMessage, fsm *fsm.F return fsm.Transaction(mess.ID, t) } -func MicroSnapshotRequestAction(_ services.Services, mess peer.ProtoMessage, fsm *fsm.FSM) (fsm.Async, error) { - metricMicroSnapshotRequestMessage.Inc() +func MicroSnapshotRequestAction(services services.Services, mess peer.ProtoMessage, _ *fsm.FSM) (fsm.Async, error) { + blockID, err := proto.NewBlockIDFromBytes(mess.Message.(*proto.MicroBlockSnapshotRequestMessage).BlockIDBytes) + if err != nil { + return nil, err + } + sn, ok := services.MicroBlockCache.GetSnapshot(blockID) + if ok { + snapshotProto, errToProto := sn.ToProtobuf() + if errToProto != nil { + return nil, errToProto + } + sProto := g.MicroBlockSnapshot{ + Snapshots: snapshotProto, + TotalBlockId: mess.Message.(*proto.MicroBlockSnapshotRequestMessage).BlockIDBytes, + } + bsmBytes, errMarshall := protobuf.Marshal(&sProto) + if errMarshall != nil { + return nil, errMarshall + } + bs := proto.MicroBlockSnapshotMessage{Bytes: bsmBytes} + mess.ID.SendMessage(&bs) + } + return nil, nil } -func GetSnapshotAction(services services.Services, mess peer.ProtoMessage, fsm *fsm.FSM) (fsm.Async, error) { - metricGetSnapshotMessage.Inc() - block, err := services.State.Block(mess.Message.(*proto.GetBlockMessage).BlockID) +func GetSnapshotAction(services services.Services, mess peer.ProtoMessage, _ *fsm.FSM) (fsm.Async, error) { + h, err := services.State.BlockIDToHeight(mess.Message.(*proto.GetBlockSnapshotMessage).BlockID) if err != nil { - return nil, nil + return nil, err } - bm, err := proto.MessageByBlock(block, services.Scheme) + snapshot, err := services.State.SnapshotsAtHeight(h) if err != nil { - return nil, nil + return nil, err } - mess.ID.SendMessage(bm) + snapshotProto, err := snapshot.ToProtobuf() + if err != nil { + return nil, err + } + sProto := g.BlockSnapshot{ + Snapshots: snapshotProto, + BlockId: mess.Message.(*proto.GetBlockSnapshotMessage).BlockID.Bytes(), + } + bsmBytes, err := protobuf.Marshal(&sProto) + if err != nil { + return nil, err + } + bs := proto.BlockSnapshotMessage{Bytes: bsmBytes} + mess.ID.SendMessage(&bs) return nil, nil } -func SnapshotAction(services services.Services, mess peer.ProtoMessage, fsm *fsm.FSM) (fsm.Async, error) { - metricSnapshotMessage.Inc() - m := mess.Message.(*proto.BlockSnapshotMessage) - protoMess := &g.BlockSnapshot{} - if err := protobuf.Unmarshal(m.Bytes, protoMess); err != nil { +func BlockSnapshotAction(services services.Services, mess peer.ProtoMessage, fsm *fsm.FSM) (fsm.Async, error) { + m, ok := mess.Message.(*proto.BlockSnapshotMessage) + if !ok { + return nil, errors.New("Message is not BlockSnapshot") + } + protoMess := g.BlockSnapshot{} + if err := protobuf.Unmarshal(m.Bytes, &protoMess); err != nil { + return nil, err + } + blockID, err := proto.NewBlockIDFromBytes(protoMess.BlockId) + if err != nil { + return nil, err + } + blockSnapshot, err := proto.BlockSnapshotFromProtobuf(services.Scheme, protoMess.Snapshots) + if err != nil { + return nil, err + } + return fsm.BlockSnapshot(mess.ID, blockID, blockSnapshot) +} + +func MicroBlockSnapshotAction(services services.Services, mess peer.ProtoMessage, fsm *fsm.FSM) (fsm.Async, error) { + m, ok := mess.Message.(*proto.MicroBlockSnapshotMessage) + if !ok { + return nil, errors.New("Message is not MicroBlockSnapshotMessage") + } + protoMess := g.MicroBlockSnapshot{} + if err := protobuf.Unmarshal(m.Bytes, &protoMess); err != nil { return nil, err } - blockId, err := proto.NewBlockIDFromBytes(protoMess.BlockId) + blockID, err := proto.NewBlockIDFromBytes(protoMess.TotalBlockId) if err != nil { return nil, err } blockSnapshot, err := proto.BlockSnapshotFromProtobuf(services.Scheme, protoMess.Snapshots) - return fsm.BlockSnapshot(mess.ID, blockId, blockSnapshot) + if err != nil { + return nil, err + } + return fsm.MicroBlockSnapshot(mess.ID, blockID, blockSnapshot) } func createActions() map[reflect.Type]Action { @@ -311,6 +368,7 @@ func createActions() map[reflect.Type]Action { reflect.TypeOf(&proto.PBTransactionMessage{}): PBTransactionAction, reflect.TypeOf(&proto.GetBlockSnapshotMessage{}): GetSnapshotAction, reflect.TypeOf(&proto.MicroBlockSnapshotRequestMessage{}): MicroSnapshotRequestAction, - reflect.TypeOf(&proto.BlockSnapshotMessage{}): SnapshotAction, + reflect.TypeOf(&proto.BlockSnapshotMessage{}): BlockSnapshotAction, + reflect.TypeOf(&proto.MicroBlockSnapshotMessage{}): MicroBlockSnapshotAction, } } diff --git a/pkg/node/blocks_applier/blocks_applier.go b/pkg/node/blocks_applier/blocks_applier.go index 7191bfe23..e4127a885 100644 --- a/pkg/node/blocks_applier/blocks_applier.go +++ b/pkg/node/blocks_applier/blocks_applier.go @@ -8,6 +8,8 @@ import ( "github.com/wavesplatform/gowaves/pkg/state" ) +const maxRollbackDeltaHeight = 100 + type innerBlocksApplier struct { } @@ -16,9 +18,10 @@ type innerState interface { Height() (proto.Height, error) ScoreAtHeight(height proto.Height) (*big.Int, error) BlockIDToHeight(blockID proto.BlockID) (proto.Height, error) - AddDeserializedBlocks(blocks []*proto.Block) (*proto.Block, error) + AddDeserializedBlocks(blocks []*proto.Block, snapshots []*proto.BlockSnapshot) (*proto.Block, error) BlockByHeight(height proto.Height) (*proto.Block, error) RollbackToHeight(height proto.Height) error + SnapshotsAtHeight(height proto.Height) (proto.BlockSnapshot, error) } func (a *innerBlocksApplier) exists(storage innerState, block *proto.Block) (bool, error) { @@ -32,7 +35,11 @@ func (a *innerBlocksApplier) exists(storage innerState, block *proto.Block) (boo return false, err } -func (a *innerBlocksApplier) apply(storage innerState, blocks []*proto.Block) (proto.Height, error) { +func (a *innerBlocksApplier) apply( + storage innerState, + blocks []*proto.Block, + snapshots []*proto.BlockSnapshot, +) (proto.Height, error) { if len(blocks) == 0 { return 0, errors.New("empty blocks") } @@ -76,11 +83,11 @@ func (a *innerBlocksApplier) apply(storage innerState, blocks []*proto.Block) (p currentScore.String(), cumulativeScore.String())) } - // so, new blocks has higher score, try apply it. + // so, new blocks has higher score, try to apply it. // Do we need rollback? if parentHeight == currentHeight { // no, don't rollback, just add blocks - _, err := storage.AddDeserializedBlocks(blocks) + _, err = storage.AddDeserializedBlocks(blocks, snapshots) if err != nil { return 0, err } @@ -88,18 +95,14 @@ func (a *innerBlocksApplier) apply(storage innerState, blocks []*proto.Block) (p } deltaHeight := currentHeight - parentHeight - if deltaHeight > 100 { // max number that we can rollback + if deltaHeight > maxRollbackDeltaHeight { // max number that we can rollback return 0, errors.Errorf("can't apply new blocks, rollback more than 100 blocks, %d", deltaHeight) } // save previously added blocks. If new firstBlock failed to add, then return them back - rollbackBlocks := make([]*proto.Block, 0, deltaHeight) - for i := proto.Height(1); i <= deltaHeight; i++ { - block, err := storage.BlockByHeight(parentHeight + i) - if err != nil { - return 0, errors.Wrapf(err, "failed to get firstBlock by height %d", parentHeight+i) - } - rollbackBlocks = append(rollbackBlocks, block) + rollbackBlocks, rollbackBlocksSnapshots, err := a.getRollbackBlocksAndSnapshots(storage, deltaHeight, parentHeight) + if err != nil { + return 0, err } err = storage.RollbackToHeight(parentHeight) @@ -107,10 +110,10 @@ func (a *innerBlocksApplier) apply(storage innerState, blocks []*proto.Block) (p return 0, errors.Wrapf(err, "failed to rollback to height %d", parentHeight) } // applying new blocks - _, err = storage.AddDeserializedBlocks(blocks) + _, err = storage.AddDeserializedBlocks(blocks, snapshots) if err != nil { // return back saved blocks - _, err2 := storage.AddDeserializedBlocks(rollbackBlocks) + _, err2 := storage.AddDeserializedBlocks(rollbackBlocks, rollbackBlocksSnapshots) if err2 != nil { return 0, errors.Wrap(err2, "failed rollback deserialized blocks") } @@ -119,7 +122,34 @@ func (a *innerBlocksApplier) apply(storage innerState, blocks []*proto.Block) (p return parentHeight + proto.Height(len(blocks)), nil } -func (a *innerBlocksApplier) applyMicro(storage innerState, block *proto.Block) (proto.Height, error) { +func (a *innerBlocksApplier) getRollbackBlocksAndSnapshots( + storage innerState, + deltaHeight proto.Height, + parentHeight proto.Height, +) ([]*proto.Block, []*proto.BlockSnapshot, error) { + rollbackBlocks := make([]*proto.Block, 0, deltaHeight) + rollbackBlocksSnapshots := make([]*proto.BlockSnapshot, 0, deltaHeight) + for i := proto.Height(1); i <= deltaHeight; i++ { + block, err := storage.BlockByHeight(parentHeight + i) + if err != nil { + return nil, nil, errors.Wrapf(err, "failed to get firstBlock by height %d", parentHeight+i) + } + rollbackBlocks = append(rollbackBlocks, block) + + snapshot, err := storage.SnapshotsAtHeight(parentHeight + i) + if err != nil { + return nil, nil, errors.Wrapf(err, "failed to get snapshot by height %d", parentHeight+i) + } + rollbackBlocksSnapshots = append(rollbackBlocksSnapshots, &snapshot) + } + return rollbackBlocks, rollbackBlocksSnapshots, nil +} + +func (a *innerBlocksApplier) applyMicro( + storage innerState, + block *proto.Block, + snapshot *proto.BlockSnapshot, +) (proto.Height, error) { _, err := storage.Block(block.BlockID()) if err == nil { return 0, errors.Errorf("block '%s' already exist", block.BlockID().String()) @@ -145,17 +175,23 @@ func (a *innerBlocksApplier) applyMicro(storage innerState, block *proto.Block) if err != nil { return 0, errors.Wrapf(err, "failed to get current block by height %d", currentHeight) } - + currentSnapshot, err := storage.SnapshotsAtHeight(currentHeight) + if err != nil { + return 0, err + } err = storage.RollbackToHeight(parentHeight) if err != nil { return 0, errors.Wrapf(err, "failed to rollback to height %d", parentHeight) } // applying new blocks - _, err = storage.AddDeserializedBlocks([]*proto.Block{block}) + _, err = storage.AddDeserializedBlocks([]*proto.Block{block}, []*proto.BlockSnapshot{snapshot}) if err != nil { // return back saved blocks - _, err2 := storage.AddDeserializedBlocks([]*proto.Block{currentBlock}) + _, err2 := storage.AddDeserializedBlocks( + []*proto.Block{currentBlock}, + []*proto.BlockSnapshot{¤tSnapshot}, + ) if err2 != nil { return 0, errors.Wrap(err2, "failed rollback block") } @@ -178,12 +214,20 @@ func (a *BlocksApplier) BlockExists(state state.State, block *proto.Block) (bool return a.inner.exists(state, block) } -func (a *BlocksApplier) Apply(state state.State, blocks []*proto.Block) (proto.Height, error) { - return a.inner.apply(state, blocks) +func (a *BlocksApplier) Apply( + state state.State, + blocks []*proto.Block, + snapshots []*proto.BlockSnapshot, +) (proto.Height, error) { + return a.inner.apply(state, blocks, snapshots) } -func (a *BlocksApplier) ApplyMicro(state state.State, block *proto.Block) (proto.Height, error) { - return a.inner.applyMicro(state, block) +func (a *BlocksApplier) ApplyMicro( + state state.State, + block *proto.Block, + snapshot *proto.BlockSnapshot, +) (proto.Height, error) { + return a.inner.applyMicro(state, block, snapshot) } func calcMultipleScore(blocks []*proto.Block) (*big.Int, error) { diff --git a/pkg/node/blocks_applier/blocks_applier_test.go b/pkg/node/blocks_applier/blocks_applier_test.go index 225bc4ead..b811e179b 100644 --- a/pkg/node/blocks_applier/blocks_applier_test.go +++ b/pkg/node/blocks_applier/blocks_applier_test.go @@ -50,7 +50,7 @@ func TestApply_ValidBlockWithRollback(t *testing.T) { require.NoError(t, err) ba := innerBlocksApplier{} - height, err := ba.apply(mockState, []*proto.Block{block2}) + height, err := ba.apply(mockState, []*proto.Block{block2}, nil) require.NoError(t, err) require.EqualValues(t, 2, height) newBlock, _ := mockState.BlockByHeight(2) @@ -98,12 +98,12 @@ func TestApply_InvalidBlockWithRollback(t *testing.T) { // rollback to first(genesis) block stateMock.EXPECT().RollbackToHeight(proto.Height(1)).Return(nil) // adding new blocks, and have error on applying - stateMock.EXPECT().AddDeserializedBlocks([]*proto.Block{block2}).Return(nil, errors.New("error message")) + stateMock.EXPECT().AddDeserializedBlocks([]*proto.Block{block2}, nil).Return(nil, errors.New("error message")) // return blocks - stateMock.EXPECT().AddDeserializedBlocks([]*proto.Block{block1}).Return(nil, nil) + stateMock.EXPECT().AddDeserializedBlocks([]*proto.Block{block1}, nil).Return(nil, nil) ba := innerBlocksApplier{} - _, err := ba.apply(stateMock, []*proto.Block{block2}) + _, err := ba.apply(stateMock, []*proto.Block{block2}, nil) require.NotNil(t, err) require.Equal(t, "failed add deserialized blocks, first block id sV8beveiVKCiUn9BGZRgZj7V5tRRWPMRj1V9WWzKWnigtfQyZ2eErVXHi7vyGXj5hPuaxF9sGxowZr5XuD4UAwW: error message", err.Error()) } diff --git a/pkg/node/blocks_applier/node_mocks.go b/pkg/node/blocks_applier/node_mocks.go index 2c53bab89..68513e809 100644 --- a/pkg/node/blocks_applier/node_mocks.go +++ b/pkg/node/blocks_applier/node_mocks.go @@ -15,6 +15,7 @@ func notFound() state.StateError { type MockStateManager struct { state []*proto.Block + snapshots []*proto.BlockSnapshot id2Block map[proto.BlockID]*proto.Block Peers_ []proto.TCPAddr blockIDToHeight map[proto.BlockID]proto.Height @@ -275,13 +276,18 @@ func (a *MockStateManager) AddDeserializedBlock(block *proto.Block) (*proto.Bloc a.blockIDToHeight[block.BlockID()] = proto.Height(len(a.state)) return block, nil } -func (a *MockStateManager) AddDeserializedBlocks(blocks []*proto.Block) (*proto.Block, error) { + +func (a *MockStateManager) AddDeserializedBlocks( + blocks []*proto.Block, + snapshots []*proto.BlockSnapshot, +) (*proto.Block, error) { var out *proto.Block var err error - for _, b := range blocks { + for i, b := range blocks { if out, err = a.AddDeserializedBlock(b); err != nil { return nil, err } + a.snapshots = append(a.snapshots, snapshots[i]) } return out, nil } @@ -337,3 +343,10 @@ func (a *MockStateManager) StartProvidingExtendedApi() error { func (a *MockStateManager) HitSourceAtHeight(_ proto.Height) ([]byte, error) { panic("not implemented") } + +func (a *MockStateManager) SnapshotsAtHeight(h proto.Height) (proto.BlockSnapshot, error) { + if h > proto.Height(len(a.snapshots)) { + return proto.BlockSnapshot{}, notFound() + } + return *a.snapshots[h-1], nil +} diff --git a/pkg/node/fsm/fsm.go b/pkg/node/fsm/fsm.go index acb483dcd..8d86eedff 100644 --- a/pkg/node/fsm/fsm.go +++ b/pkg/node/fsm/fsm.go @@ -2,7 +2,6 @@ package fsm import ( "context" - "github.com/wavesplatform/gowaves/pkg/node/snapshot_applier" "time" "github.com/pkg/errors" @@ -28,8 +27,8 @@ type Async []tasks.Task type BlocksApplier interface { BlockExists(state storage.State, block *proto.Block) (bool, error) - Apply(state storage.State, block []*proto.Block) (proto.Height, error) - ApplyMicro(state storage.State, block *proto.Block) (proto.Height, error) + Apply(state storage.State, block []*proto.Block, snapshots []*proto.BlockSnapshot) (proto.Height, error) + ApplyMicro(state storage.State, block *proto.Block, snapshots *proto.BlockSnapshot) (proto.Height, error) } type BaseInfo struct { @@ -42,11 +41,10 @@ type BaseInfo struct { // ntp time tm types.Time - scheme proto.Scheme - invRequester InvRequester - blocksApplier BlocksApplier - snapshotApplier *snapshot_applier.SnapshotApplier - obsolescence time.Duration + scheme proto.Scheme + invRequester InvRequester + blocksApplier BlocksApplier + obsolescence time.Duration // scheduler scheduler types.Scheduler @@ -106,10 +104,12 @@ const ( TransactionEvent = "Transaction" HaltEvent = "Halt" - StopSyncEvent = "StopSync" - StopMiningEvent = "StopMining" - StartMiningEvent = "StartMining" - ChangeSyncPeerEvent = "ChangeSyncPeer" + StopSyncEvent = "StopSync" + StopMiningEvent = "StopMining" + StartMiningEvent = "StartMining" + ChangeSyncPeerEvent = "ChangeSyncPeer" + BlockSnapshotEvent = "BlockSnapshotEvent" + MicroBlockSnapshotEvent = "MicroBlockSnapshotEvent" ) type FSM struct { @@ -145,9 +145,8 @@ func NewFSM( obsolescence: obsolescence, // - invRequester: ng.NewInvRequester(), - blocksApplier: services.BlocksApplier, - snapshotApplier: snapshot_applier.NewSnapshotApplier(), + invRequester: ng.NewInvRequester(), + blocksApplier: services.BlocksApplier, scheduler: services.Scheduler, @@ -304,3 +303,9 @@ func (f *FSM) BlockSnapshot(p peer.Peer, blockID proto.BlockID, snapshots proto. err := f.fsm.Fire(BlockSnapshotEvent, asyncRes, p, blockID, snapshots) return *asyncRes, err } + +func (f *FSM) MicroBlockSnapshot(p peer.Peer, blockID proto.BlockID, snapshots proto.BlockSnapshot) (Async, error) { + asyncRes := &Async{} + err := f.fsm.Fire(MicroBlockSnapshotEvent, asyncRes, p, blockID, snapshots) + return *asyncRes, err +} diff --git a/pkg/node/fsm/fsm_common.go b/pkg/node/fsm/fsm_common.go index 9f2ec52ff..6a18499e0 100644 --- a/pkg/node/fsm/fsm_common.go +++ b/pkg/node/fsm/fsm_common.go @@ -65,6 +65,16 @@ func eventArgsTypes(event stateless.Trigger) []reflect.Type { reflect.TypeOf(&Async{}), reflect.TypeOf((*peer.Peer)(nil)).Elem(), reflect.TypeOf((*proto.Transaction)(nil)).Elem(), } + case BlockSnapshotEvent: + return []reflect.Type{ + reflect.TypeOf(&Async{}), reflect.TypeOf((*peer.Peer)(nil)).Elem(), reflect.TypeOf(proto.BlockID{}), + reflect.TypeOf(proto.BlockSnapshot{}), + } + case MicroBlockSnapshotEvent: + return []reflect.Type{ + reflect.TypeOf(&Async{}), reflect.TypeOf((*peer.Peer)(nil)).Elem(), reflect.TypeOf(proto.BlockID{}), + reflect.TypeOf(proto.BlockSnapshot{}), + } default: return nil } @@ -76,7 +86,11 @@ func syncWithNewPeer(state State, baseInfo BaseInfo, p peer.Peer) (State, Async, if err != nil { return state, nil, err } - internal := sync_internal.InternalFromLastSignatures(extension.NewPeerExtension(p, baseInfo.scheme), lastSignatures) + internal := sync_internal.InternalFromLastSignatures( + extension.NewPeerExtension(p, baseInfo.scheme), + lastSignatures, + baseInfo.enableLightMode, + ) c := conf{ peerSyncWith: p, timeout: defaultSyncTimeout, diff --git a/pkg/node/fsm/halt_state.go b/pkg/node/fsm/halt_state.go index bb9ffb84f..3d048fdac 100644 --- a/pkg/node/fsm/halt_state.go +++ b/pkg/node/fsm/halt_state.go @@ -73,5 +73,7 @@ func initHaltStateInFSM(_ *StateData, fsm *stateless.StateMachine, info BaseInfo Ignore(StartMiningEvent). Ignore(ChangeSyncPeerEvent). Ignore(StopMiningEvent). - Ignore(HaltEvent) + Ignore(HaltEvent). + Ignore(BlockSnapshotEvent). + Ignore(MicroBlockSnapshotEvent) } diff --git a/pkg/node/fsm/idle_state.go b/pkg/node/fsm/idle_state.go index ee3c06283..447ddb6f3 100644 --- a/pkg/node/fsm/idle_state.go +++ b/pkg/node/fsm/idle_state.go @@ -17,7 +17,7 @@ import ( type InvRequester interface { Add2Cache(id []byte) (existed bool) - Request(p types.MessageSender, id []byte) (existed bool) + Request(p types.MessageSender, id []byte, enableLightNode bool) (existed bool) } type IdleState struct { @@ -109,6 +109,9 @@ func initIdleStateInFSM(state *StateData, fsm *stateless.StateMachine, b BaseInf proto.ContentIDPBMicroBlock, proto.ContentIDPBTransaction, proto.ContentIDBlockIds, + proto.ContentIDBlockSnapshot, + proto.ContentIDMicroBlockSnapshot, + proto.ContentIDMicroBlockSnapshotRequest, } fsm.Configure(IdleStateName). OnEntry(func(ctx context.Context, args ...interface{}) error { @@ -122,6 +125,8 @@ func initIdleStateInFSM(state *StateData, fsm *stateless.StateMachine, b BaseInf Ignore(StopSyncEvent). Ignore(ChangeSyncPeerEvent). Ignore(StopMiningEvent). + Ignore(BlockSnapshotEvent). + Ignore(MicroBlockSnapshotEvent). PermitDynamic(StartMiningEvent, createPermitDynamicCallback(StartMiningEvent, state, func(args ...interface{}) (State, Async, error) { a, ok := state.State.(*IdleState) diff --git a/pkg/node/fsm/ng/inv_request.go b/pkg/node/fsm/ng/inv_request.go index b79b8b0a1..ad77652ba 100644 --- a/pkg/node/fsm/ng/inv_request.go +++ b/pkg/node/fsm/ng/inv_request.go @@ -25,12 +25,17 @@ func (a *InvRequesterImpl) Add2Cache(id []byte) (existed bool) { return false } -func (a *InvRequesterImpl) Request(p types.MessageSender, id []byte) (existed bool) { - existed = a.Add2Cache(id) +func (a *InvRequesterImpl) Request(p types.MessageSender, id []byte, enableLightNode bool) bool { + existed := a.Add2Cache(id) if !existed { p.SendMessage(&proto.MicroBlockRequestMessage{ TotalBlockSig: id, }) + if enableLightNode { + p.SendMessage(&proto.MicroBlockSnapshotRequestMessage{ + BlockIDBytes: id, + }) + } } return existed } diff --git a/pkg/node/fsm/ng/inv_request_test.go b/pkg/node/fsm/ng/inv_request_test.go index 0e9ee246b..d0c0dd792 100644 --- a/pkg/node/fsm/ng/inv_request_test.go +++ b/pkg/node/fsm/ng/inv_request_test.go @@ -21,10 +21,9 @@ func TestInvRequesterImpl_Request(t *testing.T) { buf := &messSender{} n := NewInvRequester() - n.Request(buf, proto.NewBlockIDFromSignature(crypto.Signature{}).Bytes()) + n.Request(buf, proto.NewBlockIDFromSignature(crypto.Signature{}).Bytes(), false) require.Equal(t, 1, len(buf.messages)) - n.Request(buf, proto.NewBlockIDFromSignature(crypto.Signature{}).Bytes()) + n.Request(buf, proto.NewBlockIDFromSignature(crypto.Signature{}).Bytes(), false) require.Equal(t, 1, len(buf.messages)) - } diff --git a/pkg/node/fsm/ng_light_state.go b/pkg/node/fsm/ng_light_state.go deleted file mode 100644 index 4a7d3049c..000000000 --- a/pkg/node/fsm/ng_light_state.go +++ /dev/null @@ -1,143 +0,0 @@ -package fsm - -import ( - "context" - "github.com/pkg/errors" - "github.com/qmuntal/stateless" - "github.com/wavesplatform/gowaves/pkg/node/fsm/tasks" - "github.com/wavesplatform/gowaves/pkg/p2p/peer" - "github.com/wavesplatform/gowaves/pkg/proto" -) - -type NGLightState struct { - baseInfo BaseInfo - blockCache *blockStatesCache -} - -func newNGLightState(baseInfo BaseInfo) State { - baseInfo.syncPeer.Clear() - return &NGLightState{ - baseInfo: baseInfo, - } -} - -func (a *NGLightState) Errorf(err error) error { - return fsmErrorf(a, err) -} - -func (a *NGLightState) String() string { - return NGLightStateName -} - -func (a *NGLightState) Block(peer peer.Peer, block *proto.Block) (State, Async, error) { - return NewWaitSnapshotState(a.baseInfo, a.blockCache).Block(peer, block) -} - -func initNGLightStateInFSM(state *StateData, fsm *stateless.StateMachine, info BaseInfo) { - ngLightSkipMessageList := proto.PeerMessageIDs{ - proto.ContentIDSignatures, - proto.ContentIDBlock, - proto.ContentIDTransaction, - proto.ContentIDInvMicroblock, - proto.ContentIDCheckpoint, - proto.ContentIDMicroblockRequest, - proto.ContentIDMicroblock, - proto.ContentIDPBBlock, - proto.ContentIDPBMicroBlock, - proto.ContentIDPBTransaction, - proto.ContentIDBlockIds, - } - fsm.Configure(NGLightStateName). - SubstateOf(NGStateName). - OnEntry(func(ctx context.Context, args ...interface{}) error { - info.skipMessageList.SetList(ngLightSkipMessageList) - return nil - }). - Ignore(BlockIDsEvent). - Ignore(StartMiningEvent). - Ignore(ChangeSyncPeerEvent). - Ignore(StopSyncEvent). - PermitDynamic(StopMiningEvent, - createPermitDynamicCallback(StopMiningEvent, state, func(args ...interface{}) (State, Async, error) { - a, ok := state.State.(*NGState) - if !ok { - return a, nil, a.Errorf(errors.Errorf( - "unexpected type '%T' expected '*NGState'", state.State)) - } - return a.StopMining() - })). - PermitDynamic(TransactionEvent, - createPermitDynamicCallback(TransactionEvent, state, func(args ...interface{}) (State, Async, error) { - a, ok := state.State.(*NGState) - if !ok { - return a, nil, a.Errorf(errors.Errorf( - "unexpected type '%T' expected '*NGState'", state.State)) - } - return a.Transaction(convertToInterface[peer.Peer](args[0]), - convertToInterface[proto.Transaction](args[1])) - })). - PermitDynamic(TaskEvent, - createPermitDynamicCallback(TaskEvent, state, func(args ...interface{}) (State, Async, error) { - a, ok := state.State.(*NGState) - if !ok { - return a, nil, a.Errorf(errors.Errorf( - "unexpected type '%T' expected '*NGState'", state.State)) - } - return a.Task(args[0].(tasks.AsyncTask)) - })). - PermitDynamic(ScoreEvent, - createPermitDynamicCallback(ScoreEvent, state, func(args ...interface{}) (State, Async, error) { - a, ok := state.State.(*NGState) - if !ok { - return a, nil, a.Errorf(errors.Errorf( - "unexpected type '%T' expected '*NGState'", state.State)) - } - return a.Score(convertToInterface[peer.Peer](args[0]), args[1].(*proto.Score)) - })). - PermitDynamic(BlockEvent, - createPermitDynamicCallback(BlockEvent, state, func(args ...interface{}) (State, Async, error) { - a, ok := state.State.(*NGState) - if !ok { - return a, nil, a.Errorf(errors.Errorf( - "unexpected type '%T' expected '*NGState'", state.State)) - } - return a.Block(convertToInterface[peer.Peer](args[0]), args[1].(*proto.Block)) - })). - PermitDynamic(MinedBlockEvent, - createPermitDynamicCallback(MinedBlockEvent, state, func(args ...interface{}) (State, Async, error) { - a, ok := state.State.(*NGState) - if !ok { - return a, nil, a.Errorf(errors.Errorf( - "unexpected type '%T' expected '*NGState'", state.State)) - } - return a.MinedBlock(args[0].(*proto.Block), args[1].(proto.MiningLimits), - args[2].(proto.KeyPair), args[3].([]byte)) - })). - PermitDynamic(MicroBlockEvent, - createPermitDynamicCallback(MicroBlockEvent, state, func(args ...interface{}) (State, Async, error) { - a, ok := state.State.(*NGState) - if !ok { - return a, nil, a.Errorf(errors.Errorf( - "unexpected type '%T' expected '*NGState'", state.State)) - } - return a.MicroBlock(convertToInterface[peer.Peer](args[0]), args[1].(*proto.MicroBlock)) - })). - PermitDynamic(MicroBlockInvEvent, - createPermitDynamicCallback(MicroBlockInvEvent, state, func(args ...interface{}) (State, Async, error) { - a, ok := state.State.(*NGState) - if !ok { - return a, nil, a.Errorf(errors.Errorf( - "unexpected type '%T' expected '*NGState'", state.State)) - } - return a.MicroBlockInv(convertToInterface[peer.Peer](args[0]), args[1].(*proto.MicroBlockInv)) - })). - PermitDynamic(HaltEvent, - createPermitDynamicCallback(HaltEvent, state, func(args ...interface{}) (State, Async, error) { - a, ok := state.State.(*NGState) - if !ok { - return a, nil, a.Errorf(errors.Errorf( - "unexpected type '%T' expected '*NGState'", state.State)) - } - return a.Halt() - })) -} diff --git a/pkg/node/fsm/ng_state.go b/pkg/node/fsm/ng_state.go index 1a3f32b2e..62b004831 100644 --- a/pkg/node/fsm/ng_state.go +++ b/pkg/node/fsm/ng_state.go @@ -2,6 +2,7 @@ package fsm import ( "context" + "time" "github.com/pkg/errors" "github.com/qmuntal/stateless" @@ -12,13 +13,16 @@ import ( "github.com/wavesplatform/gowaves/pkg/miner" "github.com/wavesplatform/gowaves/pkg/node/fsm/tasks" "github.com/wavesplatform/gowaves/pkg/p2p/peer" + "github.com/wavesplatform/gowaves/pkg/p2p/peer/extension" "github.com/wavesplatform/gowaves/pkg/proto" "github.com/wavesplatform/gowaves/pkg/state" ) type NGState struct { - baseInfo BaseInfo - blocksCache blockStatesCache + baseInfo BaseInfo + blocksCache blockStatesCache + blockWaitingForSnapshot *proto.Block + microBlockWaitingForSnapshot *proto.MicroBlock } func newNGState(baseInfo BaseInfo) State { @@ -60,6 +64,24 @@ func (a *NGState) Task(task tasks.AsyncTask) (State, Async, error) { "unexpected type %T, expected 'tasks.MineMicroTaskData'", task.Data)) } return a.mineMicro(t.Block, t.Limits, t.KeyPair, t.Vrf) + case tasks.SnapshotTimeout: + t, ok := task.Data.(tasks.SnapshotTimeoutTaskData) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type %T, expected 'tasks.SnapshotTimeoutTaskData'", task.Data)) + } + switch t.SnapshotTaskType { + case tasks.BlockSnapshot: + a.blockWaitingForSnapshot = nil + return a, nil, a.Errorf(errors.Errorf( + "failed to get snapshot for block '%s' - timeout", t.BlockID)) + case tasks.MicroBlockSnapshot: + a.microBlockWaitingForSnapshot = nil + return a, nil, a.Errorf(errors.Errorf( + "failed to get snapshot for micro block '%s' - timeout", t.BlockID)) + default: + return a, nil, a.Errorf(errors.New("undefined Snapshot Task type")) + } default: return a, nil, a.Errorf(errors.Errorf( "unexpected internal task '%d' with data '%+v' received by %s State", @@ -90,13 +112,37 @@ func (a *NGState) rollbackToStateFromCache(blockFromCache *proto.Block) error { return errors.Wrapf(err, "failed to rollback to parent block '%s' of cached block '%s'", previousBlockID.String(), blockFromCache.ID.String()) } - _, err = a.baseInfo.blocksApplier.Apply(a.baseInfo.storage, []*proto.Block{blockFromCache}) + _, err = a.baseInfo.blocksApplier.Apply(a.baseInfo.storage, []*proto.Block{blockFromCache}, nil) if err != nil { return errors.Wrapf(err, "failed to apply cached block %q", blockFromCache.ID.String()) } return nil } +func (a *NGState) rollbackToStateFromCacheInLightNode(parentID proto.BlockID) error { + blockFromCache, okB := a.blocksCache.Get(parentID) + snapshotFromCache, okS := a.blocksCache.GetSnapshot(parentID) + if okB && okS { + zap.S().Named(logging.FSMNamespace).Debugf("[%s] Re-applying block '%s' from cache", + a, blockFromCache.ID.String()) + previousBlockID := blockFromCache.Parent + err := a.baseInfo.storage.RollbackTo(previousBlockID) + if err != nil { + return errors.Wrapf(err, "failed to rollback to parent block '%s' of cached block '%s'", + previousBlockID.String(), blockFromCache.ID.String()) + } + _, err = a.baseInfo.blocksApplier.Apply( + a.baseInfo.storage, + []*proto.Block{blockFromCache}, + []*proto.BlockSnapshot{snapshotFromCache}, + ) + if err != nil { + return errors.Wrapf(err, "failed to apply cached block %q", blockFromCache.ID.String()) + } + } + return nil +} + func (a *NGState) Block(peer peer.Peer, block *proto.Block) (State, Async, error) { ok, err := a.baseInfo.blocksApplier.BlockExists(a.baseInfo.storage, block) if err != nil { @@ -114,32 +160,72 @@ func (a *NGState) Block(peer peer.Peer, block *proto.Block) (State, Async, error "[%s] Key-block '%s' has parent '%s' which is not the top block '%s'", a, block.ID.String(), block.Parent.String(), top.ID.String(), ) - var blockFromCache *proto.Block - if blockFromCache, ok = a.blocksCache.Get(block.Parent); ok { - zap.S().Named(logging.FSMNamespace).Debugf("[%s] Re-applying block '%s' from cache", - a, blockFromCache.ID.String()) - if err = a.rollbackToStateFromCache(blockFromCache); err != nil { + if a.baseInfo.enableLightMode { + if err = a.rollbackToStateFromCacheInLightNode(block.Parent); err != nil { return a, nil, a.Errorf(err) } + } else { + var blockFromCache *proto.Block + if blockFromCache, ok = a.blocksCache.Get(block.Parent); ok { + zap.S().Named(logging.FSMNamespace).Debugf("[%s] Re-applying block '%s' from cache", + a, blockFromCache.ID.String()) + if err = a.rollbackToStateFromCache(blockFromCache); err != nil { + return a, nil, a.Errorf(err) + } + } } } - _, err = a.baseInfo.blocksApplier.Apply(a.baseInfo.storage, []*proto.Block{block}) + if a.baseInfo.enableLightMode { + a.blockWaitingForSnapshot = block + pe := extension.NewPeerExtension(peer, a.baseInfo.scheme) + pe.AskBlockSnapshot(block.BlockID()) + return a, tasks.Tasks(tasks.NewSnapshotTimeoutTask(time.Minute, block.BlockID(), tasks.BlockSnapshot)), nil + } + a.blocksCache.Clear() + a.blocksCache.AddBlockState(block) + a.baseInfo.scheduler.Reschedule() + a.baseInfo.actions.SendScore(a.baseInfo.storage) + a.baseInfo.CleanUtx() + + return newNGState(a.baseInfo), nil, nil +} + +func (a *NGState) BlockSnapshot( + peer peer.Peer, + blockID proto.BlockID, + snapshot proto.BlockSnapshot, +) (State, Async, error) { + // Skip, we are not waiting snapshot + if a.blockWaitingForSnapshot == nil { + return a, nil, nil + } + if a.blockWaitingForSnapshot.BlockID() != blockID { + return a, nil, a.Errorf( + errors.Errorf("New snapshot doesn't match with block %s", a.blockWaitingForSnapshot.BlockID())) + } + + _, err := a.baseInfo.blocksApplier.Apply( + a.baseInfo.storage, + []*proto.Block{a.blockWaitingForSnapshot}, + []*proto.BlockSnapshot{&snapshot}, + ) if err != nil { - metrics.FSMKeyBlockDeclined("ng", block, err) + // metrics.FSMKeyBlockDeclined("ng", block, err) return a, nil, a.Errorf(errors.Wrapf(err, "peer '%s'", peer.ID())) } - metrics.FSMKeyBlockApplied("ng", block) + + metrics.FSMKeyBlockApplied("ng", a.blockWaitingForSnapshot) zap.S().Named(logging.FSMNamespace).Debugf("[%s] Handle received key block message: block '%s' applied to state", - a, block.BlockID()) + a, blockID) a.blocksCache.Clear() - a.blocksCache.AddBlockState(block) - + a.blocksCache.AddBlockState(a.blockWaitingForSnapshot) + a.blocksCache.AddSnapshot(blockID, snapshot) a.baseInfo.scheduler.Reschedule() a.baseInfo.actions.SendScore(a.baseInfo.storage) a.baseInfo.CleanUtx() - + a.blockWaitingForSnapshot = nil return newNGState(a.baseInfo), nil, nil } @@ -149,7 +235,7 @@ func (a *NGState) MinedBlock( metrics.FSMKeyBlockGenerated("ng", block) err := a.baseInfo.storage.Map(func(state state.NonThreadSafeState) error { var err error - _, err = a.baseInfo.blocksApplier.Apply(state, []*proto.Block{block}) + _, err = a.baseInfo.blocksApplier.Apply(state, []*proto.Block{block}, nil) return err }) if err != nil { @@ -174,19 +260,52 @@ func (a *NGState) MinedBlock( func (a *NGState) MicroBlock(p peer.Peer, micro *proto.MicroBlock) (State, Async, error) { metrics.FSMMicroBlockReceived("ng", micro, p.Handshake().NodeName) - block, err := a.checkAndAppendMicroblock(micro) // the TopBlock() is used here + if !a.baseInfo.enableLightMode { + block, err := a.checkAndAppendMicroBlock(micro, nil) // the TopBlock() is used here + if err != nil { + metrics.FSMMicroBlockDeclined("ng", micro, err) + return a, nil, a.Errorf(err) + } + zap.S().Named(logging.FSMNamespace).Debugf( + "[%s] Received microblock '%s' (referencing '%s') successfully applied to state", + a, block.BlockID(), micro.Reference, + ) + a.baseInfo.MicroBlockCache.Add(block.BlockID(), micro) + a.blocksCache.AddBlockState(block) + } + + a.microBlockWaitingForSnapshot = micro + tasks.Tasks(tasks.NewSnapshotTimeoutTask(time.Minute, micro.TotalBlockID, tasks.MicroBlockSnapshot)) + return a, nil, nil +} + +func (a *NGState) MicroBlockSnapshot( + _ peer.Peer, + blockID proto.BlockID, + snapshot proto.BlockSnapshot, +) (State, Async, error) { + if a.microBlockWaitingForSnapshot == nil { + return a, nil, nil + } + if a.microBlockWaitingForSnapshot.TotalBlockID != blockID { + return a, nil, a.Errorf(errors.Errorf( + "New snapshot doesn't match with microBlock %s", a.microBlockWaitingForSnapshot.TotalBlockID)) + } + // the TopBlock() is used here + block, err := a.checkAndAppendMicroBlock(a.microBlockWaitingForSnapshot, &snapshot) if err != nil { - metrics.FSMMicroBlockDeclined("ng", micro, err) + metrics.FSMMicroBlockDeclined("ng", a.microBlockWaitingForSnapshot, err) return a, nil, a.Errorf(err) } zap.S().Named(logging.FSMNamespace).Debugf( - "[%s] Received microblock '%s' (referencing '%s') successfully applied to state", - a, block.BlockID(), micro.Reference, + "[%s] Received snapshot for microblock '%s' successfully applied to state", a, block.BlockID(), ) - a.baseInfo.MicroBlockCache.Add(block.BlockID(), micro) + a.baseInfo.MicroBlockCache.Add(block.BlockID(), a.microBlockWaitingForSnapshot) + a.baseInfo.MicroBlockCache.AddSnapshot(block.BlockID(), &snapshot) a.blocksCache.AddBlockState(block) + a.blocksCache.AddSnapshot(block.BlockID(), snapshot) a.baseInfo.scheduler.Reschedule() - + a.microBlockWaitingForSnapshot = nil // Notify all connected peers about new microblock, send them microblock inv network message if inv, ok := a.baseInfo.MicroBlockInvCache.Get(block.BlockID()); ok { //TODO: We have to exclude from recipients peers that already have this microblock @@ -213,7 +332,7 @@ func (a *NGState) mineMicro( } metrics.FSMMicroBlockGenerated("ng", micro) err = a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { - _, er := a.baseInfo.blocksApplier.ApplyMicro(s, block) + _, er := a.baseInfo.blocksApplier.ApplyMicro(s, block, nil) return er }) if err != nil { @@ -267,8 +386,11 @@ func (a *NGState) broadcastMicroBlockInv(inv *proto.MicroBlockInv) error { return nil } -// checkAndAppendMicroblock checks that microblock is appendable and appends it. -func (a *NGState) checkAndAppendMicroblock(micro *proto.MicroBlock) (*proto.Block, error) { +// checkAndAppendMicroBlock checks that microblock is appendable and appends it. +func (a *NGState) checkAndAppendMicroBlock( + micro *proto.MicroBlock, + snapshot *proto.BlockSnapshot, +) (*proto.Block, error) { top := a.baseInfo.storage.TopBlock() // Get the last block if top.BlockID() != micro.Reference { // Microblock doesn't refer to last block err := errors.Errorf("microblock TBID '%s' refer to block ID '%s' but last block ID is '%s'", @@ -301,8 +423,23 @@ func (a *NGState) checkAndAppendMicroblock(micro *proto.MicroBlock) (*proto.Bloc if err != nil { return nil, errors.Wrap(err, "NGState microBlockByID: failed generate block id") } + snapshotsToApply := snapshot + if snapshot != nil { + h, errBToH := a.baseInfo.storage.BlockIDToHeight(top.BlockID()) + if errBToH != nil { + return nil, errBToH + } + topBlockSnapshots, errSAtH := a.baseInfo.storage.SnapshotsAtHeight(h) + if errSAtH != nil { + return nil, errSAtH + } + for _, sn := range snapshot.TxSnapshots { + topBlockSnapshots.AppendTxSnapshot(sn) + } + snapshotsToApply = &topBlockSnapshots + } err = a.baseInfo.storage.Map(func(state state.State) error { - _, er := a.baseInfo.blocksApplier.ApplyMicro(state, newBlock) + _, er := a.baseInfo.blocksApplier.ApplyMicro(state, newBlock, snapshotsToApply) return er }) if err != nil { @@ -315,7 +452,8 @@ func (a *NGState) checkAndAppendMicroblock(micro *proto.MicroBlock) (*proto.Bloc func (a *NGState) MicroBlockInv(p peer.Peer, inv *proto.MicroBlockInv) (State, Async, error) { metrics.MicroBlockInv(inv, p.Handshake().NodeName) - existed := a.baseInfo.invRequester.Request(p, inv.TotalBlockID.Bytes()) // TODO: add logs about microblock request + // TODO: add logs about microblock request + existed := a.baseInfo.invRequester.Request(p, inv.TotalBlockID.Bytes(), a.baseInfo.enableLightMode) if existed { zap.S().Named(logging.FSMNamespace).Debugf("[%s] Microblock inv received: block '%s' already in cache", a, inv.TotalBlockID) @@ -331,36 +469,43 @@ func (a *NGState) Halt() (State, Async, error) { return newHaltState(a.baseInfo) } -type blockWithSnapshot struct { - Block proto.Block - Snapshot proto.BlockSnapshot -} - type blockStatesCache struct { - blockStates map[proto.BlockID]blockWithSnapshot + blockStates map[proto.BlockID]proto.Block + snapshots map[proto.BlockID]proto.BlockSnapshot } func (c *blockStatesCache) AddBlockState(block *proto.Block) { - c.blockStates[block.ID] = blockWithSnapshot{Block: *block} + c.blockStates[block.ID] = *block zap.S().Named(logging.FSMNamespace).Debugf("[NG] Block '%s' added to cache, total blocks in cache: %d", block.ID.String(), len(c.blockStates)) } func (c *blockStatesCache) AddSnapshot(blockID proto.BlockID, snapshot proto.BlockSnapshot) { - c.blockStates[blockID].Snapshot = snapshot + c.snapshots[blockID] = snapshot + zap.S().Named(logging.FSMNamespace).Debugf("[NG] Snapshot '%s' added to cache, total snapshots in cache: %d", + blockID.String(), len(c.snapshots)) } func (c *blockStatesCache) Clear() { - c.blockStates = map[proto.BlockID]blockWithSnapshot{} + c.blockStates = map[proto.BlockID]proto.Block{} + c.snapshots = map[proto.BlockID]proto.BlockSnapshot{} zap.S().Named(logging.FSMNamespace).Debug("[NG] Block cache is empty") } func (c *blockStatesCache) Get(blockID proto.BlockID) (*proto.Block, bool) { - bs, ok := c.blockStates[blockID] + block, ok := c.blockStates[blockID] + if !ok { + return nil, false + } + return &block, true +} + +func (c *blockStatesCache) GetSnapshot(blockID proto.BlockID) (*proto.BlockSnapshot, bool) { + snapshot, ok := c.snapshots[blockID] if !ok { return nil, false } - return &bs.Block, true + return &snapshot, true } func initNGStateInFSM(state *StateData, fsm *stateless.StateMachine, info BaseInfo) { @@ -456,5 +601,31 @@ func initNGStateInFSM(state *StateData, fsm *stateless.StateMachine, info BaseIn "unexpected type '%T' expected '*NGState'", state.State)) } return a.Halt() + })). + PermitDynamic(BlockSnapshotEvent, + createPermitDynamicCallback(BlockSnapshotEvent, state, func(args ...interface{}) (State, Async, error) { + a, ok := state.State.(*NGState) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type '%T' expected '*NGState'", state.State)) + } + return a.BlockSnapshot( + convertToInterface[peer.Peer](args[0]), + args[1].(proto.BlockID), + args[2].(proto.BlockSnapshot), + ) + })). + PermitDynamic(MicroBlockSnapshotEvent, + createPermitDynamicCallback(MicroBlockSnapshotEvent, state, func(args ...interface{}) (State, Async, error) { + a, ok := state.State.(*NGState) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type '%T' expected '*NGState'", state.State)) + } + return a.MicroBlockSnapshot( + convertToInterface[peer.Peer](args[0]), + args[1].(proto.BlockID), + args[2].(proto.BlockSnapshot), + ) })) } diff --git a/pkg/node/fsm/persist_state.go b/pkg/node/fsm/persist_state.go index f3bb471bf..1bec34962 100644 --- a/pkg/node/fsm/persist_state.go +++ b/pkg/node/fsm/persist_state.go @@ -77,6 +77,10 @@ func initPersistStateInFSM(state *StateData, fsm *stateless.StateMachine, info B proto.ContentIDPBMicroBlock, proto.ContentIDPBTransaction, proto.ContentIDGetBlockIds, + proto.ContentIDBlockSnapshot, + proto.ContentIDMicroBlockSnapshot, + proto.ContentIDGetBlockSnapshot, + proto.ContentIDMicroBlockSnapshotRequest, } fsm.Configure(PersistStateName). Ignore(BlockEvent). @@ -88,6 +92,8 @@ func initPersistStateInFSM(state *StateData, fsm *stateless.StateMachine, info B Ignore(StartMiningEvent). Ignore(ChangeSyncPeerEvent). Ignore(StopSyncEvent). + Ignore(BlockSnapshotEvent). + Ignore(MicroBlockSnapshotEvent). OnEntry(func(ctx context.Context, args ...interface{}) error { info.skipMessageList.SetList(persistSkipMessageList) return nil diff --git a/pkg/node/fsm/sync_internal/internal.go b/pkg/node/fsm/sync_internal/internal.go index 80a713ca5..4874572a4 100644 --- a/pkg/node/fsm/sync_internal/internal.go +++ b/pkg/node/fsm/sync_internal/internal.go @@ -10,6 +10,7 @@ import ( ) type Blocks []*proto.Block +type Snapshots []*proto.BlockSnapshot type Eof = bool type BlockApplied bool @@ -19,24 +20,36 @@ var UnexpectedBlockErr = proto.NewInfoMsg(errors.New("unexpected block")) type PeerExtension interface { AskBlocksIDs(id []proto.BlockID) AskBlock(id proto.BlockID) + AskBlockSnapshot(id proto.BlockID) } type Internal struct { respondedSignatures *signatures.BlockIDs orderedBlocks *ordered_blocks.OrderedBlocks waitingForSignatures bool + isLightNode bool } -func InternalFromLastSignatures(p extension.PeerExtension, signatures *signatures.ReverseOrdering) Internal { +func InternalFromLastSignatures( + p extension.PeerExtension, + signatures *signatures.ReverseOrdering, + isLightNode bool, +) Internal { p.AskBlocksIDs(signatures.BlockIDS()) - return NewInternal(ordered_blocks.NewOrderedBlocks(), signatures, true) + return NewInternal(ordered_blocks.NewOrderedBlocks(), signatures, true, isLightNode) } -func NewInternal(orderedBlocks *ordered_blocks.OrderedBlocks, respondedSignatures *signatures.ReverseOrdering, waitingForSignatures bool) Internal { +func NewInternal( + orderedBlocks *ordered_blocks.OrderedBlocks, + respondedSignatures *signatures.ReverseOrdering, + waitingForSignatures bool, + isLightNode bool, +) Internal { return Internal{ respondedSignatures: respondedSignatures, orderedBlocks: orderedBlocks, waitingForSignatures: waitingForSignatures, + isLightNode: isLightNode, } } @@ -52,10 +65,13 @@ func (a Internal) BlockIDs(p PeerExtension, ids []proto.BlockID) (Internal, erro newIDs = append(newIDs, id) if a.orderedBlocks.Add(id) { p.AskBlock(id) + if a.isLightNode { + p.AskBlockSnapshot(id) + } } } respondedSignatures := signatures.NewSignatures(newIDs...).Revert() - return NewInternal(a.orderedBlocks, respondedSignatures, false), nil + return NewInternal(a.orderedBlocks, respondedSignatures, false, a.isLightNode), nil } func (a Internal) WaitingForSignatures() bool { @@ -70,26 +86,36 @@ func (a Internal) Block(block *proto.Block) (Internal, error) { return a, nil } +func (a Internal) Snapshot(blockID proto.BlockID, snapshot *proto.BlockSnapshot) (Internal, error) { + if !a.orderedBlocks.Contains(blockID) { + return a, UnexpectedBlockErr + } + a.orderedBlocks.SetSnapshot(blockID, snapshot) + return a, nil +} + type peerExtension interface { AskBlocksIDs(id []proto.BlockID) } -func (a Internal) Blocks(p peerExtension) (Internal, Blocks, Eof) { +func (a Internal) Blocks(p peerExtension) (Internal, Blocks, Snapshots, Eof) { if a.waitingForSignatures { - return NewInternal(a.orderedBlocks, a.respondedSignatures, a.waitingForSignatures), nil, false + return NewInternal(a.orderedBlocks, a.respondedSignatures, a.waitingForSignatures, a.isLightNode), nil, nil, false } - if a.orderedBlocks.RequestedCount() > a.orderedBlocks.ReceivedCount() { - return NewInternal(a.orderedBlocks, a.respondedSignatures, a.waitingForSignatures), nil, false + if a.orderedBlocks.RequestedCount() > a.orderedBlocks.ReceivedCount(a.isLightNode) { + return NewInternal(a.orderedBlocks, a.respondedSignatures, a.waitingForSignatures, a.isLightNode), nil, nil, false } if a.orderedBlocks.RequestedCount() < 100 { - return NewInternal(a.orderedBlocks, a.respondedSignatures, false), a.orderedBlocks.PopAll(), true + bs, ss := a.orderedBlocks.PopAll() + return NewInternal(a.orderedBlocks, a.respondedSignatures, false, a.isLightNode), bs, ss, true } p.AskBlocksIDs(a.respondedSignatures.BlockIDS()) - return NewInternal(a.orderedBlocks, a.respondedSignatures, true), a.orderedBlocks.PopAll(), false + bs, ss := a.orderedBlocks.PopAll() + return NewInternal(a.orderedBlocks, a.respondedSignatures, true, a.isLightNode), bs, ss, false } func (a Internal) AvailableCount() int { - return a.orderedBlocks.ReceivedCount() + return a.orderedBlocks.ReceivedCount(a.isLightNode) } func (a Internal) RequestedCount() int { diff --git a/pkg/node/fsm/sync_internal/internal_test.go b/pkg/node/fsm/sync_internal/internal_test.go index 91c9845d1..a330f27eb 100644 --- a/pkg/node/fsm/sync_internal/internal_test.go +++ b/pkg/node/fsm/sync_internal/internal_test.go @@ -15,10 +15,14 @@ import ( type noopWrapper struct { } -func (noopWrapper) AskBlocksIDs(id []proto.BlockID) { +func (noopWrapper) AskBlocksIDs(_ []proto.BlockID) { } -func (noopWrapper) AskBlock(id proto.BlockID) { +func (noopWrapper) AskBlock(_ proto.BlockID) { +} + +func (noopWrapper) AskBlockSnapshot(_ proto.BlockID) { + } var sig1 = crypto.MustSignatureFromBase58("5syuWANDSgk8KyPxq2yQs2CYV23QfnrBoZMSv2LaciycxDYfBw6cLA2SqVnonnh1nFiFumzTgy2cPETnE7ZaZg5P") @@ -37,14 +41,14 @@ func TestSigFSM_Signatures(t *testing.T) { sigs := signatures.NewSignatures() t.Run("error on receive unexpected signatures", func(t *testing.T) { - fsm := NewInternal(or, sigs, false) + fsm := NewInternal(or, sigs, false, false) rs2, err := fsm.BlockIDs(nil, blocksFromSigs(sig1, sig2)) require.Equal(t, NoSignaturesExpectedErr, err) require.NotNil(t, rs2) }) t.Run("successful receive signatures", func(t *testing.T) { - fsm := NewInternal(or, sigs, true) + fsm := NewInternal(or, sigs, true, false) rs2, err := fsm.BlockIDs(noopWrapper{}, blocksFromSigs(sig1, sig2)) require.NoError(t, err) require.NotNil(t, rs2) @@ -63,7 +67,7 @@ func block(sig crypto.Signature) *proto.Block { func TestSigFSM_Block(t *testing.T) { or := ordered_blocks.NewOrderedBlocks() sigs := signatures.NewSignatures() - fsm := NewInternal(or, sigs, true) + fsm := NewInternal(or, sigs, true, false) fsm, _ = fsm.BlockIDs(noopWrapper{}, blocksFromSigs(sig1, sig2)) fsm, _ = fsm.Block(block(sig1)) @@ -71,13 +75,13 @@ func TestSigFSM_Block(t *testing.T) { require.Equal(t, 2, fsm.AvailableCount()) // no panic, cause `nearEnd` is True - _, blocks, _ := fsm.Blocks(nil) + _, blocks, _, _ := fsm.Blocks(nil) require.Equal(t, 2, len(blocks)) } func TestSigFSM_BlockGetSignatures(t *testing.T) { or := ordered_blocks.NewOrderedBlocks() sigs := signatures.NewSignatures() - _, bs, _ := NewInternal(or, sigs, false).Blocks(nil) + _, bs, _, _ := NewInternal(or, sigs, false, false).Blocks(nil) require.Nil(t, bs) } diff --git a/pkg/node/fsm/sync_state.go b/pkg/node/fsm/sync_state.go index 1fc480843..dfcc17fe2 100644 --- a/pkg/node/fsm/sync_state.go +++ b/pkg/node/fsm/sync_state.go @@ -44,6 +44,8 @@ func (noopWrapper) AskBlocksIDs([]proto.BlockID) {} func (noopWrapper) AskBlock(proto.BlockID) {} +func (noopWrapper) AskBlockSnapshot(proto.BlockID) {} + type SyncState struct { baseInfo BaseInfo conf conf @@ -71,12 +73,22 @@ func (a *SyncState) Transaction(p peer.Peer, t proto.Transaction) (State, Async, } func (a *SyncState) StopSync() (State, Async, error) { - _, blocks, _ := a.internal.Blocks(noopWrapper{}) + _, blocks, snapshots, _ := a.internal.Blocks(noopWrapper{}) if len(blocks) > 0 { - err := a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { - _, err := a.baseInfo.blocksApplier.Apply(s, blocks) - return err - }) + var err error + if a.baseInfo.enableLightMode { + err = a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { + var errApply error + _, errApply = a.baseInfo.blocksApplier.Apply(s, blocks, snapshots) + return errApply + }) + } else { + err = a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { + var errApply error + _, errApply = a.baseInfo.blocksApplier.Apply(s, blocks, nil) + return errApply + }) + } return newIdleState(a.baseInfo), nil, a.Errorf(err) } return newIdleState(a.baseInfo), nil, nil @@ -163,11 +175,30 @@ func (a *SyncState) Block(p peer.Peer, block *proto.Block) (State, Async, error) } metrics.FSMKeyBlockReceived("sync", block, p.Handshake().NodeName) zap.S().Named(logging.FSMNamespace).Debugf("[Sync][%s] Received block %s", p.ID(), block.ID.String()) + internal, err := a.internal.Block(block) if err != nil { return newSyncState(a.baseInfo, a.conf, internal), nil, a.Errorf(err) } - return a.applyBlocks(a.baseInfo, a.conf.Now(a.baseInfo.tm), internal) + if !a.baseInfo.enableLightMode { + return a.applyBlocksWithSnapshots(a.baseInfo, a.conf.Now(a.baseInfo.tm), internal) + } + return a, nil, nil +} + +func (a *SyncState) BlockSnapshot( + p peer.Peer, + blockID proto.BlockID, + snapshot proto.BlockSnapshot, +) (State, Async, error) { + if !p.Equal(a.conf.peerSyncWith) { + return a, nil, nil + } + internal, err := a.internal.Snapshot(blockID, &snapshot) + if err != nil { + return newSyncState(a.baseInfo, a.conf, internal), nil, a.Errorf(err) + } + return a.applyBlocksWithSnapshots(a.baseInfo, a.conf.Now(a.baseInfo.tm), internal) } func (a *SyncState) MinedBlock( @@ -175,7 +206,7 @@ func (a *SyncState) MinedBlock( ) (State, Async, error) { metrics.FSMKeyBlockGenerated("sync", block) zap.S().Named(logging.FSMNamespace).Infof("[Sync] New block '%s' mined", block.ID.String()) - _, err := a.baseInfo.blocksApplier.Apply(a.baseInfo.storage, []*proto.Block{block}) + _, err := a.baseInfo.blocksApplier.Apply(a.baseInfo.storage, []*proto.Block{block}, nil) if err != nil { zap.S().Warnf("[Sync] Failed to apply mined block: %v", err) return a, nil, nil // We've failed to apply mined block, it's not an error @@ -213,19 +244,29 @@ func (a *SyncState) changePeerIfRequired() (peer.Peer, bool) { } // TODO suspend peer on state error -func (a *SyncState) applyBlocks( +func (a *SyncState) applyBlocksWithSnapshots( baseInfo BaseInfo, conf conf, internal sync_internal.Internal, ) (State, Async, error) { - internal, blocks, eof := internal.Blocks(extension.NewPeerExtension(a.conf.peerSyncWith, a.baseInfo.scheme)) + internal, blocks, snapshots, eof := internal.Blocks(extension.NewPeerExtension(a.conf.peerSyncWith, a.baseInfo.scheme)) if len(blocks) == 0 { zap.S().Named(logging.FSMNamespace).Debug("[Sync] No blocks to apply") return newSyncState(baseInfo, conf, internal), nil, nil } - err := a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { - var err error - _, err = a.baseInfo.blocksApplier.Apply(s, blocks) - return err - }) + var err error + if baseInfo.enableLightMode { + err = a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { + var errApply error + _, errApply = a.baseInfo.blocksApplier.Apply(s, blocks, snapshots) + return errApply + }) + } else { + err = a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { + var errApply error + _, errApply = a.baseInfo.blocksApplier.Apply(s, blocks, nil) + return errApply + }) + } + if err != nil { if errs.IsValidationError(err) || errs.IsValidationError(errors.Cause(err)) { zap.S().Named(logging.FSMNamespace).Debugf( @@ -272,9 +313,15 @@ func initSyncStateInFSM(state *StateData, fsm *stateless.StateMachine, info Base proto.ContentIDMicroblock, proto.ContentIDPBMicroBlock, proto.ContentIDPBTransaction, + proto.ContentIDMicroBlockSnapshot, + proto.ContentIDMicroBlockSnapshotRequest, } fsm.Configure(SyncStateName). - Ignore(MicroBlockEvent).Ignore(MicroBlockInvEvent).Ignore(StartMiningEvent).Ignore(StopMiningEvent). + Ignore(MicroBlockEvent). + Ignore(MicroBlockInvEvent). + Ignore(StartMiningEvent). + Ignore(StopMiningEvent). + Ignore(MicroBlockSnapshotEvent). OnEntry(func(ctx context.Context, args ...interface{}) error { info.skipMessageList.SetList(syncSkipMessageList) return nil @@ -361,5 +408,18 @@ func initSyncStateInFSM(state *StateData, fsm *stateless.StateMachine, info Base "unexpected type '%T' expected '*SyncState'", state.State)) } return a.Halt() + })). + PermitDynamic(BlockSnapshotEvent, + createPermitDynamicCallback(BlockSnapshotEvent, state, func(args ...interface{}) (State, Async, error) { + a, ok := state.State.(*SyncState) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type '%T' expected '*NGState'", state.State)) + } + return a.BlockSnapshot( + convertToInterface[peer.Peer](args[0]), + args[1].(proto.BlockID), + args[2].(proto.BlockSnapshot), + ) })) } diff --git a/pkg/node/fsm/tasks/tasks.go b/pkg/node/fsm/tasks/tasks.go index 1a08caa72..2397ea934 100644 --- a/pkg/node/fsm/tasks/tasks.go +++ b/pkg/node/fsm/tasks/tasks.go @@ -15,6 +15,7 @@ const ( AskPeers MineMicro PersistComplete + SnapshotTimeout ) // SendAsyncTask sends task into channel with overflow check. @@ -173,3 +174,53 @@ func NewFuncTask(f func(ctx context.Context, output chan AsyncTask) error, taskT _type: taskType, } } + +type SnapshotTimeoutTaskType int + +const ( + BlockSnapshot SnapshotTimeoutTaskType = iota + MicroBlockSnapshot +) + +type SnapshotTimeoutTaskData struct { + BlockID proto.BlockID + SnapshotTaskType SnapshotTimeoutTaskType +} + +func (SnapshotTimeoutTaskData) taskDataMarker() {} + +type SnapshotTimeoutTask struct { + timeout time.Duration + SnapshotTimeoutTaskData SnapshotTimeoutTaskData +} + +func NewSnapshotTimeoutTask( + timeout time.Duration, + blockID proto.BlockID, + taskType SnapshotTimeoutTaskType, +) SnapshotTimeoutTask { + return SnapshotTimeoutTask{ + timeout: timeout, + SnapshotTimeoutTaskData: SnapshotTimeoutTaskData{ + BlockID: blockID, + SnapshotTaskType: taskType, + }, + } +} + +func (SnapshotTimeoutTask) Type() int { + return SnapshotTimeout +} + +func (a SnapshotTimeoutTask) Run(ctx context.Context, output chan AsyncTask) error { + select { + case <-ctx.Done(): + return ctx.Err() + case <-time.After(a.timeout): + SendAsyncTask(output, AsyncTask{ + TaskType: a.Type(), + Data: a.SnapshotTimeoutTaskData, + }) + } + return nil +} diff --git a/pkg/node/fsm/wait_snapshot_state.go b/pkg/node/fsm/wait_snapshot_state.go deleted file mode 100644 index d3410e8c5..000000000 --- a/pkg/node/fsm/wait_snapshot_state.go +++ /dev/null @@ -1,83 +0,0 @@ -package fsm - -import ( - "github.com/pkg/errors" - "github.com/wavesplatform/gowaves/pkg/logging" - "github.com/wavesplatform/gowaves/pkg/metrics" - "github.com/wavesplatform/gowaves/pkg/p2p/peer" - "github.com/wavesplatform/gowaves/pkg/proto" - "go.uber.org/zap" -) - -type WaitSnapshotState struct { - baseInfo BaseInfo - blockCache *blockStatesCache -} - -func NewWaitSnapshotState(baseInfo BaseInfo, blockCache *blockStatesCache) *WaitSnapshotState { - baseInfo.syncPeer.Clear() - return &WaitSnapshotState{ - baseInfo: baseInfo, - blockCache: blockCache, - } -} - -func (a *WaitSnapshotState) Errorf(err error) error { - return fsmErrorf(a, err) -} - -func (a *WaitSnapshotState) String() string { - return NGLightStateName -} - -func (a *WaitSnapshotState) Block(peer peer.Peer, block *proto.Block) (State, Async, error) { - ok, err := a.baseInfo.snapshotApplier.BlockSnapshotExists(a.baseInfo.storage, block.BlockID()) - if err != nil { - return a, nil, a.Errorf(errors.Wrapf(err, "peer '%s'", peer.ID())) - } - if ok { - return a, nil, a.Errorf(proto.NewInfoMsg(errors.Errorf("Block '%s' already exists", block.BlockID().String()))) - } - //metrics.FSMKeyBlockReceived("ng", block, peer.Handshake().NodeName) - - top := a.baseInfo.storage.TopBlock() - if top.BlockID() != block.Parent { // does block refer to last block - zap.S().Named(logging.FSMNamespace).Debugf( - "[%s] Key-block '%s' has parent '%s' which is not the top block '%s'", - a, block.ID.String(), block.Parent.String(), top.ID.String(), - ) - var blockFromCache *proto.Block - if blockFromCache, ok = a.blockCache.Get(block.Parent); ok { - zap.S().Named(logging.FSMNamespace).Debugf("[%s] Re-applying block '%s' from cache", - a, blockFromCache.ID.String()) - if err = a.rollbackToStateFromCache(blockFromCache); err != nil { - return a, nil, a.Errorf(err) - } - } - } - a.blockCache.Clear() - a.blockCache.AddBlockState(block) -} - -func (a *WaitSnapshotState) BlockSnapshot(peer peer.Peer, blockID proto.BlockID, snapshots proto.BlockSnapshot) (State, Async, error) { - // check if this snapshot for our block - if _, ok := a.blockCache.Get(blockID); !ok { - return newNGLightState(a.baseInfo), nil, a.Errorf(errors.Errorf("Snapshot for the block '%s' doestn match", blockID)) - } - - _, err := a.baseInfo.snapshotApplier.Apply(a.baseInfo.storage, []proto.BlockSnapshot{snapshots}, []proto.BlockID{blockID}) - if err != nil { - //metrics.FSMKeyBlockDeclined("ng", block, err) - return a, nil, a.Errorf(errors.Wrapf(err, "peer '%s'", peer.ID())) - } - - metrics.FSMKeyBlockApplied("ng", block) - zap.S().Named(logging.FSMNamespace).Debugf("[%s] Handle received key block message: block '%s' applied to state", - a, block.BlockID()) - - a.baseInfo.scheduler.Reschedule() - a.baseInfo.actions.SendScore(a.baseInfo.storage) - a.baseInfo.CleanUtx() - - return newNGLightState(a.baseInfo), nil, nil -} diff --git a/pkg/node/metrics.go b/pkg/node/metrics.go index 5777c5ade..58587c4d4 100644 --- a/pkg/node/metrics.go +++ b/pkg/node/metrics.go @@ -41,30 +41,6 @@ var metricGetBlockMessage = prometheus.NewCounter( }, ) -var metricGetSnapshotMessage = prometheus.NewCounter( - prometheus.CounterOpts{ - Namespace: "messages", - Name: "get_snapshot", - Help: "Counter of GetSnapshot message.", - }, -) - -var metricMicroSnapshotRequestMessage = prometheus.NewCounter( - prometheus.CounterOpts{ - Namespace: "messages", - Name: "micro_snapshot_request", - Help: "Counter of MicroSnapshotRequest message.", - }, -) - -var metricSnapshotMessage = prometheus.NewCounter( - prometheus.CounterOpts{ - Namespace: "messages", - Name: "snapshot", - Help: "Counter of Snapshot message.", - }, -) - func init() { prometheus.MustRegister(metricInternalChannelSize) prometheus.MustRegister(metricPeersMessage) diff --git a/pkg/node/snapshot_applier/snapshot_applier.go b/pkg/node/snapshot_applier/snapshot_applier.go deleted file mode 100644 index 0cb65a43d..000000000 --- a/pkg/node/snapshot_applier/snapshot_applier.go +++ /dev/null @@ -1,25 +0,0 @@ -package snapshot_applier - -import ( - "github.com/wavesplatform/gowaves/pkg/proto" - "github.com/wavesplatform/gowaves/pkg/state" -) - -type SnapshotApplier struct { -} - -func NewSnapshotApplier() *SnapshotApplier { - return &SnapshotApplier{} -} - -func (a *SnapshotApplier) BlockSnapshotExists(state state.State, blockID proto.BlockID) (bool, error) { - return true, nil -} - -func (a *SnapshotApplier) Apply(state state.State, snapshots []proto.BlockSnapshot, block []proto.BlockID) (proto.Height, error) { - return 0, nil -} - -func (a *SnapshotApplier) ApplyMicro(state state.State, snapshots []proto.BlockSnapshot, block []proto.BlockID) (proto.Height, error) { - return 0, nil -} diff --git a/pkg/p2p/peer/extension/extension.go b/pkg/p2p/peer/extension/extension.go index 5eec3ec7b..7e3d1055a 100644 --- a/pkg/p2p/peer/extension/extension.go +++ b/pkg/p2p/peer/extension/extension.go @@ -14,6 +14,7 @@ var peerVersionWithProtobuf = proto.NewVersion(1, 2, 0) type PeerExtension interface { AskBlocksIDs(id []proto.BlockID) AskBlock(id proto.BlockID) + AskBlockSnapshot(id proto.BlockID) SendMicroBlock(micro *proto.MicroBlock) error SendTransaction(t proto.Transaction) error } @@ -65,6 +66,13 @@ func (a PeerWrapperImpl) AskBlock(id proto.BlockID) { a.p.SendMessage(&proto.GetBlockMessage{BlockID: id}) } +func (a PeerWrapperImpl) AskBlockSnapshot(id proto.BlockID) { + zap.S().Named(logging.NetworkNamespace).Debugf( + "[%s] Requesting block snapshot for block %s", a.p.ID().String(), id.ShortString(), + ) + a.p.SendMessage(&proto.GetBlockSnapshotMessage{BlockID: id}) +} + func (a PeerWrapperImpl) SendMicroBlock(micro *proto.MicroBlock) error { if a.p.Handshake().Version.Cmp(peerVersionWithProtobuf) < 0 { bts, err := micro.MarshalBinary(a.scheme) diff --git a/pkg/proto/block_snapshot.go b/pkg/proto/block_snapshot.go index bb457eb08..5484fa3fb 100644 --- a/pkg/proto/block_snapshot.go +++ b/pkg/proto/block_snapshot.go @@ -66,3 +66,17 @@ func (bs *BlockSnapshot) UnmarshalBinary(data []byte, scheme Scheme) error { bs.TxSnapshots = txSnapshots return nil } + +func (bs BlockSnapshot) ToProtobuf() ([]*g.TransactionStateSnapshot, error) { + res := make([]*g.TransactionStateSnapshot, 0, len(bs.TxSnapshots)) + for _, ts := range bs.TxSnapshots { + var tsProto g.TransactionStateSnapshot + for _, atomicSnapshot := range ts { + if err := atomicSnapshot.AppendToProtobuf(&tsProto); err != nil { + return nil, errors.Wrap(err, "failed to marshall TransactionSnapshot to proto") + } + } + res = append(res, &tsProto) + } + return res, nil +} diff --git a/pkg/proto/proto.go b/pkg/proto/proto.go index 4fb72abc9..e495b4019 100644 --- a/pkg/proto/proto.go +++ b/pkg/proto/proto.go @@ -12,6 +12,7 @@ import ( "github.com/pkg/errors" "github.com/valyala/bytebufferpool" + "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/util/collect_writes" ) @@ -56,6 +57,7 @@ const ( ContentIDMicroBlockSnapshot PeerMessageID = 37 ) +// ProtocolVersion TODO: change to 1.5.0 var ProtocolVersion = NewVersion(1, 4, 0) type Message interface { @@ -1819,6 +1821,8 @@ func UnmarshalMessage(b []byte) (Message, error) { m = &MicroBlockSnapshotRequestMessage{} case ContentIDBlockSnapshot: m = &BlockSnapshotMessage{} + case ContentIDMicroBlockSnapshot: + m = &MicroBlockSnapshotMessage{} default: return nil, errors.Errorf( "received unknown content id byte %d 0x%x", b[HeaderContentIDPosition], b[HeaderContentIDPosition]) @@ -2093,7 +2097,7 @@ func (m *GetBlockSnapshotMessage) MarshalBinary() ([]byte, error) { body := m.BlockID.Bytes() var h Header - h.Length = maxHeaderLength + uint32(len(body)) - 4 + h.Length = maxHeaderLength + uint32(len(body)) - headerChecksumLen h.Magic = headerMagic h.ContentID = ContentIDGetBlockSnapshot h.PayloadLength = uint32(len(body)) @@ -2101,7 +2105,7 @@ func (m *GetBlockSnapshotMessage) MarshalBinary() ([]byte, error) { if err != nil { return nil, err } - copy(h.PayloadChecksum[:], dig[:4]) + copy(h.PayloadChecksum[:], dig[:headerChecksumLen]) hdr, err := h.MarshalBinary() if err != nil { @@ -2135,7 +2139,7 @@ func (m *BlockSnapshotMessage) WriteTo(w io.Writer) (int64, error) { } func (m *BlockSnapshotMessage) UnmarshalBinary(data []byte) error { - if len(data) < 17 { + if len(data) < maxHeaderLength { return errors.New("BlockSnapshotMessage UnmarshalBinary: invalid data size") } var h Header @@ -2149,15 +2153,16 @@ func (m *BlockSnapshotMessage) UnmarshalBinary(data []byte) error { if h.ContentID != ContentIDBlockSnapshot { return fmt.Errorf("wrong ContentID in Header: %x", h.ContentID) } - m.Bytes = data[17:] + m.Bytes = make([]byte, h.PayloadLength) + copy(m.Bytes, data[maxHeaderLength:maxHeaderLength+h.PayloadLength]) return nil } -func (m *BlockSnapshotMessage) MarshalBinary() (data []byte, err error) { +func (m *BlockSnapshotMessage) MarshalBinary() ([]byte, error) { body := m.Bytes var h Header - h.Length = maxHeaderLength + uint32(len(body)) - 4 + h.Length = maxHeaderLength + uint32(len(body)) - headerChecksumLen h.Magic = headerMagic h.ContentID = ContentIDBlockSnapshot h.PayloadLength = uint32(len(body)) @@ -2165,7 +2170,7 @@ func (m *BlockSnapshotMessage) MarshalBinary() (data []byte, err error) { if err != nil { return nil, err } - copy(h.PayloadChecksum[:], dig[:4]) + copy(h.PayloadChecksum[:], dig[:headerChecksumLen]) hdr, err := h.MarshalBinary() if err != nil { @@ -2176,28 +2181,72 @@ func (m *BlockSnapshotMessage) MarshalBinary() (data []byte, err error) { } type MicroBlockSnapshotMessage struct { - BlockID BlockID - Snapshots BlockSnapshot + Bytes []byte } -func (m *MicroBlockSnapshotMessage) ReadFrom(_ io.Reader) (n int64, err error) { - panic("implement me") +func (m *MicroBlockSnapshotMessage) ReadFrom(r io.Reader) (int64, error) { + packet, nn, err := readPacket(r) + if err != nil { + return nn, err + } + + return nn, m.UnmarshalBinary(packet) } -func (m *MicroBlockSnapshotMessage) WriteTo(_ io.Writer) (n int64, err error) { - panic("implement me") +func (m *MicroBlockSnapshotMessage) WriteTo(w io.Writer) (int64, error) { + buf, err := m.MarshalBinary() + if err != nil { + return 0, err + } + nn, err := w.Write(buf) + n := int64(nn) + return n, err } -func (m *MicroBlockSnapshotMessage) UnmarshalBinary(_ []byte) error { - panic("implement me") +func (m *MicroBlockSnapshotMessage) UnmarshalBinary(data []byte) error { + if len(data) < maxHeaderLength { + return errors.New("MicroBlockSnapshotMessage UnmarshalBinary: invalid data size") + } + var h Header + + if err := h.UnmarshalBinary(data); err != nil { + return err + } + if h.Magic != headerMagic { + return fmt.Errorf("wrong magic in Header: %x", h.Magic) + } + if h.ContentID != ContentIDMicroBlockSnapshot { + return fmt.Errorf("wrong ContentID in Header: %x", h.ContentID) + } + m.Bytes = make([]byte, h.PayloadLength) + copy(m.Bytes, data[maxHeaderLength:maxHeaderLength+h.PayloadLength]) + return nil } -func (m *MicroBlockSnapshotMessage) MarshalBinary() (data []byte, err error) { - panic("ads") +func (m *MicroBlockSnapshotMessage) MarshalBinary() ([]byte, error) { + body := m.Bytes + + var h Header + h.Length = maxHeaderLength + uint32(len(body)) - headerChecksumLen + h.Magic = headerMagic + h.ContentID = ContentIDMicroBlockSnapshot + h.PayloadLength = uint32(len(body)) + dig, err := crypto.FastHash(body) + if err != nil { + return nil, err + } + copy(h.PayloadChecksum[:], dig[:headerChecksumLen]) + + hdr, err := h.MarshalBinary() + if err != nil { + return nil, err + } + body = append(hdr, body...) + return body, nil } type MicroBlockSnapshotRequestMessage struct { - BlockID BlockID + BlockIDBytes []byte } func (m *MicroBlockSnapshotRequestMessage) ReadFrom(r io.Reader) (int64, error) { @@ -2220,21 +2269,21 @@ func (m *MicroBlockSnapshotRequestMessage) WriteTo(w io.Writer) (int64, error) { } func (m *MicroBlockSnapshotRequestMessage) UnmarshalBinary(data []byte) error { - return parsePacket(data, ContentIDMicroBlockSnapshotRequest, "MicroBlockSnapshotRequestMessage", func(payload []byte) error { - blockID, err := NewBlockIDFromBytes(payload) - if err != nil { - return err - } - m.BlockID = blockID - return nil - }) + return parsePacket( + data, + ContentIDMicroBlockSnapshotRequest, + "MicroBlockSnapshotRequestMessage", + func(payload []byte) error { + m.BlockIDBytes = payload + return nil + }) } func (m *MicroBlockSnapshotRequestMessage) MarshalBinary() ([]byte, error) { - body := m.BlockID.Bytes() + body := m.BlockIDBytes var h Header - h.Length = maxHeaderLength + uint32(len(body)) - 4 + h.Length = maxHeaderLength + uint32(len(body)) - headerChecksumLen h.Magic = headerMagic h.ContentID = ContentIDGetBlockSnapshot h.PayloadLength = uint32(len(body)) @@ -2242,7 +2291,7 @@ func (m *MicroBlockSnapshotRequestMessage) MarshalBinary() ([]byte, error) { if err != nil { return nil, err } - copy(h.PayloadChecksum[:], dig[:4]) + copy(h.PayloadChecksum[:], dig[:headerChecksumLen]) hdr, err := h.MarshalBinary() if err != nil { diff --git a/pkg/services/services.go b/pkg/services/services.go index 50abc3b94..3ab3e4229 100644 --- a/pkg/services/services.go +++ b/pkg/services/services.go @@ -11,13 +11,15 @@ import ( type BlocksApplier interface { BlockExists(state state.State, block *proto.Block) (bool, error) - Apply(state state.State, block []*proto.Block) (proto.Height, error) - ApplyMicro(state state.State, block *proto.Block) (proto.Height, error) + Apply(state state.State, block []*proto.Block, snapshots []*proto.BlockSnapshot) (proto.Height, error) + ApplyMicro(state state.State, block *proto.Block, snapshots *proto.BlockSnapshot) (proto.Height, error) } type MicroBlockCache interface { Add(blockID proto.BlockID, micro *proto.MicroBlock) Get(proto.BlockID) (*proto.MicroBlock, bool) + AddSnapshot(blockID proto.BlockID, snapshot *proto.BlockSnapshot) + GetSnapshot(proto.BlockID) (*proto.BlockSnapshot, bool) } type MicroBlockInvCache interface { diff --git a/pkg/state/address_transactions_test.go b/pkg/state/address_transactions_test.go index 255796de8..7ff4b29b9 100644 --- a/pkg/state/address_transactions_test.go +++ b/pkg/state/address_transactions_test.go @@ -24,7 +24,7 @@ func testIterImpl(t *testing.T, params StateParams) { blocks, err := ReadMainnetBlocksToHeight(blockHeight) require.NoError(t, err) // Add extra blocks and rollback to check that rollback scenario is handled correctly. - _, err = st.AddDeserializedBlocks(blocks) + _, err = st.AddDeserializedBlocks(blocks, nil) require.NoError(t, err) err = st.RollbackToHeight(8000) require.NoError(t, err) diff --git a/pkg/state/api.go b/pkg/state/api.go index 6a636a1b6..7a8be2178 100644 --- a/pkg/state/api.go +++ b/pkg/state/api.go @@ -148,11 +148,11 @@ type StateModifier interface { // It's not recommended using this function when you are able to accumulate big blocks batch, // since it's much more efficient to add many blocks at once. AddBlock(block []byte) (*proto.Block, error) - AddDeserializedBlock(block *proto.Block) (*proto.Block, error) + AddDeserializedBlock(block *proto.Block, snapshot *proto.BlockSnapshot) (*proto.Block, error) // AddBlocks adds batch of new blocks to state. AddBlocks(blocks [][]byte) error // AddDeserializedBlocks marshals blocks to binary and calls AddBlocks. - AddDeserializedBlocks(blocks []*proto.Block) (*proto.Block, error) + AddDeserializedBlocks(blocks []*proto.Block, snapshots []*proto.BlockSnapshot) (*proto.Block, error) // Rollback functionality. RollbackToHeight(height proto.Height) error RollbackTo(removalEdge proto.BlockID) error diff --git a/pkg/state/appender.go b/pkg/state/appender.go index eed15363c..4ff914ebe 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -155,7 +155,8 @@ type appendBlockParams struct { chans *verifierChans block, parent *proto.BlockHeader height uint64 - snapshot proto.BlockSnapshot + snapshot *proto.BlockSnapshot + isLightNode bool } func (a *txAppender) orderIsScripted(order proto.Order) (bool, error) { @@ -644,81 +645,46 @@ func (a *txAppender) createInitialBlockSnapshot(minerAndRewardDiff txDiff) (txSn return snapshot, nil } -func (a *txAppender) appendBlock(params *appendBlockParams) error { - // Reset block complexity counter. - defer func() { - a.sc.resetComplexity() - a.totalScriptsRuns = 0 - }() - rideV5Activated, err := a.stor.features.newestIsActivated(int16(settings.RideV5)) - if err != nil { - return err - } - rideV6Activated, err := a.stor.features.newestIsActivated(int16(settings.RideV6)) - if err != nil { - return err - } - blockRewardDistribution, err := a.stor.features.newestIsActivated(int16(settings.BlockRewardDistribution)) - if err != nil { - return err - } - checkerInfo := &checkerInfo{ - currentTimestamp: params.block.Timestamp, - blockID: params.block.BlockID(), - blockVersion: params.block.Version, - height: params.height, - rideV5Activated: rideV5Activated, - rideV6Activated: rideV6Activated, - blockRewardDistribution: blockRewardDistribution, - } - hasParent := params.parent != nil - if hasParent { - checkerInfo.parentTimestamp = params.parent.Timestamp +func (a *txAppender) applySnapshotsInLightNode(params *appendBlockParams) error { + for _, txs := range params.snapshot.TxSnapshots { + for _, snapshot := range txs { + if errApply := snapshot.Apply(a.txHandler.tp.snapshotApplier); errApply != nil { + return errors.Wrap(errApply, "failed to apply tx snapshot") + } + } } - stateActionsCounterInBlockValidation := new(proto.StateActionsCounter) - - snapshotApplierInfo := newBlockSnapshotsApplierInfo(checkerInfo, a.settings.AddressSchemeCharacter, - stateActionsCounterInBlockValidation) - a.txHandler.tp.snapshotApplier.SetApplierInfo(snapshotApplierInfo) - // 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. - minerAndRewardDiff, err := a.blockDiffer.createMinerAndRewardDiff(params.block, hasParent) - if err != nil { + if err := a.stor.snapshots.saveSnapshots(params.block.BlockID(), params.height, *params.snapshot); err != nil { return err } - // create the initial snapshot - _, err = a.createInitialBlockSnapshot(minerAndRewardDiff) - if err != nil { - return errors.Wrap(err, "failed to create initial snapshot") - } - - // TODO apply this snapshot when balances are refatored - // err = initialSnapshot.Apply(&snapshotApplier) + return nil +} - // Save miner diff first (for validation) - if err = a.diffStor.saveTxDiff(minerAndRewardDiff); err != nil { - return err - } - blockInfo, err := a.currentBlockInfo() - if err != nil { - return err - } - blockV5Activated, err := a.stor.features.newestIsActivated(int16(settings.BlockV5)) - if err != nil { - return err - } - consensusImprovementsActivated, err := a.stor.features.newestIsActivated(int16(settings.ConsensusImprovements)) - if err != nil { - return err - } - blockRewardDistributionActivated, err := a.stor.features.newestIsActivated(int16(settings.BlockRewardDistribution)) - if err != nil { - return err - } - invokeExpressionActivated, err := a.stor.features.newestIsActivated(int16(settings.InvokeExpression)) - if err != nil { - return err +func (a *txAppender) appendTxs( + params *appendBlockParams, + info *checkerInfo, + stateActionsCounterInBlockValidation *proto.StateActionsCounter) error { + blockInfo, errBlockInfo := a.currentBlockInfo() + if errBlockInfo != nil { + return errBlockInfo + } + blockV5Activated, errActivatedFeature := a.stor.features.newestIsActivated(int16(settings.BlockV5)) + if errActivatedFeature != nil { + return errActivatedFeature + } + consensusImprovementsActivated, errActivatedFeature := + a.stor.features.newestIsActivated(int16(settings.ConsensusImprovements)) + if errActivatedFeature != nil { + return errActivatedFeature + } + blockRewardDistributionActivated, errActivatedFeature := + a.stor.features.newestIsActivated(int16(settings.BlockRewardDistribution)) + if errActivatedFeature != nil { + return errActivatedFeature + } + invokeExpressionActivated, errActivatedFeature := + a.stor.features.newestIsActivated(int16(settings.InvokeExpression)) + if errActivatedFeature != nil { + return errActivatedFeature } // Check and append transactions. var blockSnapshots proto.BlockSnapshot @@ -726,13 +692,13 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { for _, tx := range params.transactions { appendTxArgs := &appendTxParams{ chans: params.chans, - checkerInfo: checkerInfo, + checkerInfo: info, blockInfo: blockInfo, block: params.block, acceptFailed: blockV5Activated, blockV5Activated: blockV5Activated, - rideV5Activated: rideV5Activated, - rideV6Activated: rideV6Activated, + rideV5Activated: info.rideV5Activated, + rideV6Activated: info.rideV6Activated, consensusImprovementsActivated: consensusImprovementsActivated, blockRewardDistributionActivated: blockRewardDistributionActivated, invokeExpressionActivated: invokeExpressionActivated, @@ -746,15 +712,13 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { } blockSnapshots.AppendTxSnapshot(txSnapshots.regular) } - if err = a.stor.snapshots.saveSnapshots(params.block.BlockID(), params.height, blockSnapshots); err != nil { + if err := a.stor.snapshots.saveSnapshots(params.block.BlockID(), params.height, blockSnapshots); err != nil { return err } - // Save fee distribution of this block. - // This will be needed for createMinerAndRewardDiff() of next block due to NG. - return a.blockDiffer.saveCurFeeDistr(params.block) + return nil } -func (a *txAppender) appendBlockWithSnapshot(params *appendBlockParams) error { +func (a *txAppender) appendBlock(params *appendBlockParams) error { // Reset block complexity counter. defer func() { a.sc.resetComplexity() @@ -810,16 +774,14 @@ func (a *txAppender) appendBlockWithSnapshot(params *appendBlockParams) error { if err = a.diffStor.saveTxDiff(minerAndRewardDiff); err != nil { return err } - - for _, txs := range params.snapshot.TxSnapshots { - for _, snapshot := range txs { - if errApply := snapshot.Apply(a.txHandler.tp.snapshotApplier); errApply != nil { - return errors.Wrap(errApply, "failed to apply tx snapshot") - } + if params.isLightNode { + if err = a.applySnapshotsInLightNode(params); err != nil { + return err + } + } else { + if err = a.appendTxs(params, checkerInfo, stateActionsCounterInBlockValidation); err != nil { + return err } - } - if err = a.stor.snapshots.saveSnapshots(params.block.BlockID(), params.height, params.snapshot); err != nil { - return err } // Save fee distribution of this block. // This will be needed for createMinerAndRewardDiff() of next block due to NG. diff --git a/pkg/state/state.go b/pkg/state/state.go index ba3efc39a..c8cb03ff5 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -371,7 +371,8 @@ type stateManager struct { // Specifies how many goroutines will be run for verification of transactions and blocks signatures. verificationGoroutinesNum int - newBlocks *newBlocks + newBlocks *newBlocks + isLightNode bool } func newStateManager(dataDir string, amend bool, params StateParams, settings *settings.BlockchainSettings) (*stateManager, error) { @@ -591,7 +592,7 @@ func (s *stateManager) addGenesisBlock() error { defer cancel() chans := launchVerifier(ctx, s.verificationGoroutinesNum, s.settings.AddressSchemeCharacter) - if err := s.addNewBlock(s.genesis, nil, chans, 0); err != nil { + if err := s.addNewBlock(s.genesis, nil, chans, 0, nil, false); err != nil { return err } if err := s.stor.hitSources.appendBlockHitSource(s.genesis, 1, s.genesis.GenSignature); err != nil { @@ -1055,7 +1056,13 @@ func (s *stateManager) addRewardVote(block *proto.Block, height uint64) error { return s.stor.monetaryPolicy.vote(block.RewardVote, height, activation, isCappedRewardsActivated, block.BlockID()) } -func (s *stateManager) addNewBlock(block, parent *proto.Block, chans *verifierChans, height uint64) error { +func (s *stateManager) addNewBlock( + block, parent *proto.Block, + chans *verifierChans, + height uint64, + snapshot *proto.BlockSnapshot, + isLightNode bool, +) error { blockHeight := height + 1 // Add score. if err := s.stor.scores.appendBlockScore(block, blockHeight); err != nil { @@ -1083,6 +1090,8 @@ func (s *stateManager) addNewBlock(block, parent *proto.Block, chans *verifierCh block: &block.BlockHeader, parent: parentHeader, height: height, + snapshot: snapshot, + isLightNode: isLightNode, } // Check and perform block's transactions, create balance diffs, write transactions to storage. if err := s.appender.appendBlock(params); err != nil { @@ -1109,61 +1118,6 @@ func (s *stateManager) addNewBlock(block, parent *proto.Block, chans *verifierCh return nil } -func (s *stateManager) addNewBlockWithSnapshot(block, parent *proto.Block, snapshots proto.BlockSnapshot, chans *verifierChans, height uint64) error { - blockHeight := height + 1 - // Add score. - if err := s.stor.scores.appendBlockScore(block, blockHeight); err != nil { - return err - } - // Indicate new block for storage. - if err := s.rw.startBlock(block.BlockID()); err != nil { - return err - } - // Save block header to block storage. - if err := s.rw.writeBlockHeader(&block.BlockHeader); err != nil { - return err - } - transactions := block.Transactions - if block.TransactionCount != transactions.Count() { - return errors.Errorf("block.TransactionCount != transactions.Count(), %d != %d", block.TransactionCount, transactions.Count()) - } - var parentHeader *proto.BlockHeader - if parent != nil { - parentHeader = &parent.BlockHeader - } - params := &appendBlockParams{ - transactions: transactions, - chans: chans, - block: &block.BlockHeader, - parent: parentHeader, - height: height, - snapshot: snapshots, - } - // Check and perform block's transactions, create balance diffs, write transactions to storage. - if err := s.appender.appendBlockWithSnapshot(params); err != nil { - return err - } - // Let block storage know that the current block is over. - if err := s.rw.finishBlock(block.BlockID()); err != nil { - return err - } - // when block is finished blockchain height is incremented, so we should use 'blockHeight' as height value in actions below - - // Count features votes. - if err := s.addFeaturesVotes(block); err != nil { - return err - } - blockRewardActivated := s.stor.features.newestIsActivatedAtHeight(int16(settings.BlockReward), blockHeight) - // Count reward vote. - if blockRewardActivated { - err := s.addRewardVote(block, blockHeight) - if err != nil { - return err - } - } - return nil -} - func (s *stateManager) reset() { s.rw.reset() s.stor.reset() @@ -1190,7 +1144,7 @@ func (s *stateManager) flush() error { func (s *stateManager) AddBlock(block []byte) (*proto.Block, error) { s.newBlocks.setNewBinary([][]byte{block}) - rs, err := s.addBlocks() + rs, err := s.addBlocks(nil) if err != nil { if err := s.rw.syncWithDb(); err != nil { zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) @@ -1200,9 +1154,9 @@ func (s *stateManager) AddBlock(block []byte) (*proto.Block, error) { return rs, nil } -func (s *stateManager) AddDeserializedBlock(block *proto.Block) (*proto.Block, error) { +func (s *stateManager) AddDeserializedBlock(block *proto.Block, snapshot *proto.BlockSnapshot) (*proto.Block, error) { s.newBlocks.setNew([]*proto.Block{block}) - rs, err := s.addBlocks() + rs, err := s.addBlocks([]*proto.BlockSnapshot{snapshot}) if err != nil { if err := s.rw.syncWithDb(); err != nil { zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) @@ -1214,7 +1168,7 @@ func (s *stateManager) AddDeserializedBlock(block *proto.Block) (*proto.Block, e func (s *stateManager) AddBlocks(blockBytes [][]byte) error { s.newBlocks.setNewBinary(blockBytes) - if _, err := s.addBlocks(); err != nil { + if _, err := s.addBlocks(nil); err != nil { if err := s.rw.syncWithDb(); err != nil { zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) } @@ -1223,24 +1177,12 @@ func (s *stateManager) AddBlocks(blockBytes [][]byte) error { return nil } -func (s *stateManager) AddDeserializedBlocks(blocks []*proto.Block) (*proto.Block, error) { - s.newBlocks.setNew(blocks) - lastBlock, err := s.addBlocks() - if err != nil { - if err := s.rw.syncWithDb(); err != nil { - zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) - } - return nil, err - } - return lastBlock, nil -} - -func (s *stateManager) AddDeserializedBlocksWithSnapshots( +func (s *stateManager) AddDeserializedBlocks( blocks []*proto.Block, - snapshots []proto.BlockSnapshot, + snapshots []*proto.BlockSnapshot, ) (*proto.Block, error) { s.newBlocks.setNew(blocks) - lastBlock, err := s.addBlocksWithSnapshots(snapshots) + lastBlock, err := s.addBlocks(snapshots) if err != nil { if err := s.rw.syncWithDb(); err != nil { zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) @@ -1513,7 +1455,8 @@ func (s *stateManager) recalculateVotesAfterCappedRewardActivationInVotingPeriod return nil } -func (s *stateManager) addBlocks() (*proto.Block, error) { +func (s *stateManager) addBlocks(snapshots []*proto.BlockSnapshot) (*proto.Block, error) { //nolint:gocognit + // TODO: fix lint ctx, cancel := context.WithCancel(context.Background()) defer cancel() defer func() { @@ -1549,20 +1492,20 @@ func (s *stateManager) addBlocks() (*proto.Block, error) { pos := 0 for s.newBlocks.next() { blockchainCurHeight := height + uint64(pos) - block, err := s.newBlocks.current() - if err != nil { - return nil, wrapErr(DeserializationError, err) + block, errCurBlock := s.newBlocks.current() + if errCurBlock != nil { + return nil, wrapErr(DeserializationError, errCurBlock) } - if err := s.cv.ValidateHeaderBeforeBlockApplying(&block.BlockHeader, blockchainCurHeight); err != nil { + if err = s.cv.ValidateHeaderBeforeBlockApplying(&block.BlockHeader, blockchainCurHeight); err != nil { return nil, err } // Assign unique block number for this block ID, add this number to the list of valid blocks. - if err := s.stateDB.addBlock(block.BlockID()); err != nil { + if err = s.stateDB.addBlock(block.BlockID()); err != nil { return nil, wrapErr(ModificationError, err) } // At some blockchain heights specific logic is performed. // This includes voting for features, block rewards and so on. - if err := s.blockchainHeightAction(blockchainCurHeight, lastAppliedBlock.BlockID(), block.BlockID()); err != nil { + if err = s.blockchainHeightAction(blockchainCurHeight, lastAppliedBlock.BlockID(), block.BlockID()); err != nil { return nil, wrapErr(ModificationError, err) } // Send block for signature verification, which works in separate goroutine. @@ -1571,18 +1514,15 @@ func (s *stateManager) addBlocks() (*proto.Block, error) { parentID: lastAppliedBlock.BlockID(), block: block, } - if err := chans.trySend(task); err != nil { + if err = chans.trySend(task); err != nil { return nil, err } - hs, err := s.cv.GenerateHitSource(blockchainCurHeight, block.BlockHeader) - if err != nil { - return nil, err - } - if err := s.stor.hitSources.appendBlockHitSource(block, blockchainCurHeight+1, hs); err != nil { + if err = s.appendHitSource(block, blockchainCurHeight); err != nil { return nil, err } // Save block to storage, check its transactions, create and save balance diffs for its transactions. - if err := s.addNewBlock(block, lastAppliedBlock, chans, blockchainCurHeight); err != nil { + if err = s.addNewBlock(block, lastAppliedBlock, chans, + blockchainCurHeight, snapshots[pos], s.isLightNode); err != nil { return nil, err } @@ -1596,30 +1536,9 @@ func (s *stateManager) addBlocks() (*proto.Block, error) { ids = append(ids, block.BlockID()) lastAppliedBlock = block } - // Tasks chan can now be closed, since all the blocks and transactions have been already sent for verification. - // wait for all verifier goroutines - if verifyError := chans.closeAndWait(); verifyError != nil { - return nil, wrapErr(ValidationError, verifyError) - } - - // Apply all the balance diffs accumulated from this blocks batch. - // This also validates diffs for negative balances. - if err := s.appender.applyAllDiffs(); err != nil { + if err = s.afterAddingNewBlocks(chans, height, headers, pos, ids); err != nil { return nil, err } - - // Retrieve and store state hashes for each of new blocks. - if err := s.stor.handleStateHashes(height, ids); err != nil { - return nil, wrapErr(ModificationError, err) - } - // Validate consensus (i.e. that all the new blocks were mined fairly). - if err := s.cv.ValidateHeadersBatch(headers[:pos], height); err != nil { - return nil, wrapErr(ValidationError, err) - } - // After everything is validated, save all the changes to DB. - if err := s.flush(); err != nil { - return nil, wrapErr(ModificationError, err) - } zap.S().Infof( "Height: %d; Block ID: %s, GenSig: %s, ts: %d", height+uint64(blocksNumber), @@ -1630,121 +1549,49 @@ func (s *stateManager) addBlocks() (*proto.Block, error) { return lastAppliedBlock, nil } -func (s *stateManager) addBlocksWithSnapshots(snapshots []proto.BlockSnapshot) (*proto.Block, error) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - defer func() { - // Reset in-memory storages and load last block in defer. - s.reset() - if err := s.loadLastBlock(); err != nil { - zap.S().Fatalf("Failed to load last block: %v", err) - } - s.newBlocks.reset() - }() - - blocksNumber := s.newBlocks.len() - if blocksNumber == 0 { - return nil, wrapErr(InvalidInputError, errors.New("no blocks provided")) - } - - // Read some useful values for later. - lastAppliedBlock, err := s.topBlock() +func (s *stateManager) appendHitSource(block *proto.Block, blockchainCurHeight proto.Height) error { + hs, err := s.cv.GenerateHitSource(blockchainCurHeight, block.BlockHeader) if err != nil { - return nil, wrapErr(RetrievalError, err) + return err } - zap.S().Debugf("StateManager: parent (top) block ID: %s, ts: %d", lastAppliedBlock.BlockID().String(), lastAppliedBlock.Timestamp) - height, err := s.Height() - if err != nil { - return nil, wrapErr(RetrievalError, err) + if err = s.stor.hitSources.appendBlockHitSource(block, blockchainCurHeight+1, hs); err != nil { + return err } - headers := make([]proto.BlockHeader, blocksNumber) - - // Launch verifier that checks signatures of blocks and transactions. - chans := launchVerifier(ctx, s.verificationGoroutinesNum, s.settings.AddressSchemeCharacter) - - var ids []proto.BlockID - pos := 0 - for s.newBlocks.next() { - blockchainCurHeight := height + uint64(pos) - block, err := s.newBlocks.current() - if err != nil { - return nil, wrapErr(DeserializationError, err) - } - if err := s.cv.ValidateHeaderBeforeBlockApplying(&block.BlockHeader, blockchainCurHeight); err != nil { - return nil, err - } - // Assign unique block number for this block ID, add this number to the list of valid blocks. - if err := s.stateDB.addBlock(block.BlockID()); err != nil { - return nil, wrapErr(ModificationError, err) - } - // At some blockchain heights specific logic is performed. - // This includes voting for features, block rewards and so on. - if err := s.blockchainHeightAction(blockchainCurHeight, lastAppliedBlock.BlockID(), block.BlockID()); err != nil { - return nil, wrapErr(ModificationError, err) - } - // Send block for signature verification, which works in separate goroutine. - task := &verifyTask{ - taskType: verifyBlock, - parentID: lastAppliedBlock.BlockID(), - block: block, - } - if err := chans.trySend(task); err != nil { - return nil, err - } - hs, err := s.cv.GenerateHitSource(blockchainCurHeight, block.BlockHeader) - if err != nil { - return nil, err - } - if err := s.stor.hitSources.appendBlockHitSource(block, blockchainCurHeight+1, hs); err != nil { - return nil, err - } - // Save block to storage, check its transactions, create and save balance diffs for its transactions. - if err := s.addNewBlockWithSnapshot(block, lastAppliedBlock, snapshots[pos], chans, blockchainCurHeight); err != nil { - return nil, err - } + return nil +} - if s.needToFinishVotingPeriod(blockchainCurHeight + 1) { - // If we need to finish voting period on the next block (h+1) then - // we have to check that protobuf will be activated on next block - s.checkProtobufActivation(blockchainCurHeight + 2) - } - headers[pos] = block.BlockHeader - pos++ - ids = append(ids, block.BlockID()) - lastAppliedBlock = block - } +func (s *stateManager) afterAddingNewBlocks( + chans *verifierChans, + height proto.Height, + headers []proto.BlockHeader, + pos int, + ids []proto.BlockID, +) error { // Tasks chan can now be closed, since all the blocks and transactions have been already sent for verification. // wait for all verifier goroutines if verifyError := chans.closeAndWait(); verifyError != nil { - return nil, wrapErr(ValidationError, verifyError) + return wrapErr(ValidationError, verifyError) } // Apply all the balance diffs accumulated from this blocks batch. // This also validates diffs for negative balances. if err := s.appender.applyAllDiffs(); err != nil { - return nil, err + return err } // Retrieve and store state hashes for each of new blocks. if err := s.stor.handleStateHashes(height, ids); err != nil { - return nil, wrapErr(ModificationError, err) + return wrapErr(ModificationError, err) } // Validate consensus (i.e. that all the new blocks were mined fairly). if err := s.cv.ValidateHeadersBatch(headers[:pos], height); err != nil { - return nil, wrapErr(ValidationError, err) + return wrapErr(ValidationError, err) } // After everything is validated, save all the changes to DB. if err := s.flush(); err != nil { - return nil, wrapErr(ModificationError, err) + return wrapErr(ModificationError, err) } - zap.S().Infof( - "Height: %d; Block ID: %s, GenSig: %s, ts: %d", - height+uint64(blocksNumber), - lastAppliedBlock.BlockID().String(), - base58.Encode(lastAppliedBlock.GenSignature), - lastAppliedBlock.Timestamp, - ) - return lastAppliedBlock, nil + return nil } func (s *stateManager) checkRollbackHeight(height uint64) error { diff --git a/pkg/state/threadsafe_wrapper.go b/pkg/state/threadsafe_wrapper.go index f2cadc502..7f01eb1a6 100644 --- a/pkg/state/threadsafe_wrapper.go +++ b/pkg/state/threadsafe_wrapper.go @@ -413,10 +413,13 @@ func (a *ThreadSafeWriteWrapper) AddBlock(block []byte) (*proto.Block, error) { return a.s.AddBlock(block) } -func (a *ThreadSafeWriteWrapper) AddDeserializedBlock(block *proto.Block) (*proto.Block, error) { +func (a *ThreadSafeWriteWrapper) AddDeserializedBlock( + block *proto.Block, + snapshot *proto.BlockSnapshot, +) (*proto.Block, error) { a.lock() defer a.unlock() - return a.s.AddDeserializedBlock(block) + return a.s.AddDeserializedBlock(block, snapshot) } func (a *ThreadSafeWriteWrapper) AddBlocks(blocks [][]byte) error { @@ -425,10 +428,13 @@ func (a *ThreadSafeWriteWrapper) AddBlocks(blocks [][]byte) error { return a.s.AddBlocks(blocks) } -func (a *ThreadSafeWriteWrapper) AddDeserializedBlocks(blocks []*proto.Block) (*proto.Block, error) { +func (a *ThreadSafeWriteWrapper) AddDeserializedBlocks( + blocks []*proto.Block, + snapshots []*proto.BlockSnapshot, +) (*proto.Block, error) { a.lock() defer a.unlock() - return a.s.AddDeserializedBlocks(blocks) + return a.s.AddDeserializedBlocks(blocks, snapshots) } func (a *ThreadSafeWriteWrapper) RollbackToHeight(height proto.Height) error { From c9ec17d8f992db7d7daa54060076ece5e4efc6c3 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Tue, 12 Dec 2023 21:14:12 +0300 Subject: [PATCH 089/139] fix linter issue --- pkg/state/appender.go | 10 ++-------- pkg/state/state.go | 5 +---- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 4ff914ebe..384c0ad5a 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -653,10 +653,7 @@ func (a *txAppender) applySnapshotsInLightNode(params *appendBlockParams) error } } } - if err := a.stor.snapshots.saveSnapshots(params.block.BlockID(), params.height, *params.snapshot); err != nil { - return err - } - return nil + return a.stor.snapshots.saveSnapshots(params.block.BlockID(), params.height, *params.snapshot) } func (a *txAppender) appendTxs( @@ -712,10 +709,7 @@ func (a *txAppender) appendTxs( } blockSnapshots.AppendTxSnapshot(txSnapshots.regular) } - if err := a.stor.snapshots.saveSnapshots(params.block.BlockID(), params.height, blockSnapshots); err != nil { - return err - } - return nil + return a.stor.snapshots.saveSnapshots(params.block.BlockID(), params.height, blockSnapshots) } func (a *txAppender) appendBlock(params *appendBlockParams) error { diff --git a/pkg/state/state.go b/pkg/state/state.go index eef1bb4a9..dbd555fe4 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -1558,10 +1558,7 @@ func (s *stateManager) appendHitSource(block *proto.Block, blockchainCurHeight p if err != nil { return err } - if err = s.stor.hitSources.appendBlockHitSource(block, blockchainCurHeight+1, hs); err != nil { - return err - } - return nil + return s.stor.hitSources.appendBlockHitSource(block, blockchainCurHeight+1, hs) } func (s *stateManager) afterAddingNewBlocks( From c3dbeb231d5a09ce2f14510bd09d449ce8177609 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Tue, 12 Dec 2023 22:09:33 +0300 Subject: [PATCH 090/139] fix tests --- pkg/libs/ordered_blocks/optimistic_load.go | 18 ++++--- .../ordered_blocks/optimistic_load_test.go | 10 ++-- pkg/node/blocks_applier/blocks_applier.go | 52 +++++++++++++++---- pkg/node/blocks_applier/node_mocks.go | 4 +- pkg/node/fsm/sync_internal/internal.go | 4 +- pkg/state/appender.go | 3 +- pkg/state/state.go | 17 +++--- 7 files changed, 76 insertions(+), 32 deletions(-) diff --git a/pkg/libs/ordered_blocks/optimistic_load.go b/pkg/libs/ordered_blocks/optimistic_load.go index c428ccd20..49fc50a06 100644 --- a/pkg/libs/ordered_blocks/optimistic_load.go +++ b/pkg/libs/ordered_blocks/optimistic_load.go @@ -31,27 +31,31 @@ func (a *OrderedBlocks) SetSnapshot(blockID proto.BlockID, snapshot *proto.Block a.snapshots[blockID] = snapshot } -func (a *OrderedBlocks) pop() (proto.BlockID, *proto.Block, *proto.BlockSnapshot, bool) { +func (a *OrderedBlocks) pop(isLightNode bool) (proto.BlockID, *proto.Block, *proto.BlockSnapshot, bool) { if len(a.requestedBlocks) == 0 { return proto.BlockID{}, nil, nil, false } firstSig := a.requestedBlocks[0] bts := a.blocks[firstSig] bsn := a.snapshots[firstSig] - if bts != nil && bsn != nil { + if bts != nil { delete(a.blocks, firstSig) - delete(a.snapshots, firstSig) + if isLightNode && bsn != nil { + delete(a.snapshots, firstSig) + a.requestedBlocks = a.requestedBlocks[1:] + return firstSig, bts, bsn, true + } a.requestedBlocks = a.requestedBlocks[1:] - return firstSig, bts, bsn, true + return firstSig, bts, nil, true } return proto.BlockID{}, nil, nil, false } -func (a *OrderedBlocks) PopAll() ([]*proto.Block, []*proto.BlockSnapshot) { +func (a *OrderedBlocks) PopAll(isLightNode bool) ([]*proto.Block, []*proto.BlockSnapshot) { var outBlocks []*proto.Block var outSnapshots []*proto.BlockSnapshot for { - _, b, s, ok := a.pop() + _, b, s, ok := a.pop(isLightNode) if !ok { return outBlocks, outSnapshots } @@ -79,7 +83,7 @@ func (a *OrderedBlocks) RequestedCount() int { // blocks count available for pop func (a *OrderedBlocks) ReceivedCount(isLightNode bool) int { for i, sig := range a.requestedBlocks { - if isLightNode && a.blocks[sig] == nil || a.snapshots[sig] == nil { + if isLightNode && (a.blocks[sig] == nil || a.snapshots[sig] == nil) { return i } else if !isLightNode && a.blocks[sig] == nil { return i diff --git a/pkg/libs/ordered_blocks/optimistic_load_test.go b/pkg/libs/ordered_blocks/optimistic_load_test.go index 335af63f7..f3c70a72c 100644 --- a/pkg/libs/ordered_blocks/optimistic_load_test.go +++ b/pkg/libs/ordered_blocks/optimistic_load_test.go @@ -23,23 +23,23 @@ func makeBlock(sig crypto.Signature) *proto.Block { func TestOrderedBlocks(t *testing.T) { o := ordered_blocks.NewOrderedBlocks() o.Add(proto.NewBlockIDFromSignature(sig1)) - b, _ := o.PopAll() + b, _ := o.PopAll(false) require.Len(t, b, 0) - b, _ = o.PopAll() + b, _ = o.PopAll(false) o.Add(proto.NewBlockIDFromSignature(sig2)) require.Len(t, b, 0) // second block arrived first, no sequence right now o.SetBlock(makeBlock(sig2)) - b, _ = o.PopAll() + b, _ = o.PopAll(false) require.Len(t, b, 0) //require.Equal(t, 0, o.ReceivedCount()) // finally arrived first block, so seq contains 2 blocks o.SetBlock(makeBlock(sig1)) //require.Equal(t, 2, o.ReceivedCount()) - b, _ = o.PopAll() + b, _ = o.PopAll(false) require.Len(t, b, 2) } @@ -55,6 +55,6 @@ func TestOrderedBlocks_AvailableCount(t *testing.T) { o.SetBlock(makeBlock(sig2)) require.Equal(t, 2, o.ReceivedCount(false)) - o.PopAll() + o.PopAll(false) require.Equal(t, 0, o.ReceivedCount(false)) } diff --git a/pkg/node/blocks_applier/blocks_applier.go b/pkg/node/blocks_applier/blocks_applier.go index e4127a885..141b0876f 100644 --- a/pkg/node/blocks_applier/blocks_applier.go +++ b/pkg/node/blocks_applier/blocks_applier.go @@ -35,7 +35,7 @@ func (a *innerBlocksApplier) exists(storage innerState, block *proto.Block) (boo return false, err } -func (a *innerBlocksApplier) apply( +func (a *innerBlocksApplier) apply( //nolint:gocognit storage innerState, blocks []*proto.Block, snapshots []*proto.BlockSnapshot, @@ -100,9 +100,18 @@ func (a *innerBlocksApplier) apply( } // save previously added blocks. If new firstBlock failed to add, then return them back - rollbackBlocks, rollbackBlocksSnapshots, err := a.getRollbackBlocksAndSnapshots(storage, deltaHeight, parentHeight) - if err != nil { - return 0, err + var rollbackBlocks []*proto.Block + var rollbackBlocksSnapshots []*proto.BlockSnapshot + if snapshots != nil { + rollbackBlocks, rollbackBlocksSnapshots, err = a.getRollbackBlocksAndSnapshots(storage, deltaHeight, parentHeight) + if err != nil { + return 0, err + } + } else { + rollbackBlocks, err = a.getRollbackBlocks(storage, deltaHeight, parentHeight) + if err != nil { + return 0, err + } } err = storage.RollbackToHeight(parentHeight) @@ -145,6 +154,22 @@ func (a *innerBlocksApplier) getRollbackBlocksAndSnapshots( return rollbackBlocks, rollbackBlocksSnapshots, nil } +func (a *innerBlocksApplier) getRollbackBlocks( + storage innerState, + deltaHeight proto.Height, + parentHeight proto.Height, +) ([]*proto.Block, error) { + rollbackBlocks := make([]*proto.Block, 0, deltaHeight) + for i := proto.Height(1); i <= deltaHeight; i++ { + block, err := storage.BlockByHeight(parentHeight + i) + if err != nil { + return nil, errors.Wrapf(err, "failed to get firstBlock by height %d", parentHeight+i) + } + rollbackBlocks = append(rollbackBlocks, block) + } + return rollbackBlocks, nil +} + func (a *innerBlocksApplier) applyMicro( storage innerState, block *proto.Block, @@ -175,22 +200,31 @@ func (a *innerBlocksApplier) applyMicro( if err != nil { return 0, errors.Wrapf(err, "failed to get current block by height %d", currentHeight) } - currentSnapshot, err := storage.SnapshotsAtHeight(currentHeight) - if err != nil { - return 0, err + var currentSnapshotsToApply []*proto.BlockSnapshot + if snapshot != nil { + curSnapshot, errSAT := storage.SnapshotsAtHeight(currentHeight) + if errSAT != nil { + return 0, errSAT + } + currentSnapshotsToApply = []*proto.BlockSnapshot{&curSnapshot} } + err = storage.RollbackToHeight(parentHeight) if err != nil { return 0, errors.Wrapf(err, "failed to rollback to height %d", parentHeight) } // applying new blocks - _, err = storage.AddDeserializedBlocks([]*proto.Block{block}, []*proto.BlockSnapshot{snapshot}) + var snapshotToApply []*proto.BlockSnapshot + if snapshot != nil { + snapshotToApply = []*proto.BlockSnapshot{snapshot} + } + _, err = storage.AddDeserializedBlocks([]*proto.Block{block}, snapshotToApply) if err != nil { // return back saved blocks _, err2 := storage.AddDeserializedBlocks( []*proto.Block{currentBlock}, - []*proto.BlockSnapshot{¤tSnapshot}, + currentSnapshotsToApply, ) if err2 != nil { return 0, errors.Wrap(err2, "failed rollback block") diff --git a/pkg/node/blocks_applier/node_mocks.go b/pkg/node/blocks_applier/node_mocks.go index 68513e809..d29e33e56 100644 --- a/pkg/node/blocks_applier/node_mocks.go +++ b/pkg/node/blocks_applier/node_mocks.go @@ -287,7 +287,9 @@ func (a *MockStateManager) AddDeserializedBlocks( if out, err = a.AddDeserializedBlock(b); err != nil { return nil, err } - a.snapshots = append(a.snapshots, snapshots[i]) + if snapshots != nil { + a.snapshots = append(a.snapshots, snapshots[i]) + } } return out, nil } diff --git a/pkg/node/fsm/sync_internal/internal.go b/pkg/node/fsm/sync_internal/internal.go index 4874572a4..64aca79bf 100644 --- a/pkg/node/fsm/sync_internal/internal.go +++ b/pkg/node/fsm/sync_internal/internal.go @@ -106,11 +106,11 @@ func (a Internal) Blocks(p peerExtension) (Internal, Blocks, Snapshots, Eof) { return NewInternal(a.orderedBlocks, a.respondedSignatures, a.waitingForSignatures, a.isLightNode), nil, nil, false } if a.orderedBlocks.RequestedCount() < 100 { - bs, ss := a.orderedBlocks.PopAll() + bs, ss := a.orderedBlocks.PopAll(a.isLightNode) return NewInternal(a.orderedBlocks, a.respondedSignatures, false, a.isLightNode), bs, ss, true } p.AskBlocksIDs(a.respondedSignatures.BlockIDS()) - bs, ss := a.orderedBlocks.PopAll() + bs, ss := a.orderedBlocks.PopAll(a.isLightNode) return NewInternal(a.orderedBlocks, a.respondedSignatures, true, a.isLightNode), bs, ss, false } diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 384c0ad5a..9b6ef178b 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -156,7 +156,6 @@ type appendBlockParams struct { block, parent *proto.BlockHeader height uint64 snapshot *proto.BlockSnapshot - isLightNode bool } func (a *txAppender) orderIsScripted(order proto.Order) (bool, error) { @@ -768,7 +767,7 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { if err = a.diffStor.saveTxDiff(minerAndRewardDiff); err != nil { return err } - if params.isLightNode { + if params.snapshot != nil { if err = a.applySnapshotsInLightNode(params); err != nil { return err } diff --git a/pkg/state/state.go b/pkg/state/state.go index dbd555fe4..77a896672 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -371,8 +371,7 @@ type stateManager struct { // Specifies how many goroutines will be run for verification of transactions and blocks signatures. verificationGoroutinesNum int - newBlocks *newBlocks - isLightNode bool + newBlocks *newBlocks } func newStateManager(dataDir string, amend bool, params StateParams, settings *settings.BlockchainSettings) (*stateManager, error) { @@ -592,7 +591,7 @@ func (s *stateManager) addGenesisBlock() error { defer cancel() chans := launchVerifier(ctx, s.verificationGoroutinesNum, s.settings.AddressSchemeCharacter) - if err := s.addNewBlock(s.genesis, nil, chans, 0, nil, false); err != nil { + if err := s.addNewBlock(s.genesis, nil, chans, 0, nil); err != nil { return err } if err := s.stor.hitSources.appendBlockHitSource(s.genesis, 1, s.genesis.GenSignature); err != nil { @@ -1065,7 +1064,6 @@ func (s *stateManager) addNewBlock( chans *verifierChans, height uint64, snapshot *proto.BlockSnapshot, - isLightNode bool, ) error { blockHeight := height + 1 // Add score. @@ -1095,7 +1093,6 @@ func (s *stateManager) addNewBlock( parent: parentHeader, height: height, snapshot: snapshot, - isLightNode: isLightNode, } // Check and perform block's transactions, create balance diffs, write transactions to storage. if err := s.appender.appendBlock(params); err != nil { @@ -1459,6 +1456,14 @@ func (s *stateManager) recalculateVotesAfterCappedRewardActivationInVotingPeriod return nil } +func getSnapshotByIndIfNotNil(snapshots []*proto.BlockSnapshot, pos int) *proto.BlockSnapshot { + if snapshots == nil { + return nil + } + + return snapshots[pos] +} + func (s *stateManager) addBlocks(snapshots []*proto.BlockSnapshot) (*proto.Block, error) { //nolint:gocognit // TODO: fix lint ctx, cancel := context.WithCancel(context.Background()) @@ -1526,7 +1531,7 @@ func (s *stateManager) addBlocks(snapshots []*proto.BlockSnapshot) (*proto.Block } // Save block to storage, check its transactions, create and save balance diffs for its transactions. if err = s.addNewBlock(block, lastAppliedBlock, chans, - blockchainCurHeight, snapshots[pos], s.isLightNode); err != nil { + blockchainCurHeight, getSnapshotByIndIfNotNil(snapshots, pos)); err != nil { return nil, err } From e22129dfaca05a41b719bbe9f02375047510519e Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Thu, 21 Dec 2023 15:37:41 +0300 Subject: [PATCH 091/139] fix ng state --- itests/config/template.conf | 1 - pkg/node/fsm/ng_state.go | 2 +- pkg/state/appender.go | 2 -- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/itests/config/template.conf b/itests/config/template.conf index 54071a1e1..1ecba277e 100644 --- a/itests/config/template.conf +++ b/itests/config/template.conf @@ -2,7 +2,6 @@ waves { blockchain.type = CUSTOM directory = /var/lib/waves/ ntp-server = "localhost:123" - enable-light-mode = false db { store-state-hashes = true } diff --git a/pkg/node/fsm/ng_state.go b/pkg/node/fsm/ng_state.go index 62b004831..1c64ace2e 100644 --- a/pkg/node/fsm/ng_state.go +++ b/pkg/node/fsm/ng_state.go @@ -182,6 +182,7 @@ func (a *NGState) Block(peer peer.Peer, block *proto.Block) (State, Async, error pe.AskBlockSnapshot(block.BlockID()) return a, tasks.Tasks(tasks.NewSnapshotTimeoutTask(time.Minute, block.BlockID(), tasks.BlockSnapshot)), nil } + _, err = a.baseInfo.blocksApplier.Apply(a.baseInfo.storage, []*proto.Block{block}, nil) a.blocksCache.Clear() a.blocksCache.AddBlockState(block) a.baseInfo.scheduler.Reschedule() @@ -248,7 +249,6 @@ func (a *NGState) MinedBlock( a.blocksCache.Clear() a.blocksCache.AddBlockState(block) - a.baseInfo.scheduler.Reschedule() a.baseInfo.actions.SendBlock(block) a.baseInfo.actions.SendScore(a.baseInfo.storage) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 9b6ef178b..9c5898ea2 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -610,8 +610,6 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) (txS zap.S().Errorf("failed to commit transaction (id %s) after successful validation; this should NEVER happen", base58.Encode(txID)) return txSnapshot{}, err } - // TODO: a temporary dummy for linters - _ = 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 { From d0e2fcd0580e31692f6619f66412538f2edcc282 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Mon, 25 Dec 2023 12:14:28 +0300 Subject: [PATCH 092/139] fix some bugs --- pkg/state/state.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pkg/state/state.go b/pkg/state/state.go index 1d769df84..4e7d58834 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -1569,6 +1569,17 @@ func (s *stateManager) addBlocks(snapshots []*proto.BlockSnapshot) (*proto.Block ids = append(ids, block.BlockID()) lastAppliedBlock = block } + // Tasks chan can now be closed, since all the blocks and transactions have been already sent for verification. + // wait for all verifier goroutines + if verifyError := chans.closeAndWait(); verifyError != nil { + return nil, wrapErr(ValidationError, verifyError) + } + + // Apply all the balance diffs accumulated from this blocks batch. + // This also validates diffs for negative balances. + if err := s.appender.applyAllDiffs(); err != nil { + return nil, err + } // Retrieve and store legacy state hashes for each of new blocks. if shErr := s.stor.handleLegacyStateHashes(height, ids); shErr != nil { From 4d9d3116a732e4ba33c714369f28d454b2af60b3 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Wed, 10 Jan 2024 04:41:51 +0300 Subject: [PATCH 093/139] Merge fix --- pkg/state/appender.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index b3348da02..b2110b0ab 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -648,7 +648,7 @@ func (a *txAppender) applySnapshotsInLightNode( } for _, snapshot := range txs { - if errApply := snapshot.Apply(a.txHandler.tp.snapshotApplier); errApply != nil { + if errApply := snapshot.Apply(a.txHandler.sa); errApply != nil { return errors.Wrap(errApply, "failed to apply tx snapshot") } } From ba7a6843470b79a64956bf19d161044cee82d681 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Tue, 16 Jan 2024 12:14:17 +0300 Subject: [PATCH 094/139] fix issues --- cmd/importer/importer.go | 2 +- cmd/node/node.go | 4 +- cmd/rollback/main.go | 2 +- cmd/statehash/statehash.go | 2 +- pkg/grpc/server/common_test.go | 4 +- pkg/libs/microblock_cache/microblock_cache.go | 35 ++++---- pkg/libs/ordered_blocks/optimistic_load.go | 33 ++++---- pkg/node/actions_by_type.go | 27 +++--- pkg/node/blocks_applier/blocks_applier.go | 18 ++-- .../blocks_applier/blocks_applier_test.go | 4 +- pkg/node/blocks_applier/node_mocks.go | 4 + pkg/node/fsm/fsm.go | 14 +++- pkg/node/fsm/ng_state.go | 71 +++++++++------- pkg/node/fsm/sync_internal/internal.go | 2 +- pkg/node/fsm/sync_state.go | 49 +++++------ pkg/node/fsm/tasks/tasks.go | 51 ----------- pkg/proto/proto.go | 48 ++++------- pkg/proto/types.go | 8 -- pkg/services/services.go | 21 +++-- pkg/state/address_transactions_test.go | 2 +- pkg/state/api.go | 10 ++- pkg/state/appender.go | 84 ++++++++----------- pkg/state/invoke_applier_test.go | 2 +- pkg/state/state.go | 17 +++- pkg/state/state_test.go | 16 ++-- 25 files changed, 249 insertions(+), 281 deletions(-) diff --git a/cmd/importer/importer.go b/cmd/importer/importer.go index 8eb6d9af0..883759161 100644 --- a/cmd/importer/importer.go +++ b/cmd/importer/importer.go @@ -125,7 +125,7 @@ func main() { // We do not need to provide any APIs during import. params.ProvideExtendedApi = false - st, err := state.NewState(*dataDirPath, false, params, ss) + st, err := state.NewState(*dataDirPath, false, params, ss, false) if err != nil { zap.S().Fatalf("Failed to create state: %v", err) } diff --git a/cmd/node/node.go b/cmd/node/node.go index 123b44274..530b15cd6 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -234,7 +234,7 @@ func (c *config) parse() { flag.DurationVar(&c.microblockInterval, "microblock-interval", defaultMicroblockInterval, "Interval between microblocks.") flag.BoolVar(&c.enableLightMode, "enable-light-mode", false, - "Start node in light mode (disable mining and store only snapshots)") + "Start node in light mode") flag.Parse() c.logLevel = *l } @@ -383,7 +383,7 @@ func main() { params.Time = ntpTime params.DbParams.BloomFilterParams.Disable = nc.disableBloomFilter - st, err := state.NewState(path, true, params, cfg) + st, err := state.NewState(path, true, params, cfg, nc.enableLightMode) if err != nil { zap.S().Error("Failed to initialize node's state: %v", err) return diff --git a/cmd/rollback/main.go b/cmd/rollback/main.go index b637f795b..4116e6335 100644 --- a/cmd/rollback/main.go +++ b/cmd/rollback/main.go @@ -75,7 +75,7 @@ func main() { params.BuildStateHashes = *buildStateHashes params.StoreExtendedApiData = *buildExtendedAPI - s, err := state.NewState(*statePath, true, params, cfg) + s, err := state.NewState(*statePath, true, params, cfg, false) if err != nil { zap.S().Error(err) return diff --git a/cmd/statehash/statehash.go b/cmd/statehash/statehash.go index b90f6e2f7..62d33226a 100644 --- a/cmd/statehash/statehash.go +++ b/cmd/statehash/statehash.go @@ -103,7 +103,7 @@ func run() error { params.BuildStateHashes = true params.ProvideExtendedApi = false - st, err := state.NewState(statePath, false, params, ss) + st, err := state.NewState(statePath, false, params, ss, false) if err != nil { zap.S().Errorf("Failed to open state at '%s': %v", statePath, err) return err diff --git a/pkg/grpc/server/common_test.go b/pkg/grpc/server/common_test.go index b02d567f5..a6d3b5834 100644 --- a/pkg/grpc/server/common_test.go +++ b/pkg/grpc/server/common_test.go @@ -86,7 +86,7 @@ func stateWithCustomGenesis(t *testing.T, genesisPath string) state.State { // Activate data transactions. sets.PreactivatedFeatures = []int16{5} params := defaultStateParams() - st, err := state.NewState(dataDir, true, params, sets) + st, err := state.NewState(dataDir, true, params, sets, false) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, st.Close()) @@ -120,7 +120,7 @@ func withAutoCancel(t *testing.T, ctx context.Context) context.Context { func newTestState(t *testing.T, amend bool, params state.StateParams, settings *settings.BlockchainSettings) state.State { dataDir := t.TempDir() - st, err := state.NewState(dataDir, amend, params, settings) + st, err := state.NewState(dataDir, amend, params, settings, false) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, st.Close()) diff --git a/pkg/libs/microblock_cache/microblock_cache.go b/pkg/libs/microblock_cache/microblock_cache.go index 69f3c8c3a..28a188d61 100644 --- a/pkg/libs/microblock_cache/microblock_cache.go +++ b/pkg/libs/microblock_cache/microblock_cache.go @@ -7,39 +7,46 @@ import ( const microBlockCacheSize = 24 +type microBlockWithSnapshot struct { + microBlock *proto.MicroBlock + snapshot *proto.BlockSnapshot +} + type MicroBlockCache struct { - blockCache *fifo_cache.FIFOCache - snapshotCache *fifo_cache.FIFOCache + cache *fifo_cache.FIFOCache } func NewMicroBlockCache() *MicroBlockCache { return &MicroBlockCache{ - blockCache: fifo_cache.New(microBlockCacheSize), - snapshotCache: fifo_cache.New(microBlockCacheSize), + cache: fifo_cache.New(microBlockCacheSize), } } -func (a *MicroBlockCache) Add(blockID proto.BlockID, micro *proto.MicroBlock) { - a.blockCache.Add2(blockID.Bytes(), micro) +func (a *MicroBlockCache) AddMicroBlockWithSnapshot( + blockID proto.BlockID, + micro *proto.MicroBlock, + snapshot *proto.BlockSnapshot, +) { + a.cache.Add2(blockID.Bytes(), microBlockWithSnapshot{ + microBlock: micro, + snapshot: snapshot, + }) } -func (a *MicroBlockCache) Get(sig proto.BlockID) (*proto.MicroBlock, bool) { - rs, ok := a.blockCache.Get(sig.Bytes()) +func (a *MicroBlockCache) GetBlock(sig proto.BlockID) (*proto.MicroBlock, bool) { + rs, ok := a.cache.Get(sig.Bytes()) if !ok { return nil, false } - return rs.(*proto.MicroBlock), true + return rs.(microBlockWithSnapshot).microBlock, true } -func (a *MicroBlockCache) AddSnapshot(blockID proto.BlockID, snapshot *proto.BlockSnapshot) { - a.snapshotCache.Add2(blockID.Bytes(), snapshot) -} func (a *MicroBlockCache) GetSnapshot(sig proto.BlockID) (*proto.BlockSnapshot, bool) { - rs, ok := a.snapshotCache.Get(sig.Bytes()) + rs, ok := a.cache.Get(sig.Bytes()) if !ok { return nil, false } - return rs.(*proto.BlockSnapshot), true + return rs.(microBlockWithSnapshot).snapshot, true } type MicroblockInvCache struct { diff --git a/pkg/libs/ordered_blocks/optimistic_load.go b/pkg/libs/ordered_blocks/optimistic_load.go index 49fc50a06..f00712358 100644 --- a/pkg/libs/ordered_blocks/optimistic_load.go +++ b/pkg/libs/ordered_blocks/optimistic_load.go @@ -5,16 +5,16 @@ import ( ) type OrderedBlocks struct { - requestedBlocks []proto.BlockID - blocks map[proto.BlockID]*proto.Block - snapshots map[proto.BlockID]*proto.BlockSnapshot + requested []proto.BlockID + blocks map[proto.BlockID]*proto.Block + snapshots map[proto.BlockID]*proto.BlockSnapshot } func NewOrderedBlocks() *OrderedBlocks { return &OrderedBlocks{ - requestedBlocks: nil, - blocks: make(map[proto.BlockID]*proto.Block), - snapshots: make(map[proto.BlockID]*proto.BlockSnapshot), + requested: nil, + blocks: make(map[proto.BlockID]*proto.Block), + snapshots: make(map[proto.BlockID]*proto.BlockSnapshot), } } @@ -32,20 +32,20 @@ func (a *OrderedBlocks) SetSnapshot(blockID proto.BlockID, snapshot *proto.Block } func (a *OrderedBlocks) pop(isLightNode bool) (proto.BlockID, *proto.Block, *proto.BlockSnapshot, bool) { - if len(a.requestedBlocks) == 0 { + if len(a.requested) == 0 { return proto.BlockID{}, nil, nil, false } - firstSig := a.requestedBlocks[0] + firstSig := a.requested[0] bts := a.blocks[firstSig] bsn := a.snapshots[firstSig] if bts != nil { delete(a.blocks, firstSig) if isLightNode && bsn != nil { delete(a.snapshots, firstSig) - a.requestedBlocks = a.requestedBlocks[1:] + a.requested = a.requested[1:] return firstSig, bts, bsn, true } - a.requestedBlocks = a.requestedBlocks[1:] + a.requested = a.requested[1:] return firstSig, bts, nil, true } return proto.BlockID{}, nil, nil, false @@ -70,24 +70,25 @@ func (a *OrderedBlocks) Add(sig proto.BlockID) bool { if _, ok := a.blocks[sig]; ok { return false } - a.requestedBlocks = append(a.requestedBlocks, sig) + a.requested = append(a.requested, sig) a.blocks[sig] = nil a.snapshots[sig] = nil return true } func (a *OrderedBlocks) RequestedCount() int { - return len(a.requestedBlocks) + return len(a.requested) } // blocks count available for pop func (a *OrderedBlocks) ReceivedCount(isLightNode bool) int { - for i, sig := range a.requestedBlocks { - if isLightNode && (a.blocks[sig] == nil || a.snapshots[sig] == nil) { + for i, sig := range a.requested { + blockIsNil := a.blocks[sig] == nil + if isLightNode && (blockIsNil || a.snapshots[sig] == nil) { return i - } else if !isLightNode && a.blocks[sig] == nil { + } else if !isLightNode && blockIsNil { return i } } - return len(a.requestedBlocks) + return len(a.requested) } diff --git a/pkg/node/actions_by_type.go b/pkg/node/actions_by_type.go index 3b95c7b41..d6d3dbee2 100644 --- a/pkg/node/actions_by_type.go +++ b/pkg/node/actions_by_type.go @@ -4,7 +4,6 @@ import ( "math/big" "reflect" - "github.com/pkg/errors" "go.uber.org/zap" protobuf "google.golang.org/protobuf/proto" @@ -181,7 +180,7 @@ func MicroBlockRequestAction( if err != nil { return nil, err } - micro, ok := services.MicroBlockCache.Get(blockID) + micro, ok := services.MicroBlockCache.GetBlock(blockID) if ok { _ = extension.NewPeerExtension(mess.ID, services.Scheme).SendMicroBlock(micro) } @@ -258,7 +257,8 @@ func PBTransactionAction(_ services.Services, mess peer.ProtoMessage, fsm *fsm.F } func MicroSnapshotRequestAction(services services.Services, mess peer.ProtoMessage, _ *fsm.FSM) (fsm.Async, error) { - blockID, err := proto.NewBlockIDFromBytes(mess.Message.(*proto.MicroBlockSnapshotRequestMessage).BlockIDBytes) + blockIDBytes := mess.Message.(*proto.MicroBlockSnapshotRequestMessage).BlockIDBytes + blockID, err := proto.NewBlockIDFromBytes(blockIDBytes) if err != nil { return nil, err } @@ -270,7 +270,7 @@ func MicroSnapshotRequestAction(services services.Services, mess peer.ProtoMessa } sProto := g.MicroBlockSnapshot{ Snapshots: snapshotProto, - TotalBlockId: mess.Message.(*proto.MicroBlockSnapshotRequestMessage).BlockIDBytes, + TotalBlockId: blockIDBytes, } bsmBytes, errMarshall := protobuf.Marshal(&sProto) if errMarshall != nil { @@ -283,7 +283,8 @@ func MicroSnapshotRequestAction(services services.Services, mess peer.ProtoMessa } func GetSnapshotAction(services services.Services, mess peer.ProtoMessage, _ *fsm.FSM) (fsm.Async, error) { - h, err := services.State.BlockIDToHeight(mess.Message.(*proto.GetBlockSnapshotMessage).BlockID) + blockID := mess.Message.(*proto.GetBlockSnapshotMessage).BlockID + h, err := services.State.BlockIDToHeight(blockID) if err != nil { return nil, err } @@ -297,7 +298,7 @@ func GetSnapshotAction(services services.Services, mess peer.ProtoMessage, _ *fs } sProto := g.BlockSnapshot{ Snapshots: snapshotProto, - BlockId: mess.Message.(*proto.GetBlockSnapshotMessage).BlockID.Bytes(), + BlockId: blockID.Bytes(), } bsmBytes, err := protobuf.Marshal(&sProto) if err != nil { @@ -309,12 +310,9 @@ func GetSnapshotAction(services services.Services, mess peer.ProtoMessage, _ *fs } func BlockSnapshotAction(services services.Services, mess peer.ProtoMessage, fsm *fsm.FSM) (fsm.Async, error) { - m, ok := mess.Message.(*proto.BlockSnapshotMessage) - if !ok { - return nil, errors.New("Message is not BlockSnapshot") - } protoMess := g.BlockSnapshot{} - if err := protobuf.Unmarshal(m.Bytes, &protoMess); err != nil { + if err := protoMess.UnmarshalVT(mess.Message.(*proto.BlockSnapshotMessage).Bytes); err != nil { + zap.S().Named(logging.NetworkNamespace).Debugf("Failed to deserialize block snapshot: %v", err) return nil, err } blockID, err := proto.NewBlockIDFromBytes(protoMess.BlockId) @@ -329,12 +327,9 @@ func BlockSnapshotAction(services services.Services, mess peer.ProtoMessage, fsm } func MicroBlockSnapshotAction(services services.Services, mess peer.ProtoMessage, fsm *fsm.FSM) (fsm.Async, error) { - m, ok := mess.Message.(*proto.MicroBlockSnapshotMessage) - if !ok { - return nil, errors.New("Message is not MicroBlockSnapshotMessage") - } protoMess := g.MicroBlockSnapshot{} - if err := protobuf.Unmarshal(m.Bytes, &protoMess); err != nil { + if err := protoMess.UnmarshalVT(mess.Message.(*proto.MicroBlockSnapshotMessage).Bytes); err != nil { + zap.S().Named(logging.NetworkNamespace).Debugf("Failed to deserialize micro block snapshot: %v", err) return nil, err } blockID, err := proto.NewBlockIDFromBytes(protoMess.TotalBlockId) diff --git a/pkg/node/blocks_applier/blocks_applier.go b/pkg/node/blocks_applier/blocks_applier.go index 141b0876f..95d540ab4 100644 --- a/pkg/node/blocks_applier/blocks_applier.go +++ b/pkg/node/blocks_applier/blocks_applier.go @@ -39,6 +39,7 @@ func (a *innerBlocksApplier) apply( //nolint:gocognit storage innerState, blocks []*proto.Block, snapshots []*proto.BlockSnapshot, + isLightNode bool, ) (proto.Height, error) { if len(blocks) == 0 { return 0, errors.New("empty blocks") @@ -102,7 +103,7 @@ func (a *innerBlocksApplier) apply( //nolint:gocognit // save previously added blocks. If new firstBlock failed to add, then return them back var rollbackBlocks []*proto.Block var rollbackBlocksSnapshots []*proto.BlockSnapshot - if snapshots != nil { + if isLightNode { rollbackBlocks, rollbackBlocksSnapshots, err = a.getRollbackBlocksAndSnapshots(storage, deltaHeight, parentHeight) if err != nil { return 0, err @@ -122,9 +123,9 @@ func (a *innerBlocksApplier) apply( //nolint:gocognit _, err = storage.AddDeserializedBlocks(blocks, snapshots) if err != nil { // return back saved blocks - _, err2 := storage.AddDeserializedBlocks(rollbackBlocks, rollbackBlocksSnapshots) - if err2 != nil { - return 0, errors.Wrap(err2, "failed rollback deserialized blocks") + _, errDeserialized := storage.AddDeserializedBlocks(rollbackBlocks, rollbackBlocksSnapshots) + if errDeserialized != nil { + return 0, errors.Wrap(errDeserialized, "failed rollback deserialized blocks") } return 0, errors.Wrapf(err, "failed add deserialized blocks, first block id %s", firstBlock.BlockID().String()) } @@ -174,6 +175,7 @@ func (a *innerBlocksApplier) applyMicro( storage innerState, block *proto.Block, snapshot *proto.BlockSnapshot, + isLightNode bool, ) (proto.Height, error) { _, err := storage.Block(block.BlockID()) if err == nil { @@ -201,7 +203,7 @@ func (a *innerBlocksApplier) applyMicro( return 0, errors.Wrapf(err, "failed to get current block by height %d", currentHeight) } var currentSnapshotsToApply []*proto.BlockSnapshot - if snapshot != nil { + if isLightNode { curSnapshot, errSAT := storage.SnapshotsAtHeight(currentHeight) if errSAT != nil { return 0, errSAT @@ -252,16 +254,18 @@ func (a *BlocksApplier) Apply( state state.State, blocks []*proto.Block, snapshots []*proto.BlockSnapshot, + isLightNode bool, ) (proto.Height, error) { - return a.inner.apply(state, blocks, snapshots) + return a.inner.apply(state, blocks, snapshots, isLightNode) } func (a *BlocksApplier) ApplyMicro( state state.State, block *proto.Block, snapshot *proto.BlockSnapshot, + isLightNode bool, ) (proto.Height, error) { - return a.inner.applyMicro(state, block, snapshot) + return a.inner.applyMicro(state, block, snapshot, isLightNode) } func calcMultipleScore(blocks []*proto.Block) (*big.Int, error) { diff --git a/pkg/node/blocks_applier/blocks_applier_test.go b/pkg/node/blocks_applier/blocks_applier_test.go index b811e179b..70ae84c25 100644 --- a/pkg/node/blocks_applier/blocks_applier_test.go +++ b/pkg/node/blocks_applier/blocks_applier_test.go @@ -50,7 +50,7 @@ func TestApply_ValidBlockWithRollback(t *testing.T) { require.NoError(t, err) ba := innerBlocksApplier{} - height, err := ba.apply(mockState, []*proto.Block{block2}, nil) + height, err := ba.apply(mockState, []*proto.Block{block2}, nil, false) require.NoError(t, err) require.EqualValues(t, 2, height) newBlock, _ := mockState.BlockByHeight(2) @@ -103,7 +103,7 @@ func TestApply_InvalidBlockWithRollback(t *testing.T) { stateMock.EXPECT().AddDeserializedBlocks([]*proto.Block{block1}, nil).Return(nil, nil) ba := innerBlocksApplier{} - _, err := ba.apply(stateMock, []*proto.Block{block2}, nil) + _, err := ba.apply(stateMock, []*proto.Block{block2}, nil, false) require.NotNil(t, err) require.Equal(t, "failed add deserialized blocks, first block id sV8beveiVKCiUn9BGZRgZj7V5tRRWPMRj1V9WWzKWnigtfQyZ2eErVXHi7vyGXj5hPuaxF9sGxowZr5XuD4UAwW: error message", err.Error()) } diff --git a/pkg/node/blocks_applier/node_mocks.go b/pkg/node/blocks_applier/node_mocks.go index d29e33e56..16b5884c9 100644 --- a/pkg/node/blocks_applier/node_mocks.go +++ b/pkg/node/blocks_applier/node_mocks.go @@ -118,6 +118,7 @@ func (a *MockStateManager) RollbackToHeight(height uint64) error { block := a.state[len(a.state)-1] a.state = a.state[:len(a.state)-1] delete(a.blockIDToHeight, block.BlockID()) + a.snapshots = a.snapshots[:len(a.snapshots)-1] } return nil } @@ -283,6 +284,9 @@ func (a *MockStateManager) AddDeserializedBlocks( ) (*proto.Block, error) { var out *proto.Block var err error + if snapshots != nil && (len(blocks) != len(snapshots)) { + panic("the numbers of snapshots doesn't match the number of blocks") + } for i, b := range blocks { if out, err = a.AddDeserializedBlock(b); err != nil { return nil, err diff --git a/pkg/node/fsm/fsm.go b/pkg/node/fsm/fsm.go index 8d86eedff..90b838b53 100644 --- a/pkg/node/fsm/fsm.go +++ b/pkg/node/fsm/fsm.go @@ -27,8 +27,18 @@ type Async []tasks.Task type BlocksApplier interface { BlockExists(state storage.State, block *proto.Block) (bool, error) - Apply(state storage.State, block []*proto.Block, snapshots []*proto.BlockSnapshot) (proto.Height, error) - ApplyMicro(state storage.State, block *proto.Block, snapshots *proto.BlockSnapshot) (proto.Height, error) + Apply( + state storage.State, + block []*proto.Block, + snapshots []*proto.BlockSnapshot, + isLightNode bool, + ) (proto.Height, error) + ApplyMicro( + state storage.State, + block *proto.Block, + snapshots *proto.BlockSnapshot, + isLightNode bool, + ) (proto.Height, error) } type BaseInfo struct { diff --git a/pkg/node/fsm/ng_state.go b/pkg/node/fsm/ng_state.go index 9928b2e76..976bc3040 100644 --- a/pkg/node/fsm/ng_state.go +++ b/pkg/node/fsm/ng_state.go @@ -2,8 +2,6 @@ package fsm import ( "context" - "time" - "github.com/pkg/errors" "github.com/qmuntal/stateless" "go.uber.org/zap" @@ -64,24 +62,6 @@ func (a *NGState) Task(task tasks.AsyncTask) (State, Async, error) { "unexpected type %T, expected 'tasks.MineMicroTaskData'", task.Data)) } return a.mineMicro(t.Block, t.Limits, t.KeyPair, t.Vrf) - case tasks.SnapshotTimeout: - t, ok := task.Data.(tasks.SnapshotTimeoutTaskData) - if !ok { - return a, nil, a.Errorf(errors.Errorf( - "unexpected type %T, expected 'tasks.SnapshotTimeoutTaskData'", task.Data)) - } - switch t.SnapshotTaskType { - case tasks.BlockSnapshot: - a.blockWaitingForSnapshot = nil - return a, nil, a.Errorf(errors.Errorf( - "failed to get snapshot for block '%s' - timeout", t.BlockID)) - case tasks.MicroBlockSnapshot: - a.microBlockWaitingForSnapshot = nil - return a, nil, a.Errorf(errors.Errorf( - "failed to get snapshot for micro block '%s' - timeout", t.BlockID)) - default: - return a, nil, a.Errorf(errors.New("undefined Snapshot Task type")) - } default: return a, nil, a.Errorf(errors.Errorf( "unexpected internal task '%d' with data '%+v' received by %s State", @@ -112,7 +92,12 @@ func (a *NGState) rollbackToStateFromCache(blockFromCache *proto.Block) error { return errors.Wrapf(err, "failed to rollback to parent block '%s' of cached block '%s'", previousBlockID.String(), blockFromCache.ID.String()) } - _, err = a.baseInfo.blocksApplier.Apply(a.baseInfo.storage, []*proto.Block{blockFromCache}, nil) + _, err = a.baseInfo.blocksApplier.Apply( + a.baseInfo.storage, + []*proto.Block{blockFromCache}, + nil, + a.baseInfo.enableLightMode, + ) if err != nil { return errors.Wrapf(err, "failed to apply cached block %q", blockFromCache.ID.String()) } @@ -135,6 +120,7 @@ func (a *NGState) rollbackToStateFromCacheInLightNode(parentID proto.BlockID) er a.baseInfo.storage, []*proto.Block{blockFromCache}, []*proto.BlockSnapshot{snapshotFromCache}, + a.baseInfo.enableLightMode, ) if err != nil { return errors.Wrapf(err, "failed to apply cached block %q", blockFromCache.ID.String()) @@ -144,6 +130,12 @@ func (a *NGState) rollbackToStateFromCacheInLightNode(parentID proto.BlockID) er } func (a *NGState) Block(peer peer.Peer, block *proto.Block) (State, Async, error) { + if a.blockWaitingForSnapshot != nil { + return a, nil, a.Errorf(errors.Errorf( + "skip block %s, waiting snapshot for block %s", + block.BlockID().String(), + a.blockWaitingForSnapshot.BlockID().String())) + } ok, err := a.baseInfo.blocksApplier.BlockExists(a.baseInfo.storage, block) if err != nil { return a, nil, a.Errorf(errors.Wrapf(err, "peer '%s'", peer.ID())) @@ -180,9 +172,14 @@ func (a *NGState) Block(peer peer.Peer, block *proto.Block) (State, Async, error a.blockWaitingForSnapshot = block pe := extension.NewPeerExtension(peer, a.baseInfo.scheme) pe.AskBlockSnapshot(block.BlockID()) - return a, tasks.Tasks(tasks.NewSnapshotTimeoutTask(time.Minute, block.BlockID(), tasks.BlockSnapshot)), nil + return a, nil, nil } - _, err = a.baseInfo.blocksApplier.Apply(a.baseInfo.storage, []*proto.Block{block}, nil) + _, err = a.baseInfo.blocksApplier.Apply( + a.baseInfo.storage, + []*proto.Block{block}, + nil, + a.baseInfo.enableLightMode, + ) if err != nil { return a, nil, a.Errorf(errors.Wrapf(err, "failed to apply block %s", block.BlockID())) } @@ -206,13 +203,14 @@ func (a *NGState) BlockSnapshot( } if a.blockWaitingForSnapshot.BlockID() != blockID { return a, nil, a.Errorf( - errors.Errorf("New snapshot doesn't match with block %s", a.blockWaitingForSnapshot.BlockID())) + errors.Errorf("new snapshot doesn't match with block %s", a.blockWaitingForSnapshot.BlockID())) } _, err := a.baseInfo.blocksApplier.Apply( a.baseInfo.storage, []*proto.Block{a.blockWaitingForSnapshot}, []*proto.BlockSnapshot{&snapshot}, + a.baseInfo.enableLightMode, ) if err != nil { // metrics.FSMKeyBlockDeclined("ng", block, err) @@ -239,7 +237,12 @@ func (a *NGState) MinedBlock( metrics.FSMKeyBlockGenerated("ng", block) err := a.baseInfo.storage.Map(func(state state.NonThreadSafeState) error { var err error - _, err = a.baseInfo.blocksApplier.Apply(state, []*proto.Block{block}, nil) + _, err = a.baseInfo.blocksApplier.Apply( + state, + []*proto.Block{block}, + nil, + a.baseInfo.enableLightMode, + ) return err }) if err != nil { @@ -262,6 +265,12 @@ func (a *NGState) MinedBlock( } func (a *NGState) MicroBlock(p peer.Peer, micro *proto.MicroBlock) (State, Async, error) { + if a.microBlockWaitingForSnapshot != nil { + return a, nil, a.Errorf(errors.Errorf( + "skip micro block %s, waiting snapshot for micro block %s", + micro.TotalBlockID.String(), + a.microBlockWaitingForSnapshot.TotalBlockID.String())) + } metrics.FSMMicroBlockReceived("ng", micro, p.Handshake().NodeName) if !a.baseInfo.enableLightMode { block, err := a.checkAndAppendMicroBlock(micro, nil) // the TopBlock() is used here @@ -273,12 +282,11 @@ func (a *NGState) MicroBlock(p peer.Peer, micro *proto.MicroBlock) (State, Async "[%s] Received microblock '%s' (referencing '%s') successfully applied to state", a, block.BlockID(), micro.Reference, ) - a.baseInfo.MicroBlockCache.Add(block.BlockID(), micro) + a.baseInfo.MicroBlockCache.AddMicroBlockWithSnapshot(block.BlockID(), micro, nil) a.blocksCache.AddBlockState(block) } a.microBlockWaitingForSnapshot = micro - tasks.Tasks(tasks.NewSnapshotTimeoutTask(time.Minute, micro.TotalBlockID, tasks.MicroBlockSnapshot)) return a, nil, nil } @@ -303,8 +311,7 @@ func (a *NGState) MicroBlockSnapshot( zap.S().Named(logging.FSMNamespace).Debugf( "[%s] Received snapshot for microblock '%s' successfully applied to state", a, block.BlockID(), ) - a.baseInfo.MicroBlockCache.Add(block.BlockID(), a.microBlockWaitingForSnapshot) - a.baseInfo.MicroBlockCache.AddSnapshot(block.BlockID(), &snapshot) + a.baseInfo.MicroBlockCache.AddMicroBlockWithSnapshot(block.BlockID(), a.microBlockWaitingForSnapshot, &snapshot) a.blocksCache.AddBlockState(block) a.blocksCache.AddSnapshot(block.BlockID(), snapshot) a.baseInfo.scheduler.Reschedule() @@ -335,7 +342,7 @@ func (a *NGState) mineMicro( } metrics.FSMMicroBlockGenerated("ng", micro) err = a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { - _, er := a.baseInfo.blocksApplier.ApplyMicro(s, block, nil) + _, er := a.baseInfo.blocksApplier.ApplyMicro(s, block, nil, a.baseInfo.enableLightMode) return er }) if err != nil { @@ -361,7 +368,7 @@ func (a *NGState) mineMicro( return a, nil, a.Errorf(errors.Wrap(err, "failed to broadcast generated microblock")) } - a.baseInfo.MicroBlockCache.Add(block.BlockID(), micro) + a.baseInfo.MicroBlockCache.AddMicroBlockWithSnapshot(block.BlockID(), micro, nil) a.baseInfo.MicroBlockInvCache.Add(block.BlockID(), inv) return a, tasks.Tasks(tasks.NewMineMicroTask(a.baseInfo.microblockInterval, block, rest, keyPair, vrf)), nil @@ -442,7 +449,7 @@ func (a *NGState) checkAndAppendMicroBlock( snapshotsToApply = &topBlockSnapshots } err = a.baseInfo.storage.Map(func(state state.State) error { - _, er := a.baseInfo.blocksApplier.ApplyMicro(state, newBlock, snapshotsToApply) + _, er := a.baseInfo.blocksApplier.ApplyMicro(state, newBlock, snapshotsToApply, a.baseInfo.enableLightMode) return er }) if err != nil { diff --git a/pkg/node/fsm/sync_internal/internal.go b/pkg/node/fsm/sync_internal/internal.go index 64aca79bf..673aae87d 100644 --- a/pkg/node/fsm/sync_internal/internal.go +++ b/pkg/node/fsm/sync_internal/internal.go @@ -86,7 +86,7 @@ func (a Internal) Block(block *proto.Block) (Internal, error) { return a, nil } -func (a Internal) Snapshot(blockID proto.BlockID, snapshot *proto.BlockSnapshot) (Internal, error) { +func (a Internal) SetSnapshot(blockID proto.BlockID, snapshot *proto.BlockSnapshot) (Internal, error) { if !a.orderedBlocks.Contains(blockID) { return a, UnexpectedBlockErr } diff --git a/pkg/node/fsm/sync_state.go b/pkg/node/fsm/sync_state.go index dfcc17fe2..0e303aea0 100644 --- a/pkg/node/fsm/sync_state.go +++ b/pkg/node/fsm/sync_state.go @@ -75,20 +75,14 @@ func (a *SyncState) Transaction(p peer.Peer, t proto.Transaction) (State, Async, func (a *SyncState) StopSync() (State, Async, error) { _, blocks, snapshots, _ := a.internal.Blocks(noopWrapper{}) if len(blocks) > 0 { - var err error - if a.baseInfo.enableLightMode { - err = a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { - var errApply error - _, errApply = a.baseInfo.blocksApplier.Apply(s, blocks, snapshots) - return errApply - }) - } else { - err = a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { - var errApply error - _, errApply = a.baseInfo.blocksApplier.Apply(s, blocks, nil) - return errApply - }) + if !a.baseInfo.enableLightMode { + snapshots = nil // ensure that snapshots are emtpy } + err := a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { + var errApply error + _, errApply = a.baseInfo.blocksApplier.Apply(s, blocks, snapshots, a.baseInfo.enableLightMode) + return errApply + }) return newIdleState(a.baseInfo), nil, a.Errorf(err) } return newIdleState(a.baseInfo), nil, nil @@ -194,7 +188,7 @@ func (a *SyncState) BlockSnapshot( if !p.Equal(a.conf.peerSyncWith) { return a, nil, nil } - internal, err := a.internal.Snapshot(blockID, &snapshot) + internal, err := a.internal.SetSnapshot(blockID, &snapshot) if err != nil { return newSyncState(a.baseInfo, a.conf, internal), nil, a.Errorf(err) } @@ -206,7 +200,12 @@ func (a *SyncState) MinedBlock( ) (State, Async, error) { metrics.FSMKeyBlockGenerated("sync", block) zap.S().Named(logging.FSMNamespace).Infof("[Sync] New block '%s' mined", block.ID.String()) - _, err := a.baseInfo.blocksApplier.Apply(a.baseInfo.storage, []*proto.Block{block}, nil) + _, err := a.baseInfo.blocksApplier.Apply( + a.baseInfo.storage, + []*proto.Block{block}, + nil, + a.baseInfo.enableLightMode, + ) if err != nil { zap.S().Warnf("[Sync] Failed to apply mined block: %v", err) return a, nil, nil // We've failed to apply mined block, it's not an error @@ -252,20 +251,14 @@ func (a *SyncState) applyBlocksWithSnapshots( zap.S().Named(logging.FSMNamespace).Debug("[Sync] No blocks to apply") return newSyncState(baseInfo, conf, internal), nil, nil } - var err error - if baseInfo.enableLightMode { - err = a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { - var errApply error - _, errApply = a.baseInfo.blocksApplier.Apply(s, blocks, snapshots) - return errApply - }) - } else { - err = a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { - var errApply error - _, errApply = a.baseInfo.blocksApplier.Apply(s, blocks, nil) - return errApply - }) + if !a.baseInfo.enableLightMode { + snapshots = nil // ensure that snapshots are emtpy } + err := a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { + var errApply error + _, errApply = a.baseInfo.blocksApplier.Apply(s, blocks, snapshots, a.baseInfo.enableLightMode) + return errApply + }) if err != nil { if errs.IsValidationError(err) || errs.IsValidationError(errors.Cause(err)) { diff --git a/pkg/node/fsm/tasks/tasks.go b/pkg/node/fsm/tasks/tasks.go index 2397ea934..1a08caa72 100644 --- a/pkg/node/fsm/tasks/tasks.go +++ b/pkg/node/fsm/tasks/tasks.go @@ -15,7 +15,6 @@ const ( AskPeers MineMicro PersistComplete - SnapshotTimeout ) // SendAsyncTask sends task into channel with overflow check. @@ -174,53 +173,3 @@ func NewFuncTask(f func(ctx context.Context, output chan AsyncTask) error, taskT _type: taskType, } } - -type SnapshotTimeoutTaskType int - -const ( - BlockSnapshot SnapshotTimeoutTaskType = iota - MicroBlockSnapshot -) - -type SnapshotTimeoutTaskData struct { - BlockID proto.BlockID - SnapshotTaskType SnapshotTimeoutTaskType -} - -func (SnapshotTimeoutTaskData) taskDataMarker() {} - -type SnapshotTimeoutTask struct { - timeout time.Duration - SnapshotTimeoutTaskData SnapshotTimeoutTaskData -} - -func NewSnapshotTimeoutTask( - timeout time.Duration, - blockID proto.BlockID, - taskType SnapshotTimeoutTaskType, -) SnapshotTimeoutTask { - return SnapshotTimeoutTask{ - timeout: timeout, - SnapshotTimeoutTaskData: SnapshotTimeoutTaskData{ - BlockID: blockID, - SnapshotTaskType: taskType, - }, - } -} - -func (SnapshotTimeoutTask) Type() int { - return SnapshotTimeout -} - -func (a SnapshotTimeoutTask) Run(ctx context.Context, output chan AsyncTask) error { - select { - case <-ctx.Done(): - return ctx.Err() - case <-time.After(a.timeout): - SendAsyncTask(output, AsyncTask{ - TaskType: a.Type(), - Data: a.SnapshotTimeoutTaskData, - }) - } - return nil -} diff --git a/pkg/proto/proto.go b/pkg/proto/proto.go index e495b4019..de5684101 100644 --- a/pkg/proto/proto.go +++ b/pkg/proto/proto.go @@ -2059,6 +2059,20 @@ type MiningLimits struct { MaxTxsSizeInBytes int } +func buildHeader(body []byte, messID PeerMessageID) (Header, error) { + var h Header + h.Length = maxHeaderLength + uint32(len(body)) - headerChecksumLen + h.Magic = headerMagic + h.ContentID = messID + h.PayloadLength = uint32(len(body)) + dig, err := crypto.FastHash(body) + if err != nil { + return Header{}, err + } + copy(h.PayloadChecksum[:], dig[:headerChecksumLen]) + return h, nil +} + type GetBlockSnapshotMessage struct { BlockID BlockID } @@ -2095,18 +2109,10 @@ func (m *GetBlockSnapshotMessage) UnmarshalBinary(data []byte) error { func (m *GetBlockSnapshotMessage) MarshalBinary() ([]byte, error) { body := m.BlockID.Bytes() - - var h Header - h.Length = maxHeaderLength + uint32(len(body)) - headerChecksumLen - h.Magic = headerMagic - h.ContentID = ContentIDGetBlockSnapshot - h.PayloadLength = uint32(len(body)) - dig, err := crypto.FastHash(body) + h, err := buildHeader(body, ContentIDGetBlockSnapshot) if err != nil { return nil, err } - copy(h.PayloadChecksum[:], dig[:headerChecksumLen]) - hdr, err := h.MarshalBinary() if err != nil { return nil, err @@ -2161,16 +2167,10 @@ func (m *BlockSnapshotMessage) UnmarshalBinary(data []byte) error { func (m *BlockSnapshotMessage) MarshalBinary() ([]byte, error) { body := m.Bytes - var h Header - h.Length = maxHeaderLength + uint32(len(body)) - headerChecksumLen - h.Magic = headerMagic - h.ContentID = ContentIDBlockSnapshot - h.PayloadLength = uint32(len(body)) - dig, err := crypto.FastHash(body) + h, err := buildHeader(body, ContentIDBlockSnapshot) if err != nil { return nil, err } - copy(h.PayloadChecksum[:], dig[:headerChecksumLen]) hdr, err := h.MarshalBinary() if err != nil { @@ -2226,16 +2226,10 @@ func (m *MicroBlockSnapshotMessage) UnmarshalBinary(data []byte) error { func (m *MicroBlockSnapshotMessage) MarshalBinary() ([]byte, error) { body := m.Bytes - var h Header - h.Length = maxHeaderLength + uint32(len(body)) - headerChecksumLen - h.Magic = headerMagic - h.ContentID = ContentIDMicroBlockSnapshot - h.PayloadLength = uint32(len(body)) - dig, err := crypto.FastHash(body) + h, err := buildHeader(body, ContentIDMicroBlockSnapshot) if err != nil { return nil, err } - copy(h.PayloadChecksum[:], dig[:headerChecksumLen]) hdr, err := h.MarshalBinary() if err != nil { @@ -2282,16 +2276,10 @@ func (m *MicroBlockSnapshotRequestMessage) UnmarshalBinary(data []byte) error { func (m *MicroBlockSnapshotRequestMessage) MarshalBinary() ([]byte, error) { body := m.BlockIDBytes - var h Header - h.Length = maxHeaderLength + uint32(len(body)) - headerChecksumLen - h.Magic = headerMagic - h.ContentID = ContentIDGetBlockSnapshot - h.PayloadLength = uint32(len(body)) - dig, err := crypto.FastHash(body) + h, err := buildHeader(body, ContentIDMicroBlockSnapshotRequest) if err != nil { return nil, err } - copy(h.PayloadChecksum[:], dig[:headerChecksumLen]) hdr, err := h.MarshalBinary() if err != nil { diff --git a/pkg/proto/types.go b/pkg/proto/types.go index f877ebe2b..3c26625c7 100644 --- a/pkg/proto/types.go +++ b/pkg/proto/types.go @@ -4109,14 +4109,6 @@ type FieldsHashes struct { LeaseBalanceHash crypto.Digest } -func (s FieldsHashes) EqualWith(other FieldsHashes) bool { - return s.DataEntryHash == other.DataEntryHash && s.AccountScriptHash == other.AccountScriptHash && - s.AssetScriptHash == other.AssetScriptHash && s.LeaseStatusHash == other.LeaseStatusHash && - s.SponsorshipHash == other.SponsorshipHash && s.AliasesHash == other.AliasesHash && - s.WavesBalanceHash == other.WavesBalanceHash && s.AssetBalanceHash == other.AssetBalanceHash && - s.LeaseBalanceHash == other.LeaseBalanceHash -} - type fieldsHashesJS struct { DataEntryHash DigestWrapped `json:"dataEntryHash"` AccountScriptHash DigestWrapped `json:"accountScriptHash"` diff --git a/pkg/services/services.go b/pkg/services/services.go index 3ab3e4229..a01194f6d 100644 --- a/pkg/services/services.go +++ b/pkg/services/services.go @@ -11,15 +11,24 @@ import ( type BlocksApplier interface { BlockExists(state state.State, block *proto.Block) (bool, error) - Apply(state state.State, block []*proto.Block, snapshots []*proto.BlockSnapshot) (proto.Height, error) - ApplyMicro(state state.State, block *proto.Block, snapshots *proto.BlockSnapshot) (proto.Height, error) + Apply( + state state.State, + block []*proto.Block, + snapshots []*proto.BlockSnapshot, + isLightNode bool, + ) (proto.Height, error) + ApplyMicro( + state state.State, + block *proto.Block, + snapshots *proto.BlockSnapshot, + isLightNode bool, + ) (proto.Height, error) } type MicroBlockCache interface { - Add(blockID proto.BlockID, micro *proto.MicroBlock) - Get(proto.BlockID) (*proto.MicroBlock, bool) - AddSnapshot(blockID proto.BlockID, snapshot *proto.BlockSnapshot) - GetSnapshot(proto.BlockID) (*proto.BlockSnapshot, bool) + AddMicroBlockWithSnapshot(blockID proto.BlockID, micro *proto.MicroBlock, snapshot *proto.BlockSnapshot) + GetBlock(sig proto.BlockID) (*proto.MicroBlock, bool) + GetSnapshot(sig proto.BlockID) (*proto.BlockSnapshot, bool) } type MicroBlockInvCache interface { diff --git a/pkg/state/address_transactions_test.go b/pkg/state/address_transactions_test.go index ffd2e1f41..cf6858ef1 100644 --- a/pkg/state/address_transactions_test.go +++ b/pkg/state/address_transactions_test.go @@ -13,7 +13,7 @@ import ( func testIterImpl(t *testing.T, params StateParams) { dataDir := t.TempDir() - st, err := NewState(dataDir, true, params, settings.MainNetSettings) + st, err := NewState(dataDir, true, params, settings.MainNetSettings, false) require.NoError(t, err) t.Cleanup(func() { diff --git a/pkg/state/api.go b/pkg/state/api.go index 3ed8c4c31..27488f299 100644 --- a/pkg/state/api.go +++ b/pkg/state/api.go @@ -200,8 +200,14 @@ type State interface { // and state will try to sync and use it in this case. // params are state parameters (see below). // settings are blockchain settings (settings.MainNetSettings, settings.TestNetSettings or custom settings). -func NewState(dataDir string, amend bool, params StateParams, settings *settings.BlockchainSettings) (State, error) { - s, err := newStateManager(dataDir, amend, params, settings) +func NewState( + dataDir string, + amend bool, + params StateParams, + settings *settings.BlockchainSettings, + enableLightNode bool, +) (State, error) { + s, err := newStateManager(dataDir, amend, params, settings, enableLightNode) if err != nil { return nil, errors.Wrap(err, "failed to create new state instance") } diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 5b7b940b9..9bc10b03a 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -616,45 +616,32 @@ func (a *txAppender) applySnapshotsInLightNode( params *appendBlockParams, stateHash crypto.Digest, hasher *txSnapshotHasher, -) error { +) (*proto.BlockSnapshot, crypto.Digest, error) { blockInfo, errBlockInfo := a.currentBlockInfo() if errBlockInfo != nil { - return errBlockInfo + return nil, crypto.Digest{}, errBlockInfo } for i, txs := range params.snapshot.TxSnapshots { txID, idErr := params.transactions[i].GetID(a.settings.AddressSchemeCharacter) if idErr != nil { - return idErr + return nil, crypto.Digest{}, idErr } if len(txs) == 0 { // sanity check - return errors.Errorf("snapshot of txID %q cannot be empty", base58.Encode(txID)) + return nil, crypto.Digest{}, errors.Errorf("snapshot of txID %q cannot be empty", base58.Encode(txID)) } - - for _, snapshot := range txs { - if errApply := snapshot.Apply(a.txHandler.sa); errApply != nil { - return errors.Wrap(errApply, "failed to apply tx snapshot") - } - } - txSh, shErr := calculateTxSnapshotStateHash(hasher, txID, blockInfo.Height, stateHash, txs) if shErr != nil { - return errors.Wrapf(shErr, "failed to calculate tx snapshot hash for txID %q at height %d", + return nil, crypto.Digest{}, errors.Wrapf(shErr, "failed to calculate tx snapshot hash for txID %q at height %d", base58.Encode(txID), blockInfo.Height, ) } stateHash = txSh + regSnapshots := txSnapshot{regular: txs} + if err := regSnapshots.Apply(a.txHandler.sa, params.transactions[i], false); err != nil { + return nil, crypto.Digest{}, errors.Wrap(err, "failed to apply tx snapshot") + } } - blockID := params.block.BlockID() - if ssErr := a.stor.snapshots.saveSnapshots(blockID, blockInfo.Height, *params.snapshot); ssErr != nil { - return ssErr - } - // clean up legacy state hash records with zero diffs - a.stor.balances.filterZeroDiffsSHOut(blockID) - // TODO: check snapshot hash with the block snapshot hash if it exists - if shErr := a.stor.stateHashes.saveSnapshotStateHash(stateHash, blockInfo.Height, blockID); shErr != nil { - return errors.Wrapf(shErr, "failed to save block shasnpt hash at height %d", blockInfo.Height) - } - return nil + return params.snapshot, stateHash, nil } func (a *txAppender) appendTxs( @@ -662,26 +649,26 @@ func (a *txAppender) appendTxs( info *checkerInfo, stateHash crypto.Digest, hasher *txSnapshotHasher, -) error { +) (*proto.BlockSnapshot, crypto.Digest, error) { blockInfo, errBlockInfo := a.currentBlockInfo() if errBlockInfo != nil { - return errBlockInfo + return nil, crypto.Digest{}, errBlockInfo } blockV5Activated, err := a.stor.features.newestIsActivated(int16(settings.BlockV5)) if err != nil { - return err + return nil, crypto.Digest{}, err } consensusImprovementsActivated, err := a.stor.features.newestIsActivated(int16(settings.ConsensusImprovements)) if err != nil { - return err + return nil, crypto.Digest{}, err } blockRewardDistributionActivated, err := a.stor.features.newestIsActivated(int16(settings.BlockRewardDistribution)) if err != nil { - return err + return nil, crypto.Digest{}, err } invokeExpressionActivated, err := a.stor.features.newestIsActivated(int16(settings.InvokeExpression)) if err != nil { - return err + return nil, crypto.Digest{}, err } // Check and append transactions. var bs proto.BlockSnapshot @@ -704,37 +691,27 @@ func (a *txAppender) appendTxs( } txSnapshots, errAppendTx := a.appendTx(tx, appendTxArgs) if errAppendTx != nil { - return errAppendTx + return nil, crypto.Digest{}, errAppendTx } bs.AppendTxSnapshot(txSnapshots.regular) txID, idErr := tx.GetID(a.settings.AddressSchemeCharacter) if idErr != nil { - return idErr + return nil, crypto.Digest{}, idErr } if len(txSnapshots.regular) == 0 { // sanity check - return errors.Errorf("snapshot of txID %q cannot be empty", base58.Encode(txID)) + return nil, crypto.Digest{}, errors.Errorf("snapshot of txID %q cannot be empty", base58.Encode(txID)) } txSh, shErr := calculateTxSnapshotStateHash(hasher, txID, blockInfo.Height, stateHash, txSnapshots.regular) if shErr != nil { - return errors.Wrapf(shErr, "failed to calculate tx snapshot hash for txID %q at height %d", + return nil, crypto.Digest{}, errors.Wrapf(shErr, "failed to calculate tx snapshot hash for txID %q at height %d", base58.Encode(txID), blockInfo.Height, ) } stateHash = txSh // update stateHash in order to accumulate state hashes into block snapshot hash } - blockID := params.block.BlockID() - if ssErr := a.stor.snapshots.saveSnapshots(blockID, blockInfo.Height, bs); ssErr != nil { - return ssErr - } - // clean up legacy state hash records with zero diffs - a.stor.balances.filterZeroDiffsSHOut(blockID) - // TODO: check snapshot hash with the block snapshot hash if it exists - if shErr := a.stor.stateHashes.saveSnapshotStateHash(stateHash, blockInfo.Height, blockID); shErr != nil { - return errors.Wrapf(shErr, "failed to save block shasnpt hash at height %d", blockInfo.Height) - } - return nil + return &bs, stateHash, nil } func calculateInitialSnapshotStateHash( @@ -848,16 +825,29 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { params.block.BlockID(), currentBlockHeight, ) } - + var blockSnapshots *proto.BlockSnapshot if params.snapshot != nil { - if err = a.applySnapshotsInLightNode(params, stateHash, hasher); err != nil { + blockSnapshots, stateHash, err = a.applySnapshotsInLightNode(params, stateHash, hasher) + if err != nil { return err } } else { - if err = a.appendTxs(params, checkerInfo, stateHash, hasher); err != nil { + blockSnapshots, stateHash, err = a.appendTxs(params, checkerInfo, stateHash, hasher) + if err != nil { return err } } + + blockID := params.block.BlockID() + if ssErr := a.stor.snapshots.saveSnapshots(blockID, blockInfo.Height, *blockSnapshots); ssErr != nil { + return ssErr + } + // clean up legacy state hash records with zero diffs + a.stor.balances.filterZeroDiffsSHOut(blockID) + // TODO: check snapshot hash with the block snapshot hash if it exists + if shErr := a.stor.stateHashes.saveSnapshotStateHash(stateHash, blockInfo.Height, blockID); shErr != nil { + return errors.Wrapf(shErr, "failed to save block shasnpt hash at height %d", blockInfo.Height) + } // Save fee distribution of this block. // This will be needed for createMinerAndRewardDiff() of next block due to NG. return a.blockDiffer.saveCurFeeDistr(params.block) diff --git a/pkg/state/invoke_applier_test.go b/pkg/state/invoke_applier_test.go index 730e6e7eb..cea500fbe 100644 --- a/pkg/state/invoke_applier_test.go +++ b/pkg/state/invoke_applier_test.go @@ -35,7 +35,7 @@ type invokeApplierTestObjects struct { } func createInvokeApplierTestObjects(t *testing.T) *invokeApplierTestObjects { - state, err := newStateManager(t.TempDir(), true, DefaultTestingStateParams(), settings.MainNetSettings) + state, err := newStateManager(t.TempDir(), true, DefaultTestingStateParams(), settings.MainNetSettings, false) assert.NoError(t, err, "newStateManager() failed") err = state.stateDB.addBlock(blockID0) assert.NoError(t, err) diff --git a/pkg/state/state.go b/pkg/state/state.go index 99702159e..8191c85bd 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -372,9 +372,18 @@ type stateManager struct { verificationGoroutinesNum int newBlocks *newBlocks + + enableLightNode bool } -func newStateManager(dataDir string, amend bool, params StateParams, settings *settings.BlockchainSettings) (*stateManager, error) { +func newStateManager( //nolint:funlen,gocognit + dataDir string, + amend bool, + params StateParams, + settings *settings.BlockchainSettings, + enableLightNode bool, +) (*stateManager, error) { + // TODO(anton): fix lint err := validateSettings(settings) if err != nil { return nil, err @@ -460,6 +469,7 @@ func newStateManager(dataDir string, amend bool, params StateParams, settings *s atx: atx, verificationGoroutinesNum: params.VerificationGoroutinesNum, newBlocks: newNewBlocks(rw, settings), + enableLightNode: enableLightNode, } // Set fields which depend on state. // Consensus validator is needed to check block headers. @@ -1191,6 +1201,9 @@ func (s *stateManager) AddDeserializedBlocks( blocks []*proto.Block, snapshots []*proto.BlockSnapshot, ) (*proto.Block, error) { + if s.enableLightNode && (len(blocks) != len(snapshots)) { + return nil, errors.New("the numbers of snapshots doesn't match the number of blocks") + } s.newBlocks.setNew(blocks) lastBlock, err := s.addBlocks(snapshots) if err != nil { @@ -1466,7 +1479,7 @@ func (s *stateManager) recalculateVotesAfterCappedRewardActivationInVotingPeriod } func getSnapshotByIndIfNotNil(snapshots []*proto.BlockSnapshot, pos int) *proto.BlockSnapshot { - if snapshots == nil { + if len(snapshots) != 0 { return nil } diff --git a/pkg/state/state_test.go b/pkg/state/state_test.go index 63babe104..da5b89d6b 100644 --- a/pkg/state/state_test.go +++ b/pkg/state/state_test.go @@ -35,7 +35,7 @@ func bigFromStr(s string) *big.Int { func newTestState(t *testing.T, amend bool, params StateParams, settings *settings.BlockchainSettings) State { dataDir := t.TempDir() - m, err := NewState(dataDir, amend, params, settings) + m, err := NewState(dataDir, amend, params, settings, false) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, m.Close(), "manager.Close() failed") @@ -45,7 +45,7 @@ func newTestState(t *testing.T, amend bool, params StateParams, settings *settin func newTestStateManager(t *testing.T, amend bool, params StateParams, settings *settings.BlockchainSettings) *stateManager { dataDir := t.TempDir() - m, err := newStateManager(dataDir, amend, params, settings) + m, err := newStateManager(dataDir, amend, params, settings, false) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, m.Close(), "manager.Close() failed") @@ -56,7 +56,7 @@ func newTestStateManager(t *testing.T, amend bool, params StateParams, settings func TestHandleAmendFlag(t *testing.T) { dataDir := t.TempDir() // first open with false amend - manager, err := newStateManager(dataDir, false, DefaultTestingStateParams(), settings.MainNetSettings) + manager, err := newStateManager(dataDir, false, DefaultTestingStateParams(), settings.MainNetSettings, false) assert.NoError(t, err, "newStateManager() failed") t.Cleanup(func() { assert.NoError(t, manager.Close(), "manager.Close() failed") @@ -65,18 +65,18 @@ func TestHandleAmendFlag(t *testing.T) { // open with true amend assert.NoError(t, manager.Close(), "manager.Close() failed") - manager, err = newStateManager(dataDir, true, DefaultTestingStateParams(), settings.MainNetSettings) + manager, err = newStateManager(dataDir, true, DefaultTestingStateParams(), settings.MainNetSettings, false) assert.NoError(t, err, "newStateManager() failed") assert.True(t, manager.stor.hs.amend) // open with false amend again. Result amend should be true assert.NoError(t, manager.Close(), "manager.Close() failed") - manager, err = newStateManager(dataDir, false, DefaultTestingStateParams(), settings.MainNetSettings) + manager, err = newStateManager(dataDir, false, DefaultTestingStateParams(), settings.MainNetSettings, false) assert.NoError(t, err, "newStateManager() failed") assert.True(t, manager.stor.hs.amend) // first open with true amend - newManager, err := newStateManager(t.TempDir(), true, DefaultTestingStateParams(), settings.MainNetSettings) + newManager, err := newStateManager(t.TempDir(), true, DefaultTestingStateParams(), settings.MainNetSettings, false) assert.NoError(t, err, "newStateManager() failed") t.Cleanup(func() { assert.NoError(t, newManager.Close(), "newManager.Close() failed") @@ -351,7 +351,7 @@ func TestStateManager_TopBlock(t *testing.T) { blocksPath, err := blocksPath() assert.NoError(t, err) dataDir := t.TempDir() - manager, err := newStateManager(dataDir, true, DefaultTestingStateParams(), settings.MainNetSettings) + manager, err := newStateManager(dataDir, true, DefaultTestingStateParams(), settings.MainNetSettings, false) assert.NoError(t, err, "newStateManager() failed") t.Cleanup(func() { @@ -382,7 +382,7 @@ func TestStateManager_TopBlock(t *testing.T) { // Test after closure. err = manager.Close() assert.NoError(t, err, "manager.Close() failed") - manager, err = newStateManager(dataDir, true, DefaultTestingStateParams(), settings.MainNetSettings) + manager, err = newStateManager(dataDir, true, DefaultTestingStateParams(), settings.MainNetSettings, false) assert.NoError(t, err, "newStateManager() failed") assert.Equal(t, correct, manager.TopBlock()) } From 9b944fd2da42cf818595b13caaccaa00fbae27a0 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Tue, 16 Jan 2024 16:33:38 +0300 Subject: [PATCH 095/139] fix tests --- pkg/node/blocks_applier/node_mocks.go | 4 +++- pkg/state/state.go | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/node/blocks_applier/node_mocks.go b/pkg/node/blocks_applier/node_mocks.go index 16b5884c9..847bab0de 100644 --- a/pkg/node/blocks_applier/node_mocks.go +++ b/pkg/node/blocks_applier/node_mocks.go @@ -118,7 +118,9 @@ func (a *MockStateManager) RollbackToHeight(height uint64) error { block := a.state[len(a.state)-1] a.state = a.state[:len(a.state)-1] delete(a.blockIDToHeight, block.BlockID()) - a.snapshots = a.snapshots[:len(a.snapshots)-1] + if len(a.snapshots) != 0 { + a.snapshots = a.snapshots[:len(a.snapshots)-1] + } } return nil } diff --git a/pkg/state/state.go b/pkg/state/state.go index 8191c85bd..438a8599a 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -1479,10 +1479,9 @@ func (s *stateManager) recalculateVotesAfterCappedRewardActivationInVotingPeriod } func getSnapshotByIndIfNotNil(snapshots []*proto.BlockSnapshot, pos int) *proto.BlockSnapshot { - if len(snapshots) != 0 { + if len(snapshots) == 0 { return nil } - return snapshots[pos] } From 9d038ddcd65796545c2ac5b9b832346f31edfd97 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Tue, 16 Jan 2024 23:21:52 +0300 Subject: [PATCH 096/139] fix itests --- pkg/libs/microblock_cache/microblock_cache.go | 6 +++--- pkg/node/actions_by_type.go | 5 ++--- pkg/node/fsm/ng_state.go | 3 ++- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkg/libs/microblock_cache/microblock_cache.go b/pkg/libs/microblock_cache/microblock_cache.go index 28a188d61..904bf5f57 100644 --- a/pkg/libs/microblock_cache/microblock_cache.go +++ b/pkg/libs/microblock_cache/microblock_cache.go @@ -27,7 +27,7 @@ func (a *MicroBlockCache) AddMicroBlockWithSnapshot( micro *proto.MicroBlock, snapshot *proto.BlockSnapshot, ) { - a.cache.Add2(blockID.Bytes(), microBlockWithSnapshot{ + a.cache.Add2(blockID.Bytes(), µBlockWithSnapshot{ microBlock: micro, snapshot: snapshot, }) @@ -38,7 +38,7 @@ func (a *MicroBlockCache) GetBlock(sig proto.BlockID) (*proto.MicroBlock, bool) if !ok { return nil, false } - return rs.(microBlockWithSnapshot).microBlock, true + return rs.(*microBlockWithSnapshot).microBlock, true } func (a *MicroBlockCache) GetSnapshot(sig proto.BlockID) (*proto.BlockSnapshot, bool) { @@ -46,7 +46,7 @@ func (a *MicroBlockCache) GetSnapshot(sig proto.BlockID) (*proto.BlockSnapshot, if !ok { return nil, false } - return rs.(microBlockWithSnapshot).snapshot, true + return rs.(*microBlockWithSnapshot).snapshot, true } type MicroblockInvCache struct { diff --git a/pkg/node/actions_by_type.go b/pkg/node/actions_by_type.go index d6d3dbee2..b9ce27acc 100644 --- a/pkg/node/actions_by_type.go +++ b/pkg/node/actions_by_type.go @@ -5,7 +5,6 @@ import ( "reflect" "go.uber.org/zap" - protobuf "google.golang.org/protobuf/proto" "github.com/wavesplatform/gowaves/pkg/crypto" g "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" @@ -272,7 +271,7 @@ func MicroSnapshotRequestAction(services services.Services, mess peer.ProtoMessa Snapshots: snapshotProto, TotalBlockId: blockIDBytes, } - bsmBytes, errMarshall := protobuf.Marshal(&sProto) + bsmBytes, errMarshall := sProto.MarshalVTStrict() if errMarshall != nil { return nil, errMarshall } @@ -300,7 +299,7 @@ func GetSnapshotAction(services services.Services, mess peer.ProtoMessage, _ *fs Snapshots: snapshotProto, BlockId: blockID.Bytes(), } - bsmBytes, err := protobuf.Marshal(&sProto) + bsmBytes, err := sProto.MarshalVTStrict() if err != nil { return nil, err } diff --git a/pkg/node/fsm/ng_state.go b/pkg/node/fsm/ng_state.go index 976bc3040..7529aaab9 100644 --- a/pkg/node/fsm/ng_state.go +++ b/pkg/node/fsm/ng_state.go @@ -282,8 +282,9 @@ func (a *NGState) MicroBlock(p peer.Peer, micro *proto.MicroBlock) (State, Async "[%s] Received microblock '%s' (referencing '%s') successfully applied to state", a, block.BlockID(), micro.Reference, ) - a.baseInfo.MicroBlockCache.AddMicroBlockWithSnapshot(block.BlockID(), micro, nil) + a.baseInfo.MicroBlockCache.AddMicroBlockWithSnapshot(block.BlockID(), micro, &proto.BlockSnapshot{}) a.blocksCache.AddBlockState(block) + return a, nil, nil } a.microBlockWaitingForSnapshot = micro From c0d0310f60dfcf554e6d46a1d37511ea2a1976af Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Thu, 25 Jan 2024 11:57:04 +0300 Subject: [PATCH 097/139] add add block with snpashots and new states for snapshots --- pkg/grpc/server/blockchain_api_test.go | 2 +- pkg/grpc/server/blocks_api_test.go | 6 +- pkg/mock/state.go | 62 ++-- pkg/node/blocks_applier/blocks_applier.go | 204 +++++++++---- .../blocks_applier/blocks_applier_test.go | 8 +- pkg/node/blocks_applier/node_mocks.go | 15 +- pkg/node/fsm/fsm.go | 26 +- pkg/node/fsm/fsm_common.go | 22 ++ pkg/node/fsm/halt_state.go | 4 + pkg/node/fsm/idle_state.go | 2 + pkg/node/fsm/ng_state.go | 178 +++--------- pkg/node/fsm/sync_state.go | 51 ++-- pkg/node/fsm/tasks/tasks.go | 51 ++++ pkg/node/fsm/wait_micro_snapshot.go | 232 +++++++++++++++ pkg/node/fsm/wait_snapshot_state.go | 166 +++++++++++ pkg/services/services.go | 12 +- pkg/state/address_transactions_test.go | 2 +- pkg/state/api.go | 5 +- pkg/state/appender.go | 140 ++++++--- pkg/state/state.go | 272 ++++++++++++++---- pkg/state/threadsafe_wrapper.go | 13 +- 21 files changed, 1130 insertions(+), 343 deletions(-) create mode 100644 pkg/node/fsm/wait_micro_snapshot.go create mode 100644 pkg/node/fsm/wait_snapshot_state.go diff --git a/pkg/grpc/server/blockchain_api_test.go b/pkg/grpc/server/blockchain_api_test.go index 588181d85..0785db6df 100644 --- a/pkg/grpc/server/blockchain_api_test.go +++ b/pkg/grpc/server/blockchain_api_test.go @@ -34,7 +34,7 @@ func TestGetBaseTarget(t *testing.T) { newTarget := 171657201 blocks, err := state.ReadMainnetBlocksToHeight(proto.Height(3)) assert.NoError(t, err) - _, err = st.AddDeserializedBlocks(blocks, nil) + _, err = st.AddDeserializedBlocks(blocks) assert.NoError(t, err) // Check new base target. res, err = cl.GetBaseTarget(ctx, &emptypb.Empty{}) diff --git a/pkg/grpc/server/blocks_api_test.go b/pkg/grpc/server/blocks_api_test.go index eaac2cded..14db94c18 100644 --- a/pkg/grpc/server/blocks_api_test.go +++ b/pkg/grpc/server/blocks_api_test.go @@ -48,7 +48,7 @@ func TestGetBlock(t *testing.T) { blockHeight := proto.Height(99) blocks, err := state.ReadMainnetBlocksToHeight(blockHeight) assert.NoError(t, err) - _, err = st.AddDeserializedBlocks(blocks, nil) + _, err = st.AddDeserializedBlocks(blocks) assert.NoError(t, err) // Retrieve expected block. correctBlockProto := blockFromState(t, blockHeight, st) @@ -95,7 +95,7 @@ func TestGetBlockRange(t *testing.T) { blockHeight := proto.Height(99) blocks, err := state.ReadMainnetBlocksToHeight(blockHeight) assert.NoError(t, err) - _, err = st.AddDeserializedBlocks(blocks, nil) + _, err = st.AddDeserializedBlocks(blocks) assert.NoError(t, err) // With transactions. @@ -169,7 +169,7 @@ func TestGetCurrentHeight(t *testing.T) { blockHeight := proto.Height(99) blocks, err := state.ReadMainnetBlocksToHeight(blockHeight) assert.NoError(t, err) - _, err = st.AddDeserializedBlocks(blocks, nil) + _, err = st.AddDeserializedBlocks(blocks) assert.NoError(t, err) res, err = cl.GetCurrentHeight(ctx, &emptypb.Empty{}) diff --git a/pkg/mock/state.go b/pkg/mock/state.go index 99b97a89a..9107d5f4c 100644 --- a/pkg/mock/state.go +++ b/pkg/mock/state.go @@ -1101,33 +1101,48 @@ func (mr *MockStateModifierMockRecorder) AddBlocks(blocks interface{}) *gomock.C } // AddDeserializedBlock mocks base method. -func (m *MockStateModifier) AddDeserializedBlock(block *proto.Block, snapshot *proto.BlockSnapshot) (*proto.Block, error) { +func (m *MockStateModifier) AddDeserializedBlock(block *proto.Block) (*proto.Block, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddDeserializedBlock", block, snapshot) + ret := m.ctrl.Call(m, "AddDeserializedBlock", block) ret0, _ := ret[0].(*proto.Block) ret1, _ := ret[1].(error) return ret0, ret1 } // AddDeserializedBlock indicates an expected call of AddDeserializedBlock. -func (mr *MockStateModifierMockRecorder) AddDeserializedBlock(block, snapshot interface{}) *gomock.Call { +func (mr *MockStateModifierMockRecorder) AddDeserializedBlock(block interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlock", reflect.TypeOf((*MockStateModifier)(nil).AddDeserializedBlock), block, snapshot) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlock", reflect.TypeOf((*MockStateModifier)(nil).AddDeserializedBlock), block) } // AddDeserializedBlocks mocks base method. -func (m *MockStateModifier) AddDeserializedBlocks(blocks []*proto.Block, snapshots []*proto.BlockSnapshot) (*proto.Block, error) { +func (m *MockStateModifier) AddDeserializedBlocks(blocks []*proto.Block) (*proto.Block, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddDeserializedBlocks", blocks, snapshots) + ret := m.ctrl.Call(m, "AddDeserializedBlocks", blocks) ret0, _ := ret[0].(*proto.Block) ret1, _ := ret[1].(error) return ret0, ret1 } // AddDeserializedBlocks indicates an expected call of AddDeserializedBlocks. -func (mr *MockStateModifierMockRecorder) AddDeserializedBlocks(blocks, snapshots interface{}) *gomock.Call { +func (mr *MockStateModifierMockRecorder) AddDeserializedBlocks(blocks interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlocks", reflect.TypeOf((*MockStateModifier)(nil).AddDeserializedBlocks), blocks, snapshots) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlocks", reflect.TypeOf((*MockStateModifier)(nil).AddDeserializedBlocks), blocks) +} + +// AddDeserializedBlocksWithSnapshots mocks base method. +func (m *MockStateModifier) AddDeserializedBlocksWithSnapshots(blocks []*proto.Block, snapshots []*proto.BlockSnapshot) (*proto.Block, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AddDeserializedBlocksWithSnapshots", blocks, snapshots) + ret0, _ := ret[0].(*proto.Block) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// AddDeserializedBlocksWithSnapshots indicates an expected call of AddDeserializedBlocksWithSnapshots. +func (mr *MockStateModifierMockRecorder) AddDeserializedBlocksWithSnapshots(blocks, snapshots interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlocksWithSnapshots", reflect.TypeOf((*MockStateModifier)(nil).AddDeserializedBlocksWithSnapshots), blocks, snapshots) } // Close mocks base method. @@ -1359,33 +1374,48 @@ func (mr *MockStateMockRecorder) AddBlocks(blocks interface{}) *gomock.Call { } // AddDeserializedBlock mocks base method. -func (m *MockState) AddDeserializedBlock(block *proto.Block, snapshot *proto.BlockSnapshot) (*proto.Block, error) { +func (m *MockState) AddDeserializedBlock(block *proto.Block) (*proto.Block, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddDeserializedBlock", block, snapshot) + ret := m.ctrl.Call(m, "AddDeserializedBlock", block) ret0, _ := ret[0].(*proto.Block) ret1, _ := ret[1].(error) return ret0, ret1 } // AddDeserializedBlock indicates an expected call of AddDeserializedBlock. -func (mr *MockStateMockRecorder) AddDeserializedBlock(block, snapshot interface{}) *gomock.Call { +func (mr *MockStateMockRecorder) AddDeserializedBlock(block interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlock", reflect.TypeOf((*MockState)(nil).AddDeserializedBlock), block, snapshot) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlock", reflect.TypeOf((*MockState)(nil).AddDeserializedBlock), block) } // AddDeserializedBlocks mocks base method. -func (m *MockState) AddDeserializedBlocks(blocks []*proto.Block, snapshots []*proto.BlockSnapshot) (*proto.Block, error) { +func (m *MockState) AddDeserializedBlocks(blocks []*proto.Block) (*proto.Block, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddDeserializedBlocks", blocks, snapshots) + ret := m.ctrl.Call(m, "AddDeserializedBlocks", blocks) ret0, _ := ret[0].(*proto.Block) ret1, _ := ret[1].(error) return ret0, ret1 } // AddDeserializedBlocks indicates an expected call of AddDeserializedBlocks. -func (mr *MockStateMockRecorder) AddDeserializedBlocks(blocks, snapshots interface{}) *gomock.Call { +func (mr *MockStateMockRecorder) AddDeserializedBlocks(blocks interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlocks", reflect.TypeOf((*MockState)(nil).AddDeserializedBlocks), blocks) +} + +// AddDeserializedBlocksWithSnapshots mocks base method. +func (m *MockState) AddDeserializedBlocksWithSnapshots(blocks []*proto.Block, snapshots []*proto.BlockSnapshot) (*proto.Block, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AddDeserializedBlocksWithSnapshots", blocks, snapshots) + ret0, _ := ret[0].(*proto.Block) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// AddDeserializedBlocksWithSnapshots indicates an expected call of AddDeserializedBlocksWithSnapshots. +func (mr *MockStateMockRecorder) AddDeserializedBlocksWithSnapshots(blocks, snapshots interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlocks", reflect.TypeOf((*MockState)(nil).AddDeserializedBlocks), blocks, snapshots) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDeserializedBlocksWithSnapshots", reflect.TypeOf((*MockState)(nil).AddDeserializedBlocksWithSnapshots), blocks, snapshots) } // AddrByAlias mocks base method. diff --git a/pkg/node/blocks_applier/blocks_applier.go b/pkg/node/blocks_applier/blocks_applier.go index 95d540ab4..a86af69a3 100644 --- a/pkg/node/blocks_applier/blocks_applier.go +++ b/pkg/node/blocks_applier/blocks_applier.go @@ -18,7 +18,8 @@ type innerState interface { Height() (proto.Height, error) ScoreAtHeight(height proto.Height) (*big.Int, error) BlockIDToHeight(blockID proto.BlockID) (proto.Height, error) - AddDeserializedBlocks(blocks []*proto.Block, snapshots []*proto.BlockSnapshot) (*proto.Block, error) + AddDeserializedBlocks(blocks []*proto.Block) (*proto.Block, error) + AddDeserializedBlocksWithSnapshots(blocks []*proto.Block, snapshots []*proto.BlockSnapshot) (*proto.Block, error) BlockByHeight(height proto.Height) (*proto.Block, error) RollbackToHeight(height proto.Height) error SnapshotsAtHeight(height proto.Height) (proto.BlockSnapshot, error) @@ -35,60 +36,122 @@ func (a *innerBlocksApplier) exists(storage innerState, block *proto.Block) (boo return false, err } -func (a *innerBlocksApplier) apply( //nolint:gocognit +func (a *innerBlocksApplier) apply( storage innerState, blocks []*proto.Block, - snapshots []*proto.BlockSnapshot, - isLightNode bool, ) (proto.Height, error) { if len(blocks) == 0 { return 0, errors.New("empty blocks") } + currentHeight, parentHeight, err := a.getParentAndCurrentHeight(storage, blocks) + if err != nil { + return 0, err + } + + // so, new blocks has higher score, try to apply it. + // Do we need rollback? + if parentHeight == currentHeight { + // no, don't rollback, just add blocks + _, err = storage.AddDeserializedBlocks(blocks) + if err != nil { + return 0, err + } + return currentHeight + proto.Height(len(blocks)), nil + } + + deltaHeight := currentHeight - parentHeight + if deltaHeight > maxRollbackDeltaHeight { // max number that we can rollback + return 0, errors.Errorf("can't apply new blocks, rollback more than 100 blocks, %d", deltaHeight) + } + + // save previously added blocks. If new firstBlock failed to add, then return them back + rollbackBlocks, err := a.getRollbackBlocks(storage, deltaHeight, parentHeight) + if err != nil { + return 0, err + } + + err = storage.RollbackToHeight(parentHeight) + if err != nil { + return 0, errors.Wrapf(err, "failed to rollback to height %d", parentHeight) + } + // applying new blocks + _, err = storage.AddDeserializedBlocks(blocks) + if err != nil { + // return back saved blocks + _, err2 := storage.AddDeserializedBlocks(rollbackBlocks) + if err2 != nil { + return 0, errors.Wrap(err2, "failed rollback deserialized blocks") + } + return 0, errors.Wrapf(err, "failed add deserialized blocks, first block id %s", blocks[0].BlockID().String()) + } + return parentHeight + proto.Height(len(blocks)), nil +} + +func (a *innerBlocksApplier) getParentAndCurrentHeight( + storage innerState, + blocks []*proto.Block, +) (proto.Height, proto.Height, error) { firstBlock := blocks[0] // check first block if exists _, err := storage.Block(firstBlock.BlockID()) if err == nil { - return 0, proto.NewInfoMsg(errors.Errorf("first block %s exists", firstBlock.BlockID().String())) + return 0, 0, proto.NewInfoMsg(errors.Errorf("first block %s exists", firstBlock.BlockID().String())) } if !state.IsNotFound(err) { - return 0, errors.Wrap(err, "unknown error") + return 0, 0, errors.Wrap(err, "unknown error") } currentHeight, err := storage.Height() if err != nil { - return 0, err + return 0, 0, err } // current score. Main idea is to find parent block, and check if score // of all passed blocks higher than currentScore. If yes, we can add blocks currentScore, err := storage.ScoreAtHeight(currentHeight) if err != nil { - return 0, err + return 0, 0, err } // try to find parent. If not - we can't add blocks, skip it parentHeight, err := storage.BlockIDToHeight(firstBlock.Parent) if err != nil { - return 0, proto.NewInfoMsg(errors.Wrapf(err, "failed get parent height, firstBlock id %s, for firstBlock %s", + return 0, 0, proto.NewInfoMsg(errors.Wrapf(err, "failed get parent height, firstBlock id %s, for firstBlock %s", firstBlock.Parent.String(), firstBlock.BlockID().String())) } // calculate score of all passed blocks forkScore, err := calcMultipleScore(blocks) if err != nil { - return 0, errors.Wrap(err, "failed calculate score of passed blocks") + return 0, 0, errors.Wrap(err, "failed calculate score of passed blocks") } parentScore, err := storage.ScoreAtHeight(parentHeight) if err != nil { - return 0, errors.Wrapf(err, "failed get score at %d", parentHeight) + return 0, 0, errors.Wrapf(err, "failed get score at %d", parentHeight) } cumulativeScore := forkScore.Add(forkScore, parentScore) if currentScore.Cmp(cumulativeScore) >= 0 { // current score is higher or the same as fork score - do not apply blocks - return 0, proto.NewInfoMsg(errors.Errorf("low fork score: current blockchain score (%s) is higher than or equal to fork's score (%s)", + return 0, 0, proto.NewInfoMsg(errors.Errorf( + "low fork score: current blockchain score (%s) is higher than or equal to fork's score (%s)", currentScore.String(), cumulativeScore.String())) } + return currentHeight, parentHeight, nil +} + +func (a *innerBlocksApplier) applyWithSnapshots( + storage innerState, + blocks []*proto.Block, + snapshots []*proto.BlockSnapshot, +) (proto.Height, error) { + if len(blocks) == 0 { + return 0, errors.New("empty blocks") + } + currentHeight, parentHeight, err := a.getParentAndCurrentHeight(storage, blocks) + if err != nil { + return 0, err + } // so, new blocks has higher score, try to apply it. // Do we need rollback? if parentHeight == currentHeight { // no, don't rollback, just add blocks - _, err = storage.AddDeserializedBlocks(blocks, snapshots) + _, err = storage.AddDeserializedBlocksWithSnapshots(blocks, snapshots) if err != nil { return 0, err } @@ -101,18 +164,9 @@ func (a *innerBlocksApplier) apply( //nolint:gocognit } // save previously added blocks. If new firstBlock failed to add, then return them back - var rollbackBlocks []*proto.Block - var rollbackBlocksSnapshots []*proto.BlockSnapshot - if isLightNode { - rollbackBlocks, rollbackBlocksSnapshots, err = a.getRollbackBlocksAndSnapshots(storage, deltaHeight, parentHeight) - if err != nil { - return 0, err - } - } else { - rollbackBlocks, err = a.getRollbackBlocks(storage, deltaHeight, parentHeight) - if err != nil { - return 0, err - } + rollbackBlocks, rollbackBlocksSnapshots, err := a.getRollbackBlocksAndSnapshots(storage, deltaHeight, parentHeight) + if err != nil { + return 0, err } err = storage.RollbackToHeight(parentHeight) @@ -120,14 +174,14 @@ func (a *innerBlocksApplier) apply( //nolint:gocognit return 0, errors.Wrapf(err, "failed to rollback to height %d", parentHeight) } // applying new blocks - _, err = storage.AddDeserializedBlocks(blocks, snapshots) + _, err = storage.AddDeserializedBlocksWithSnapshots(blocks, snapshots) if err != nil { // return back saved blocks - _, errDeserialized := storage.AddDeserializedBlocks(rollbackBlocks, rollbackBlocksSnapshots) + _, errDeserialized := storage.AddDeserializedBlocksWithSnapshots(rollbackBlocks, rollbackBlocksSnapshots) if errDeserialized != nil { return 0, errors.Wrap(errDeserialized, "failed rollback deserialized blocks") } - return 0, errors.Wrapf(err, "failed add deserialized blocks, first block id %s", firstBlock.BlockID().String()) + return 0, errors.Wrapf(err, "failed add deserialized blocks, first block id %s", blocks[0].BlockID().String()) } return parentHeight + proto.Height(len(blocks)), nil } @@ -174,8 +228,6 @@ func (a *innerBlocksApplier) getRollbackBlocks( func (a *innerBlocksApplier) applyMicro( storage innerState, block *proto.Block, - snapshot *proto.BlockSnapshot, - isLightNode bool, ) (proto.Height, error) { _, err := storage.Block(block.BlockID()) if err == nil { @@ -202,14 +254,60 @@ func (a *innerBlocksApplier) applyMicro( if err != nil { return 0, errors.Wrapf(err, "failed to get current block by height %d", currentHeight) } - var currentSnapshotsToApply []*proto.BlockSnapshot - if isLightNode { - curSnapshot, errSAT := storage.SnapshotsAtHeight(currentHeight) - if errSAT != nil { - return 0, errSAT + + err = storage.RollbackToHeight(parentHeight) + if err != nil { + return 0, errors.Wrapf(err, "failed to rollback to height %d", parentHeight) + } + + // applying new blocks + _, err = storage.AddDeserializedBlocks([]*proto.Block{block}) + if err != nil { + // return back saved blocks + _, err2 := storage.AddDeserializedBlocks([]*proto.Block{currentBlock}) + if err2 != nil { + return 0, errors.Wrap(err2, "failed rollback block") } - currentSnapshotsToApply = []*proto.BlockSnapshot{&curSnapshot} + return 0, errors.Wrapf(err, "failed apply new block '%s'", block.BlockID().String()) } + return currentHeight, nil +} + +func (a *innerBlocksApplier) applyMicroWithSnapshot( + storage innerState, + block *proto.Block, + snapshot *proto.BlockSnapshot, +) (proto.Height, error) { + _, err := storage.Block(block.BlockID()) + if err == nil { + return 0, errors.Errorf("block '%s' already exist", block.BlockID().String()) + } + if !state.IsNotFound(err) { + return 0, errors.Wrap(err, "unexpected error") + } + + currentHeight, err := storage.Height() + if err != nil { + return 0, err + } + parentHeight, err := storage.BlockIDToHeight(block.Parent) + if err != nil { + return 0, errors.Wrapf(err, "failed get height of parent block '%s'", block.Parent.String()) + } + + if currentHeight-parentHeight != 1 { + return 0, errors.Errorf("invalid parent height %d", parentHeight) + } + + currentBlock, err := storage.BlockByHeight(currentHeight) + if err != nil { + return 0, errors.Wrapf(err, "failed to get current block by height %d", currentHeight) + } + curSnapshot, errSAT := storage.SnapshotsAtHeight(currentHeight) + if errSAT != nil { + return 0, errSAT + } + currentSnapshotsToApply := []*proto.BlockSnapshot{&curSnapshot} err = storage.RollbackToHeight(parentHeight) if err != nil { @@ -217,19 +315,15 @@ func (a *innerBlocksApplier) applyMicro( } // applying new blocks - var snapshotToApply []*proto.BlockSnapshot - if snapshot != nil { - snapshotToApply = []*proto.BlockSnapshot{snapshot} - } - _, err = storage.AddDeserializedBlocks([]*proto.Block{block}, snapshotToApply) + _, err = storage.AddDeserializedBlocksWithSnapshots([]*proto.Block{block}, []*proto.BlockSnapshot{snapshot}) if err != nil { // return back saved blocks - _, err2 := storage.AddDeserializedBlocks( + _, errAdd := storage.AddDeserializedBlocksWithSnapshots( []*proto.Block{currentBlock}, currentSnapshotsToApply, ) - if err2 != nil { - return 0, errors.Wrap(err2, "failed rollback block") + if errAdd != nil { + return 0, errors.Wrap(errAdd, "failed rollback block") } return 0, errors.Wrapf(err, "failed apply new block '%s'", block.BlockID().String()) } @@ -253,19 +347,31 @@ func (a *BlocksApplier) BlockExists(state state.State, block *proto.Block) (bool func (a *BlocksApplier) Apply( state state.State, blocks []*proto.Block, - snapshots []*proto.BlockSnapshot, - isLightNode bool, ) (proto.Height, error) { - return a.inner.apply(state, blocks, snapshots, isLightNode) + return a.inner.apply(state, blocks) } func (a *BlocksApplier) ApplyMicro( state state.State, block *proto.Block, +) (proto.Height, error) { + return a.inner.applyMicro(state, block) +} + +func (a *BlocksApplier) ApplyWithSnapshots( + state state.State, + blocks []*proto.Block, + snapshots []*proto.BlockSnapshot, +) (proto.Height, error) { + return a.inner.applyWithSnapshots(state, blocks, snapshots) +} + +func (a *BlocksApplier) ApplyMicroWithSnapshots( + state state.State, + block *proto.Block, snapshot *proto.BlockSnapshot, - isLightNode bool, ) (proto.Height, error) { - return a.inner.applyMicro(state, block, snapshot, isLightNode) + return a.inner.applyMicroWithSnapshot(state, block, snapshot) } func calcMultipleScore(blocks []*proto.Block) (*big.Int, error) { diff --git a/pkg/node/blocks_applier/blocks_applier_test.go b/pkg/node/blocks_applier/blocks_applier_test.go index 70ae84c25..225bc4ead 100644 --- a/pkg/node/blocks_applier/blocks_applier_test.go +++ b/pkg/node/blocks_applier/blocks_applier_test.go @@ -50,7 +50,7 @@ func TestApply_ValidBlockWithRollback(t *testing.T) { require.NoError(t, err) ba := innerBlocksApplier{} - height, err := ba.apply(mockState, []*proto.Block{block2}, nil, false) + height, err := ba.apply(mockState, []*proto.Block{block2}) require.NoError(t, err) require.EqualValues(t, 2, height) newBlock, _ := mockState.BlockByHeight(2) @@ -98,12 +98,12 @@ func TestApply_InvalidBlockWithRollback(t *testing.T) { // rollback to first(genesis) block stateMock.EXPECT().RollbackToHeight(proto.Height(1)).Return(nil) // adding new blocks, and have error on applying - stateMock.EXPECT().AddDeserializedBlocks([]*proto.Block{block2}, nil).Return(nil, errors.New("error message")) + stateMock.EXPECT().AddDeserializedBlocks([]*proto.Block{block2}).Return(nil, errors.New("error message")) // return blocks - stateMock.EXPECT().AddDeserializedBlocks([]*proto.Block{block1}, nil).Return(nil, nil) + stateMock.EXPECT().AddDeserializedBlocks([]*proto.Block{block1}).Return(nil, nil) ba := innerBlocksApplier{} - _, err := ba.apply(stateMock, []*proto.Block{block2}, nil, false) + _, err := ba.apply(stateMock, []*proto.Block{block2}) require.NotNil(t, err) require.Equal(t, "failed add deserialized blocks, first block id sV8beveiVKCiUn9BGZRgZj7V5tRRWPMRj1V9WWzKWnigtfQyZ2eErVXHi7vyGXj5hPuaxF9sGxowZr5XuD4UAwW: error message", err.Error()) } diff --git a/pkg/node/blocks_applier/node_mocks.go b/pkg/node/blocks_applier/node_mocks.go index 847bab0de..ad16e6442 100644 --- a/pkg/node/blocks_applier/node_mocks.go +++ b/pkg/node/blocks_applier/node_mocks.go @@ -282,11 +282,24 @@ func (a *MockStateManager) AddDeserializedBlock(block *proto.Block) (*proto.Bloc func (a *MockStateManager) AddDeserializedBlocks( blocks []*proto.Block, +) (*proto.Block, error) { + var out *proto.Block + var err error + for _, b := range blocks { + if out, err = a.AddDeserializedBlock(b); err != nil { + return nil, err + } + } + return out, nil +} + +func (a *MockStateManager) AddDeserializedBlocksWithSnapshots( + blocks []*proto.Block, snapshots []*proto.BlockSnapshot, ) (*proto.Block, error) { var out *proto.Block var err error - if snapshots != nil && (len(blocks) != len(snapshots)) { + if len(blocks) != len(snapshots) { panic("the numbers of snapshots doesn't match the number of blocks") } for i, b := range blocks { diff --git a/pkg/node/fsm/fsm.go b/pkg/node/fsm/fsm.go index 90b838b53..cb3770283 100644 --- a/pkg/node/fsm/fsm.go +++ b/pkg/node/fsm/fsm.go @@ -30,14 +30,20 @@ type BlocksApplier interface { Apply( state storage.State, block []*proto.Block, - snapshots []*proto.BlockSnapshot, - isLightNode bool, ) (proto.Height, error) ApplyMicro( state storage.State, block *proto.Block, + ) (proto.Height, error) + ApplyWithSnapshots( + state storage.State, + block []*proto.Block, + snapshots []*proto.BlockSnapshot, + ) (proto.Height, error) + ApplyMicroWithSnapshots( + state storage.State, + block *proto.Block, snapshots *proto.BlockSnapshot, - isLightNode bool, ) (proto.Height, error) } @@ -91,12 +97,12 @@ func (a *BaseInfo) CleanUtx() { // States. const ( - IdleStateName = "Idle" - NGStateName = "NG" - NGLightStateName = "NGLight" - PersistStateName = "Persist" - SyncStateName = "Sync" - HaltStateName = "Halt" + IdleStateName = "Idle" + NGStateName = "NG" + WaitSnapshotStateName = "WaitSnapshotLight" + PersistStateName = "Persist" + SyncStateName = "Sync" + HaltStateName = "Halt" ) // Events. @@ -204,6 +210,8 @@ func NewFSM( initNGStateInFSM(state, fsm, info) initPersistStateInFSM(state, fsm, info) initSyncStateInFSM(state, fsm, info) + initWaitMicroSnapshotStateInFSM(state, fsm, info) + initWaitSnapshotStateInFSM(state, fsm, info) return &FSM{ fsm: fsm, diff --git a/pkg/node/fsm/fsm_common.go b/pkg/node/fsm/fsm_common.go index 6a18499e0..6b8fb0977 100644 --- a/pkg/node/fsm/fsm_common.go +++ b/pkg/node/fsm/fsm_common.go @@ -208,3 +208,25 @@ func validateEventArgs(event stateless.Trigger, args ...interface{}) { } } } + +func broadcastMicroBlockInv(info BaseInfo, inv *proto.MicroBlockInv) error { + invBts, err := inv.MarshalBinary() + if err != nil { + return errors.Wrapf(err, "failed to marshal binary '%T'", inv) + } + var ( + cnt int + msg = &proto.MicroBlockInvMessage{ + Body: invBts, + } + ) + info.peers.EachConnected(func(p peer.Peer, score *proto.Score) { + p.SendMessage(msg) + cnt++ + }) + info.invRequester.Add2Cache(inv.TotalBlockID.Bytes()) // prevent further unnecessary microblock request + zap.S().Named(logging.FSMNamespace).Debugf("Network message '%T' sent to %d peers: blockID='%s', ref='%s'", + msg, cnt, inv.TotalBlockID, inv.Reference, + ) + return nil +} diff --git a/pkg/node/fsm/halt_state.go b/pkg/node/fsm/halt_state.go index 3d048fdac..5a074fe82 100644 --- a/pkg/node/fsm/halt_state.go +++ b/pkg/node/fsm/halt_state.go @@ -55,6 +55,10 @@ func initHaltStateInFSM(_ *StateData, fsm *stateless.StateMachine, info BaseInfo proto.ContentIDPBMicroBlock, proto.ContentIDPBTransaction, proto.ContentIDGetBlockIds, + proto.ContentIDBlockSnapshot, + proto.ContentIDGetBlockSnapshot, + proto.ContentIDMicroBlockSnapshot, + proto.ContentIDMicroBlockSnapshotRequest, } fsm.Configure(HaltStateName). OnEntry(func(ctx context.Context, args ...interface{}) error { diff --git a/pkg/node/fsm/idle_state.go b/pkg/node/fsm/idle_state.go index 447ddb6f3..070908b22 100644 --- a/pkg/node/fsm/idle_state.go +++ b/pkg/node/fsm/idle_state.go @@ -68,6 +68,8 @@ func (a *IdleState) Task(task tasks.AsyncTask) (State, Async, error) { return a, nil, nil case tasks.MineMicro: // Do nothing return a, nil, nil + case tasks.SnapshotTimeout: + return a, nil, nil default: return a, nil, a.Errorf(errors.Errorf( "unexpected internal task '%d' with data '%+v' received by %s State", diff --git a/pkg/node/fsm/ng_state.go b/pkg/node/fsm/ng_state.go index 7529aaab9..a18a81f5b 100644 --- a/pkg/node/fsm/ng_state.go +++ b/pkg/node/fsm/ng_state.go @@ -2,6 +2,8 @@ package fsm import ( "context" + "time" + "github.com/pkg/errors" "github.com/qmuntal/stateless" "go.uber.org/zap" @@ -31,6 +33,14 @@ func newNGState(baseInfo BaseInfo) State { } } +func newNGStateWithCache(baseInfo BaseInfo, cache blockStatesCache) State { + baseInfo.syncPeer.Clear() + return &NGState{ + baseInfo: baseInfo, + blocksCache: cache, + } +} + func (a *NGState) Errorf(err error) error { return fsmErrorf(a, err) } @@ -62,6 +72,8 @@ func (a *NGState) Task(task tasks.AsyncTask) (State, Async, error) { "unexpected type %T, expected 'tasks.MineMicroTaskData'", task.Data)) } return a.mineMicro(t.Block, t.Limits, t.KeyPair, t.Vrf) + case tasks.SnapshotTimeout: + return a, nil, nil default: return a, nil, a.Errorf(errors.Errorf( "unexpected internal task '%d' with data '%+v' received by %s State", @@ -95,8 +107,6 @@ func (a *NGState) rollbackToStateFromCache(blockFromCache *proto.Block) error { _, err = a.baseInfo.blocksApplier.Apply( a.baseInfo.storage, []*proto.Block{blockFromCache}, - nil, - a.baseInfo.enableLightMode, ) if err != nil { return errors.Wrapf(err, "failed to apply cached block %q", blockFromCache.ID.String()) @@ -116,11 +126,10 @@ func (a *NGState) rollbackToStateFromCacheInLightNode(parentID proto.BlockID) er return errors.Wrapf(err, "failed to rollback to parent block '%s' of cached block '%s'", previousBlockID.String(), blockFromCache.ID.String()) } - _, err = a.baseInfo.blocksApplier.Apply( + _, err = a.baseInfo.blocksApplier.ApplyWithSnapshots( a.baseInfo.storage, []*proto.Block{blockFromCache}, []*proto.BlockSnapshot{snapshotFromCache}, - a.baseInfo.enableLightMode, ) if err != nil { return errors.Wrapf(err, "failed to apply cached block %q", blockFromCache.ID.String()) @@ -169,16 +178,14 @@ func (a *NGState) Block(peer peer.Peer, block *proto.Block) (State, Async, error } if a.baseInfo.enableLightMode { - a.blockWaitingForSnapshot = block pe := extension.NewPeerExtension(peer, a.baseInfo.scheme) pe.AskBlockSnapshot(block.BlockID()) - return a, nil, nil + return newWaitSnapshotState(a.baseInfo, block, a.blocksCache), + tasks.Tasks(tasks.NewSnapshotTimeoutTask(time.Minute, block.BlockID(), tasks.BlockSnapshot)), nil } _, err = a.baseInfo.blocksApplier.Apply( a.baseInfo.storage, []*proto.Block{block}, - nil, - a.baseInfo.enableLightMode, ) if err != nil { return a, nil, a.Errorf(errors.Wrapf(err, "failed to apply block %s", block.BlockID())) @@ -192,45 +199,6 @@ func (a *NGState) Block(peer peer.Peer, block *proto.Block) (State, Async, error return newNGState(a.baseInfo), nil, nil } -func (a *NGState) BlockSnapshot( - peer peer.Peer, - blockID proto.BlockID, - snapshot proto.BlockSnapshot, -) (State, Async, error) { - // Skip, we are not waiting snapshot - if a.blockWaitingForSnapshot == nil { - return a, nil, nil - } - if a.blockWaitingForSnapshot.BlockID() != blockID { - return a, nil, a.Errorf( - errors.Errorf("new snapshot doesn't match with block %s", a.blockWaitingForSnapshot.BlockID())) - } - - _, err := a.baseInfo.blocksApplier.Apply( - a.baseInfo.storage, - []*proto.Block{a.blockWaitingForSnapshot}, - []*proto.BlockSnapshot{&snapshot}, - a.baseInfo.enableLightMode, - ) - if err != nil { - // metrics.FSMKeyBlockDeclined("ng", block, err) - return a, nil, a.Errorf(errors.Wrapf(err, "peer '%s'", peer.ID())) - } - - metrics.FSMKeyBlockApplied("ng", a.blockWaitingForSnapshot) - zap.S().Named(logging.FSMNamespace).Debugf("[%s] Handle received key block message: block '%s' applied to state", - a, blockID) - - a.blocksCache.Clear() - a.blocksCache.AddBlockState(a.blockWaitingForSnapshot) - a.blocksCache.AddSnapshot(blockID, snapshot) - a.baseInfo.scheduler.Reschedule() - a.baseInfo.actions.SendScore(a.baseInfo.storage) - a.baseInfo.CleanUtx() - a.blockWaitingForSnapshot = nil - return newNGState(a.baseInfo), nil, nil -} - func (a *NGState) MinedBlock( block *proto.Block, limits proto.MiningLimits, keyPair proto.KeyPair, vrf []byte, ) (State, Async, error) { @@ -240,8 +208,6 @@ func (a *NGState) MinedBlock( _, err = a.baseInfo.blocksApplier.Apply( state, []*proto.Block{block}, - nil, - a.baseInfo.enableLightMode, ) return err }) @@ -287,44 +253,8 @@ func (a *NGState) MicroBlock(p peer.Peer, micro *proto.MicroBlock) (State, Async return a, nil, nil } - a.microBlockWaitingForSnapshot = micro - return a, nil, nil -} - -func (a *NGState) MicroBlockSnapshot( - _ peer.Peer, - blockID proto.BlockID, - snapshot proto.BlockSnapshot, -) (State, Async, error) { - if a.microBlockWaitingForSnapshot == nil { - return a, nil, nil - } - if a.microBlockWaitingForSnapshot.TotalBlockID != blockID { - return a, nil, a.Errorf(errors.Errorf( - "New snapshot doesn't match with microBlock %s", a.microBlockWaitingForSnapshot.TotalBlockID)) - } - // the TopBlock() is used here - block, err := a.checkAndAppendMicroBlock(a.microBlockWaitingForSnapshot, &snapshot) - if err != nil { - metrics.FSMMicroBlockDeclined("ng", a.microBlockWaitingForSnapshot, err) - return a, nil, a.Errorf(err) - } - zap.S().Named(logging.FSMNamespace).Debugf( - "[%s] Received snapshot for microblock '%s' successfully applied to state", a, block.BlockID(), - ) - a.baseInfo.MicroBlockCache.AddMicroBlockWithSnapshot(block.BlockID(), a.microBlockWaitingForSnapshot, &snapshot) - a.blocksCache.AddBlockState(block) - a.blocksCache.AddSnapshot(block.BlockID(), snapshot) - a.baseInfo.scheduler.Reschedule() - a.microBlockWaitingForSnapshot = nil - // Notify all connected peers about new microblock, send them microblock inv network message - if inv, ok := a.baseInfo.MicroBlockInvCache.Get(block.BlockID()); ok { - //TODO: We have to exclude from recipients peers that already have this microblock - if err = a.broadcastMicroBlockInv(inv); err != nil { - return a, nil, a.Errorf(errors.Wrap(err, "failed to handle microblock message")) - } - } - return a, nil, nil + return newWaitMicroSnapshotState(a.baseInfo, micro, a.blocksCache), + tasks.Tasks(tasks.NewSnapshotTimeoutTask(time.Minute, micro.TotalBlockID, tasks.MicroBlockSnapshot)), nil } // mineMicro handles a new microblock generated by miner. @@ -343,7 +273,7 @@ func (a *NGState) mineMicro( } metrics.FSMMicroBlockGenerated("ng", micro) err = a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { - _, er := a.baseInfo.blocksApplier.ApplyMicro(s, block, nil, a.baseInfo.enableLightMode) + _, er := a.baseInfo.blocksApplier.ApplyMicro(s, block) return er }) if err != nil { @@ -365,7 +295,7 @@ func (a *NGState) mineMicro( return a, nil, a.Errorf(err) } - if err = a.broadcastMicroBlockInv(inv); err != nil { + if err = broadcastMicroBlockInv(a.baseInfo, inv); err != nil { return a, nil, a.Errorf(errors.Wrap(err, "failed to broadcast generated microblock")) } @@ -375,28 +305,6 @@ func (a *NGState) mineMicro( return a, tasks.Tasks(tasks.NewMineMicroTask(a.baseInfo.microblockInterval, block, rest, keyPair, vrf)), nil } -func (a *NGState) broadcastMicroBlockInv(inv *proto.MicroBlockInv) error { - invBts, err := inv.MarshalBinary() - if err != nil { - return errors.Wrapf(err, "failed to marshal binary '%T'", inv) - } - var ( - cnt int - msg = &proto.MicroBlockInvMessage{ - Body: invBts, - } - ) - a.baseInfo.peers.EachConnected(func(p peer.Peer, score *proto.Score) { - p.SendMessage(msg) - cnt++ - }) - a.baseInfo.invRequester.Add2Cache(inv.TotalBlockID.Bytes()) // prevent further unnecessary microblock request - zap.S().Named(logging.FSMNamespace).Debugf("Network message '%T' sent to %d peers: blockID='%s', ref='%s'", - msg, cnt, inv.TotalBlockID, inv.Reference, - ) - return nil -} - // checkAndAppendMicroBlock checks that microblock is appendable and appends it. func (a *NGState) checkAndAppendMicroBlock( micro *proto.MicroBlock, @@ -448,11 +356,17 @@ func (a *NGState) checkAndAppendMicroBlock( topBlockSnapshots.AppendTxSnapshot(sn) } snapshotsToApply = &topBlockSnapshots + err = a.baseInfo.storage.Map(func(state state.State) error { + _, er := a.baseInfo.blocksApplier.ApplyMicroWithSnapshots(state, newBlock, snapshotsToApply) + return er + }) + } else { + err = a.baseInfo.storage.Map(func(state state.State) error { + _, er := a.baseInfo.blocksApplier.ApplyMicro(state, newBlock) + return er + }) } - err = a.baseInfo.storage.Map(func(state state.State) error { - _, er := a.baseInfo.blocksApplier.ApplyMicro(state, newBlock, snapshotsToApply, a.baseInfo.enableLightMode) - return er - }) + if err != nil { metrics.FSMMicroBlockDeclined("ng", micro, err) return nil, errors.Wrap(err, "failed to apply created from micro block") @@ -521,6 +435,12 @@ func (c *blockStatesCache) GetSnapshot(blockID proto.BlockID) (*proto.BlockSnaps func initNGStateInFSM(state *StateData, fsm *stateless.StateMachine, info BaseInfo) { var ngSkipMessageList proto.PeerMessageIDs + if !info.enableLightMode { + ngSkipMessageList = append(ngSkipMessageList, []proto.PeerMessageID{ + proto.ContentIDMicroBlockSnapshot, + proto.ContentIDBlockSnapshot, + }...) + } fsm.Configure(NGStateName). OnEntry(func(ctx context.Context, args ...interface{}) error { info.skipMessageList.SetList(ngSkipMessageList) @@ -530,6 +450,8 @@ func initNGStateInFSM(state *StateData, fsm *stateless.StateMachine, info BaseIn Ignore(StartMiningEvent). Ignore(ChangeSyncPeerEvent). Ignore(StopSyncEvent). + Ignore(BlockSnapshotEvent). + Ignore(MicroBlockSnapshotEvent). PermitDynamic(StopMiningEvent, createPermitDynamicCallback(StopMiningEvent, state, func(args ...interface{}) (State, Async, error) { a, ok := state.State.(*NGState) @@ -612,31 +534,5 @@ func initNGStateInFSM(state *StateData, fsm *stateless.StateMachine, info BaseIn "unexpected type '%T' expected '*NGState'", state.State)) } return a.Halt() - })). - PermitDynamic(BlockSnapshotEvent, - createPermitDynamicCallback(BlockSnapshotEvent, state, func(args ...interface{}) (State, Async, error) { - a, ok := state.State.(*NGState) - if !ok { - return a, nil, a.Errorf(errors.Errorf( - "unexpected type '%T' expected '*NGState'", state.State)) - } - return a.BlockSnapshot( - convertToInterface[peer.Peer](args[0]), - args[1].(proto.BlockID), - args[2].(proto.BlockSnapshot), - ) - })). - PermitDynamic(MicroBlockSnapshotEvent, - createPermitDynamicCallback(MicroBlockSnapshotEvent, state, func(args ...interface{}) (State, Async, error) { - a, ok := state.State.(*NGState) - if !ok { - return a, nil, a.Errorf(errors.Errorf( - "unexpected type '%T' expected '*NGState'", state.State)) - } - return a.MicroBlockSnapshot( - convertToInterface[peer.Peer](args[0]), - args[1].(proto.BlockID), - args[2].(proto.BlockSnapshot), - ) })) } diff --git a/pkg/node/fsm/sync_state.go b/pkg/node/fsm/sync_state.go index 0e303aea0..f874934df 100644 --- a/pkg/node/fsm/sync_state.go +++ b/pkg/node/fsm/sync_state.go @@ -75,14 +75,20 @@ func (a *SyncState) Transaction(p peer.Peer, t proto.Transaction) (State, Async, func (a *SyncState) StopSync() (State, Async, error) { _, blocks, snapshots, _ := a.internal.Blocks(noopWrapper{}) if len(blocks) > 0 { - if !a.baseInfo.enableLightMode { - snapshots = nil // ensure that snapshots are emtpy + var err error + if a.baseInfo.enableLightMode { + err = a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { + var errApply error + _, errApply = a.baseInfo.blocksApplier.ApplyWithSnapshots(s, blocks, snapshots) + return errApply + }) + } else { + err = a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { + var errApply error + _, errApply = a.baseInfo.blocksApplier.Apply(s, blocks) + return errApply + }) } - err := a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { - var errApply error - _, errApply = a.baseInfo.blocksApplier.Apply(s, blocks, snapshots, a.baseInfo.enableLightMode) - return errApply - }) return newIdleState(a.baseInfo), nil, a.Errorf(err) } return newIdleState(a.baseInfo), nil, nil @@ -111,6 +117,8 @@ func (a *SyncState) Task(task tasks.AsyncTask) (State, Async, error) { return a, nil, nil case tasks.MineMicro: return a, nil, nil + case tasks.SnapshotTimeout: + return a, nil, nil default: return a, nil, a.Errorf(errors.Errorf( "unexpected internal task '%d' with data '%+v' received by %s State", @@ -203,8 +211,6 @@ func (a *SyncState) MinedBlock( _, err := a.baseInfo.blocksApplier.Apply( a.baseInfo.storage, []*proto.Block{block}, - nil, - a.baseInfo.enableLightMode, ) if err != nil { zap.S().Warnf("[Sync] Failed to apply mined block: %v", err) @@ -251,14 +257,20 @@ func (a *SyncState) applyBlocksWithSnapshots( zap.S().Named(logging.FSMNamespace).Debug("[Sync] No blocks to apply") return newSyncState(baseInfo, conf, internal), nil, nil } - if !a.baseInfo.enableLightMode { - snapshots = nil // ensure that snapshots are emtpy + var err error + if a.baseInfo.enableLightMode { + err = a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { + var errApply error + _, errApply = a.baseInfo.blocksApplier.ApplyWithSnapshots(s, blocks, snapshots) + return errApply + }) + } else { + err = a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { + var errApply error + _, errApply = a.baseInfo.blocksApplier.Apply(s, blocks) + return errApply + }) } - err := a.baseInfo.storage.Map(func(s state.NonThreadSafeState) error { - var errApply error - _, errApply = a.baseInfo.blocksApplier.Apply(s, blocks, snapshots, a.baseInfo.enableLightMode) - return errApply - }) if err != nil { if errs.IsValidationError(err) || errs.IsValidationError(errors.Cause(err)) { @@ -309,6 +321,11 @@ func initSyncStateInFSM(state *StateData, fsm *stateless.StateMachine, info Base proto.ContentIDMicroBlockSnapshot, proto.ContentIDMicroBlockSnapshotRequest, } + if !info.enableLightMode { + syncSkipMessageList = append(syncSkipMessageList, []proto.PeerMessageID{ + proto.ContentIDBlockSnapshot, + }...) + } fsm.Configure(SyncStateName). Ignore(MicroBlockEvent). Ignore(MicroBlockInvEvent). @@ -407,7 +424,7 @@ func initSyncStateInFSM(state *StateData, fsm *stateless.StateMachine, info Base a, ok := state.State.(*SyncState) if !ok { return a, nil, a.Errorf(errors.Errorf( - "unexpected type '%T' expected '*NGState'", state.State)) + "unexpected type '%T' expected '*SyncState'", state.State)) } return a.BlockSnapshot( convertToInterface[peer.Peer](args[0]), diff --git a/pkg/node/fsm/tasks/tasks.go b/pkg/node/fsm/tasks/tasks.go index 1a08caa72..2397ea934 100644 --- a/pkg/node/fsm/tasks/tasks.go +++ b/pkg/node/fsm/tasks/tasks.go @@ -15,6 +15,7 @@ const ( AskPeers MineMicro PersistComplete + SnapshotTimeout ) // SendAsyncTask sends task into channel with overflow check. @@ -173,3 +174,53 @@ func NewFuncTask(f func(ctx context.Context, output chan AsyncTask) error, taskT _type: taskType, } } + +type SnapshotTimeoutTaskType int + +const ( + BlockSnapshot SnapshotTimeoutTaskType = iota + MicroBlockSnapshot +) + +type SnapshotTimeoutTaskData struct { + BlockID proto.BlockID + SnapshotTaskType SnapshotTimeoutTaskType +} + +func (SnapshotTimeoutTaskData) taskDataMarker() {} + +type SnapshotTimeoutTask struct { + timeout time.Duration + SnapshotTimeoutTaskData SnapshotTimeoutTaskData +} + +func NewSnapshotTimeoutTask( + timeout time.Duration, + blockID proto.BlockID, + taskType SnapshotTimeoutTaskType, +) SnapshotTimeoutTask { + return SnapshotTimeoutTask{ + timeout: timeout, + SnapshotTimeoutTaskData: SnapshotTimeoutTaskData{ + BlockID: blockID, + SnapshotTaskType: taskType, + }, + } +} + +func (SnapshotTimeoutTask) Type() int { + return SnapshotTimeout +} + +func (a SnapshotTimeoutTask) Run(ctx context.Context, output chan AsyncTask) error { + select { + case <-ctx.Done(): + return ctx.Err() + case <-time.After(a.timeout): + SendAsyncTask(output, AsyncTask{ + TaskType: a.Type(), + Data: a.SnapshotTimeoutTaskData, + }) + } + return nil +} diff --git a/pkg/node/fsm/wait_micro_snapshot.go b/pkg/node/fsm/wait_micro_snapshot.go new file mode 100644 index 000000000..17c918c9f --- /dev/null +++ b/pkg/node/fsm/wait_micro_snapshot.go @@ -0,0 +1,232 @@ +package fsm + +import ( + "context" + + "github.com/pkg/errors" + "github.com/qmuntal/stateless" + "go.uber.org/zap" + + "github.com/wavesplatform/gowaves/pkg/logging" + "github.com/wavesplatform/gowaves/pkg/metrics" + "github.com/wavesplatform/gowaves/pkg/node/fsm/tasks" + "github.com/wavesplatform/gowaves/pkg/p2p/peer" + "github.com/wavesplatform/gowaves/pkg/proto" + "github.com/wavesplatform/gowaves/pkg/state" +) + +type WaitMicroSnapshotState struct { + baseInfo BaseInfo + blocksCache blockStatesCache + microBlockWaitingForSnapshot *proto.MicroBlock +} + +func newWaitMicroSnapshotState(baseInfo BaseInfo, block *proto.MicroBlock, cache blockStatesCache) State { + baseInfo.syncPeer.Clear() + return &WaitMicroSnapshotState{ + baseInfo: baseInfo, + blocksCache: cache, + microBlockWaitingForSnapshot: block, + } +} + +func (a *WaitMicroSnapshotState) Errorf(err error) error { + return fsmErrorf(a, err) +} + +func (a *WaitMicroSnapshotState) String() string { + return WaitSnapshotStateName +} + +func (a *WaitMicroSnapshotState) Task(task tasks.AsyncTask) (State, Async, error) { + switch task.TaskType { + case tasks.Ping: + return a, nil, nil + case tasks.AskPeers: + zap.S().Named(logging.FSMNamespace).Debug("[WaitSnapshot] Requesting peers") + a.baseInfo.peers.AskPeers() + return a, nil, nil + case tasks.MineMicro: + return a, nil, nil + case tasks.SnapshotTimeout: + t, ok := task.Data.(tasks.SnapshotTimeoutTaskData) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type %T, expected 'tasks.SnapshotTimeoutTaskData'", task.Data)) + } + switch t.SnapshotTaskType { + case tasks.BlockSnapshot: + return a, nil, nil + case tasks.MicroBlockSnapshot: + return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, a.Errorf(errors.Errorf( + "failed to get snapshot for microBlock '%s' - timeout", t.BlockID)) + default: + return a, nil, a.Errorf(errors.New("undefined Snapshot Task type")) + } + default: + return a, nil, a.Errorf(errors.Errorf( + "unexpected internal task '%d' with data '%+v' received by %s State", + task.TaskType, task.Data, a.String())) + } +} + +func (a *WaitMicroSnapshotState) MicroBlockSnapshot( + _ peer.Peer, + blockID proto.BlockID, + snapshot proto.BlockSnapshot, +) (State, Async, error) { + if a.microBlockWaitingForSnapshot == nil { + return a, nil, nil + } + if a.microBlockWaitingForSnapshot.TotalBlockID != blockID { + return a, nil, a.Errorf(errors.Errorf( + "New snapshot doesn't match with microBlock %s", a.microBlockWaitingForSnapshot.TotalBlockID)) + } + // the TopBlock() is used here + block, err := a.checkAndAppendMicroBlock(a.microBlockWaitingForSnapshot, &snapshot) + if err != nil { + metrics.FSMMicroBlockDeclined("ng", a.microBlockWaitingForSnapshot, err) + return a, nil, a.Errorf(err) + } + zap.S().Named(logging.FSMNamespace).Debugf( + "[%s] Received snapshot for microblock '%s' successfully applied to state", a, block.BlockID(), + ) + a.baseInfo.MicroBlockCache.AddMicroBlockWithSnapshot(block.BlockID(), a.microBlockWaitingForSnapshot, &snapshot) + a.blocksCache.AddBlockState(block) + a.blocksCache.AddSnapshot(block.BlockID(), snapshot) + a.baseInfo.scheduler.Reschedule() + a.microBlockWaitingForSnapshot = nil + // Notify all connected peers about new microblock, send them microblock inv network message + if inv, ok := a.baseInfo.MicroBlockInvCache.Get(block.BlockID()); ok { + //TODO: We have to exclude from recipients peers that already have this microblock + if err = broadcastMicroBlockInv(a.baseInfo, inv); err != nil { + return a, nil, a.Errorf(errors.Wrap(err, "failed to handle microblock message")) + } + } + return a, nil, nil +} + +func (a *WaitMicroSnapshotState) checkAndAppendMicroBlock( + micro *proto.MicroBlock, + snapshot *proto.BlockSnapshot, +) (*proto.Block, error) { + top := a.baseInfo.storage.TopBlock() // Get the last block + if top.BlockID() != micro.Reference { // Microblock doesn't refer to last block + err := errors.Errorf("microblock TBID '%s' refer to block ID '%s' but last block ID is '%s'", + micro.TotalBlockID.String(), micro.Reference.String(), top.BlockID().String()) + metrics.FSMMicroBlockDeclined("ng", micro, err) + return &proto.Block{}, proto.NewInfoMsg(err) + } + ok, err := micro.VerifySignature(a.baseInfo.scheme) + if err != nil { + return nil, err + } + if !ok { + return nil, errors.Errorf("microblock '%s' has invalid signature", micro.TotalBlockID.String()) + } + newTrs := top.Transactions.Join(micro.Transactions) + newBlock, err := proto.CreateBlock(newTrs, top.Timestamp, top.Parent, top.GeneratorPublicKey, top.NxtConsensus, + top.Version, top.Features, top.RewardVote, a.baseInfo.scheme) + if err != nil { + return nil, err + } + newBlock.BlockSignature = micro.TotalResBlockSigField + ok, err = newBlock.VerifySignature(a.baseInfo.scheme) + if err != nil { + return nil, err + } + if !ok { + return nil, errors.New("incorrect signature for applied microblock") + } + err = newBlock.GenerateBlockID(a.baseInfo.scheme) + if err != nil { + return nil, errors.Wrap(err, "NGState microBlockByID: failed generate block id") + } + snapshotsToApply := snapshot + + h, errBToH := a.baseInfo.storage.BlockIDToHeight(top.BlockID()) + if errBToH != nil { + return nil, errBToH + } + topBlockSnapshots, errSAtH := a.baseInfo.storage.SnapshotsAtHeight(h) + if errSAtH != nil { + return nil, errSAtH + } + for _, sn := range snapshot.TxSnapshots { + topBlockSnapshots.AppendTxSnapshot(sn) + } + snapshotsToApply = &topBlockSnapshots + err = a.baseInfo.storage.Map(func(state state.State) error { + _, er := a.baseInfo.blocksApplier.ApplyMicroWithSnapshots(state, newBlock, snapshotsToApply) + return er + }) + + if err != nil { + metrics.FSMMicroBlockDeclined("ng", micro, err) + return nil, errors.Wrap(err, "failed to apply created from micro block") + } + metrics.FSMMicroBlockApplied("ng", micro) + return newBlock, nil +} + +func initWaitMicroSnapshotStateInFSM(state *StateData, fsm *stateless.StateMachine, info BaseInfo) { + waitSnapshotSkipMessageList := proto.PeerMessageIDs{ + proto.ContentIDGetPeers, + proto.ContentIDPeers, + proto.ContentIDGetSignatures, + proto.ContentIDSignatures, + proto.ContentIDGetBlock, + proto.ContentIDBlock, + proto.ContentIDScore, + proto.ContentIDTransaction, + proto.ContentIDInvMicroblock, + proto.ContentIDCheckpoint, + proto.ContentIDMicroblockRequest, + proto.ContentIDMicroblock, + proto.ContentIDPBBlock, + proto.ContentIDPBMicroBlock, + proto.ContentIDPBTransaction, + proto.ContentIDGetBlockIds, + proto.ContentIDBlockSnapshot, + } + fsm.Configure(WaitSnapshotStateName). + OnEntry(func(ctx context.Context, args ...interface{}) error { + info.skipMessageList.SetList(waitSnapshotSkipMessageList) + return nil + }). + Ignore(ScoreEvent). + Ignore(BlockEvent). + Ignore(MinedBlockEvent). + Ignore(BlockIDsEvent). + Ignore(MicroBlockEvent). + Ignore(MicroBlockInvEvent). + Ignore(TransactionEvent). + Ignore(StopSyncEvent). + Ignore(StartMiningEvent). + Ignore(ChangeSyncPeerEvent). + Ignore(StopMiningEvent). + Ignore(HaltEvent). + Ignore(BlockSnapshotEvent). + PermitDynamic(TaskEvent, + createPermitDynamicCallback(TaskEvent, state, func(args ...interface{}) (State, Async, error) { + a, ok := state.State.(*WaitMicroSnapshotState) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type '%T' expected '*WaitMicroSnapshotState'", state.State)) + } + return a.Task(args[0].(tasks.AsyncTask)) + })). + PermitDynamic(MicroBlockSnapshotEvent, + createPermitDynamicCallback(MicroBlockSnapshotEvent, state, func(args ...interface{}) (State, Async, error) { + a, ok := state.State.(*WaitMicroSnapshotState) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type '%T' expected '*WaitMicroSnapshotState'", state.State)) + } + return a.MicroBlockSnapshot( + convertToInterface[peer.Peer](args[0]), + args[1].(proto.BlockID), + args[2].(proto.BlockSnapshot), + ) + })) +} diff --git a/pkg/node/fsm/wait_snapshot_state.go b/pkg/node/fsm/wait_snapshot_state.go new file mode 100644 index 000000000..cbdc8a0f8 --- /dev/null +++ b/pkg/node/fsm/wait_snapshot_state.go @@ -0,0 +1,166 @@ +package fsm + +import ( + "context" + + "github.com/pkg/errors" + "github.com/qmuntal/stateless" + "go.uber.org/zap" + + "github.com/wavesplatform/gowaves/pkg/logging" + "github.com/wavesplatform/gowaves/pkg/metrics" + "github.com/wavesplatform/gowaves/pkg/node/fsm/tasks" + "github.com/wavesplatform/gowaves/pkg/p2p/peer" + "github.com/wavesplatform/gowaves/pkg/proto" +) + +type WaitSnapshotState struct { + baseInfo BaseInfo + blocksCache blockStatesCache + blockWaitingForSnapshot *proto.Block +} + +func newWaitSnapshotState(baseInfo BaseInfo, block *proto.Block, cache blockStatesCache) State { + baseInfo.syncPeer.Clear() + return &WaitSnapshotState{ + baseInfo: baseInfo, + blocksCache: cache, + blockWaitingForSnapshot: block, + } +} + +func (a *WaitSnapshotState) Errorf(err error) error { + return fsmErrorf(a, err) +} + +func (a *WaitSnapshotState) String() string { + return WaitSnapshotStateName +} + +func (a *WaitSnapshotState) Task(task tasks.AsyncTask) (State, Async, error) { + switch task.TaskType { + case tasks.Ping: + return a, nil, nil + case tasks.AskPeers: + zap.S().Named(logging.FSMNamespace).Debug("[WaitSnapshot] Requesting peers") + a.baseInfo.peers.AskPeers() + return a, nil, nil + case tasks.MineMicro: + return a, nil, nil + case tasks.SnapshotTimeout: + t, ok := task.Data.(tasks.SnapshotTimeoutTaskData) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type %T, expected 'tasks.SnapshotTimeoutTaskData'", task.Data)) + } + switch t.SnapshotTaskType { + case tasks.BlockSnapshot: + a.blockWaitingForSnapshot = nil + return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, a.Errorf(errors.Errorf( + "failed to get snapshot for block '%s' - timeout", t.BlockID)) + case tasks.MicroBlockSnapshot: + return a, nil, nil + default: + return a, nil, a.Errorf(errors.New("undefined Snapshot Task type")) + } + default: + return a, nil, a.Errorf(errors.Errorf( + "unexpected internal task '%d' with data '%+v' received by %s State", + task.TaskType, task.Data, a.String())) + } +} + +func (a *WaitSnapshotState) BlockSnapshot( + peer peer.Peer, + blockID proto.BlockID, + snapshot proto.BlockSnapshot, +) (State, Async, error) { + if a.blockWaitingForSnapshot.BlockID() != blockID { + return a, nil, a.Errorf( + errors.Errorf("new snapshot doesn't match with block %s", a.blockWaitingForSnapshot.BlockID())) + } + + _, err := a.baseInfo.blocksApplier.ApplyWithSnapshots( + a.baseInfo.storage, + []*proto.Block{a.blockWaitingForSnapshot}, + []*proto.BlockSnapshot{&snapshot}, + ) + if err != nil { + // metrics.FSMKeyBlockDeclined("ng", block, err) + return a, nil, a.Errorf(errors.Wrapf(err, "peer '%s'", peer.ID())) + } + + metrics.FSMKeyBlockApplied("ng", a.blockWaitingForSnapshot) + zap.S().Named(logging.FSMNamespace).Debugf("[%s] Handle received key block message: block '%s' applied to state", + a, blockID) + + a.blocksCache.Clear() + a.blocksCache.AddBlockState(a.blockWaitingForSnapshot) + a.blocksCache.AddSnapshot(blockID, snapshot) + a.baseInfo.scheduler.Reschedule() + a.baseInfo.actions.SendScore(a.baseInfo.storage) + a.baseInfo.CleanUtx() + a.blockWaitingForSnapshot = nil + return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, nil +} + +func initWaitSnapshotStateInFSM(state *StateData, fsm *stateless.StateMachine, info BaseInfo) { + waitSnapshotSkipMessageList := proto.PeerMessageIDs{ + proto.ContentIDGetPeers, + proto.ContentIDPeers, + proto.ContentIDGetSignatures, + proto.ContentIDSignatures, + proto.ContentIDGetBlock, + proto.ContentIDBlock, + proto.ContentIDScore, + proto.ContentIDTransaction, + proto.ContentIDInvMicroblock, + proto.ContentIDCheckpoint, + proto.ContentIDMicroblockRequest, + proto.ContentIDMicroblock, + proto.ContentIDPBBlock, + proto.ContentIDPBMicroBlock, + proto.ContentIDPBTransaction, + proto.ContentIDGetBlockIds, + } + fsm.Configure(WaitSnapshotStateName). + OnEntry(func(ctx context.Context, args ...interface{}) error { + info.skipMessageList.SetList(waitSnapshotSkipMessageList) + return nil + }). + Ignore(ScoreEvent). + Ignore(BlockEvent). + Ignore(MinedBlockEvent). + Ignore(BlockIDsEvent). + Ignore(MicroBlockEvent). + Ignore(MicroBlockInvEvent). + Ignore(TransactionEvent). + Ignore(StopSyncEvent). + Ignore(StartMiningEvent). + Ignore(ChangeSyncPeerEvent). + Ignore(StopMiningEvent). + Ignore(HaltEvent). + Ignore(MicroBlockSnapshotEvent). + PermitDynamic(TaskEvent, + createPermitDynamicCallback(TaskEvent, state, func(args ...interface{}) (State, Async, error) { + a, ok := state.State.(*WaitSnapshotState) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type '%T' expected '*WaitSnapshotState'", state.State)) + } + return a.Task(args[0].(tasks.AsyncTask)) + })). + PermitDynamic(BlockSnapshotEvent, + createPermitDynamicCallback(BlockSnapshotEvent, state, func(args ...interface{}) (State, Async, error) { + a, ok := state.State.(*WaitSnapshotState) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type '%T' expected '*WaitSnapshotState'", state.State)) + } + return a.BlockSnapshot( + convertToInterface[peer.Peer](args[0]), + args[1].(proto.BlockID), + args[2].(proto.BlockSnapshot), + ) + })) +} diff --git a/pkg/services/services.go b/pkg/services/services.go index a01194f6d..015a67605 100644 --- a/pkg/services/services.go +++ b/pkg/services/services.go @@ -14,14 +14,20 @@ type BlocksApplier interface { Apply( state state.State, block []*proto.Block, - snapshots []*proto.BlockSnapshot, - isLightNode bool, ) (proto.Height, error) ApplyMicro( state state.State, block *proto.Block, + ) (proto.Height, error) + ApplyWithSnapshots( + state state.State, + block []*proto.Block, + snapshots []*proto.BlockSnapshot, + ) (proto.Height, error) + ApplyMicroWithSnapshots( + state state.State, + block *proto.Block, snapshots *proto.BlockSnapshot, - isLightNode bool, ) (proto.Height, error) } diff --git a/pkg/state/address_transactions_test.go b/pkg/state/address_transactions_test.go index cf6858ef1..cae6677ad 100644 --- a/pkg/state/address_transactions_test.go +++ b/pkg/state/address_transactions_test.go @@ -25,7 +25,7 @@ func testIterImpl(t *testing.T, params StateParams) { blocks, err := ReadMainnetBlocksToHeight(blockHeight) require.NoError(t, err) // Add extra blocks and rollback to check that rollback scenario is handled correctly. - _, err = st.AddDeserializedBlocks(blocks, nil) + _, err = st.AddDeserializedBlocks(blocks) require.NoError(t, err) err = st.RollbackToHeight(8000) require.NoError(t, err) diff --git a/pkg/state/api.go b/pkg/state/api.go index 27488f299..2d97272d6 100644 --- a/pkg/state/api.go +++ b/pkg/state/api.go @@ -149,11 +149,12 @@ type StateModifier interface { // It's not recommended using this function when you are able to accumulate big blocks batch, // since it's much more efficient to add many blocks at once. AddBlock(block []byte) (*proto.Block, error) - AddDeserializedBlock(block *proto.Block, snapshot *proto.BlockSnapshot) (*proto.Block, error) + AddDeserializedBlock(block *proto.Block) (*proto.Block, error) // AddBlocks adds batch of new blocks to state. AddBlocks(blocks [][]byte) error // AddDeserializedBlocks marshals blocks to binary and calls AddBlocks. - AddDeserializedBlocks(blocks []*proto.Block, snapshots []*proto.BlockSnapshot) (*proto.Block, error) + AddDeserializedBlocks(blocks []*proto.Block) (*proto.Block, error) + AddDeserializedBlocksWithSnapshots(blocks []*proto.Block, snapshots []*proto.BlockSnapshot) (*proto.Block, error) // Rollback functionality. RollbackToHeight(height proto.Height) error RollbackTo(removalEdge proto.BlockID) error diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 6ce5c7af9..2fde3f4b6 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -742,18 +742,64 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { a.sc.resetComplexity() a.totalScriptsRuns = 0 }() - rideV5Activated, err := a.stor.features.newestIsActivated(int16(settings.RideV5)) + checkerInfo, err := a.createCheckerInfo(params) if err != nil { return err } - rideV6Activated, err := a.stor.features.newestIsActivated(int16(settings.RideV6)) + hasParent := params.parent != nil + if hasParent { + checkerInfo.parentTimestamp = params.parent.Timestamp + } + blockInfo, err := a.currentBlockInfo() + if err != nil { + return errors.Wrapf(err, "failed to get current block info, blockchain height is %d", params.blockchainHeight) + } + currentBlockHeight := blockInfo.Height + hasher, err := newTxSnapshotHasherDefault() + if err != nil { + return errors.Wrapf(err, "failed to create tx snapshot default hasher, block height is %d", currentBlockHeight) + } + defer hasher.Release() + + stateHash, err := a.createInitialDiffAndStateHash(params, hasParent, blockInfo, hasher) if err != nil { return err } - blockRewardDistribution, err := a.stor.features.newestIsActivated(int16(settings.BlockRewardDistribution)) + var blockSnapshots *proto.BlockSnapshot + + blockSnapshots, stateHash, err = a.appendTxs(params, checkerInfo, stateHash, hasher) if err != nil { return err } + + blockID := params.block.BlockID() + if ssErr := a.stor.snapshots.saveSnapshots(blockID, blockInfo.Height, *blockSnapshots); ssErr != nil { + return ssErr + } + // clean up legacy state hash records with zero diffs + a.stor.balances.filterZeroDiffsSHOut(blockID) + // TODO: check snapshot hash with the block snapshot hash if it exists + if shErr := a.stor.stateHashes.saveSnapshotStateHash(stateHash, blockInfo.Height, blockID); shErr != nil { + return errors.Wrapf(shErr, "failed to save block shasnpt hash at height %d", blockInfo.Height) + } + // Save fee distribution of this block. + // This will be needed for createMinerAndRewardDiff() of next block due to NG. + return a.blockDiffer.saveCurFeeDistr(params.block) +} + +func (a *txAppender) createCheckerInfo(params *appendBlockParams) (*checkerInfo, error) { + rideV5Activated, err := a.stor.features.newestIsActivated(int16(settings.RideV5)) + if err != nil { + return nil, err + } + rideV6Activated, err := a.stor.features.newestIsActivated(int16(settings.RideV6)) + if err != nil { + return nil, err + } + blockRewardDistribution, err := a.stor.features.newestIsActivated(int16(settings.BlockRewardDistribution)) + if err != nil { + return nil, err + } checkerInfo := &checkerInfo{ currentTimestamp: params.block.Timestamp, blockID: params.block.BlockID(), @@ -763,55 +809,41 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { rideV6Activated: rideV6Activated, blockRewardDistribution: blockRewardDistribution, } - hasParent := params.parent != nil - if hasParent { - checkerInfo.parentTimestamp = params.parent.Timestamp - } - stateActionsCounterInBlockValidation := new(proto.StateActionsCounter) + return checkerInfo, nil +} - snapshotApplierInfo := newBlockSnapshotsApplierInfo(checkerInfo, a.settings.AddressSchemeCharacter, - stateActionsCounterInBlockValidation) - a.txHandler.sa.SetApplierInfo(snapshotApplierInfo) - // 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. +func (a *txAppender) createInitialDiffAndStateHash( + params *appendBlockParams, + hasParent bool, + blockInfo *proto.BlockInfo, + hasher *txSnapshotHasher, +) (crypto.Digest, error) { minerAndRewardDiff, err := a.blockDiffer.createMinerAndRewardDiff(params.block, hasParent) if err != nil { - return err + return crypto.Digest{}, err } // create the initial snapshot initialSnapshot, err := a.txHandler.tp.createInitialBlockSnapshot(minerAndRewardDiff.balancesChanges()) if err != nil { - return errors.Wrap(err, "failed to create initial snapshot") - } - - blockInfo, err := a.currentBlockInfo() - if err != nil { - return errors.Wrapf(err, "failed to get current block info, blockchain height is %d", params.blockchainHeight) + return crypto.Digest{}, errors.Wrap(err, "failed to create initial snapshot") } currentBlockHeight := blockInfo.Height - hasher, err := newTxSnapshotHasherDefault() - if err != nil { - return errors.Wrapf(err, "failed to create tx snapshot default hasher, block height is %d", currentBlockHeight) - } - defer hasher.Release() - // Save miner diff first (for validation) if err = a.diffStor.saveTxDiff(minerAndRewardDiff); err != nil { - return err + return crypto.Digest{}, err } err = a.diffApplier.validateBalancesChanges(minerAndRewardDiff.balancesChanges()) if err != nil { - return errors.Wrap(err, "failed to validate miner reward changes") + return crypto.Digest{}, errors.Wrap(err, "failed to validate miner reward changes") } a.diffStor.reset() err = initialSnapshot.ApplyInitialSnapshot(a.txHandler.sa) if err != nil { - return errors.Wrap(err, "failed to apply an initial snapshot") + return crypto.Digest{}, errors.Wrap(err, "failed to apply an initial snapshot") } // get initial snapshot hash for block @@ -823,21 +855,47 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { initialSnapshot.regular, ) if err != nil { - return errors.Wrapf(err, "failed to calculate initial snapshot hash for blockID %q at height %d", + return crypto.Digest{}, errors.Wrapf(err, "failed to calculate initial snapshot hash for blockID %q at height %d", params.block.BlockID(), currentBlockHeight, ) } + return stateHash, nil +} + +func (a *txAppender) appendBlockWithSnapshot(params *appendBlockParams) error { + // Reset block complexity counter. + defer func() { + a.sc.resetComplexity() + a.totalScriptsRuns = 0 + }() + checkerInfo, err := a.createCheckerInfo(params) + if err != nil { + return err + } + hasParent := params.parent != nil + if hasParent { + checkerInfo.parentTimestamp = params.parent.Timestamp + } + blockInfo, err := a.currentBlockInfo() + if err != nil { + return errors.Wrapf(err, "failed to get current block info, blockchain height is %d", params.blockchainHeight) + } + currentBlockHeight := blockInfo.Height + hasher, err := newTxSnapshotHasherDefault() + if err != nil { + return errors.Wrapf(err, "failed to create tx snapshot default hasher, block height is %d", currentBlockHeight) + } + defer hasher.Release() + + stateHash, err := a.createInitialDiffAndStateHash(params, hasParent, blockInfo, hasher) + if err != nil { + return err + } var blockSnapshots *proto.BlockSnapshot - if params.snapshot != nil { - blockSnapshots, stateHash, err = a.applySnapshotsInLightNode(params, stateHash, hasher) - if err != nil { - return err - } - } else { - blockSnapshots, stateHash, err = a.appendTxs(params, checkerInfo, stateHash, hasher) - if err != nil { - return err - } + + blockSnapshots, stateHash, err = a.applySnapshotsInLightNode(params, stateHash, hasher) + if err != nil { + return err } // check whether the calculated snapshot state hash equals with the provided one if blockStateHash, present := params.block.GetStateHash(); present && blockStateHash != stateHash { diff --git a/pkg/state/state.go b/pkg/state/state.go index 3255a58d1..25655a893 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -606,7 +606,7 @@ func (s *stateManager) addGenesisBlock() error { chans := launchVerifier(ctx, s.verificationGoroutinesNum, s.settings.AddressSchemeCharacter) - if err := s.addNewBlock(s.genesis, nil, chans, 0, nil, initSH); err != nil { + if err := s.addNewBlock(s.genesis, nil, chans, 0, initSH); err != nil { return err } if err := s.stor.hitSources.appendBlockHitSource(s.genesis, 1, s.genesis.GenSignature); err != nil { @@ -1080,20 +1080,10 @@ func (s *stateManager) addNewBlock( block, parent *proto.Block, chans *verifierChans, blockchainHeight uint64, - snapshot *proto.BlockSnapshot, lastSnapshotStateHash crypto.Digest, ) error { blockHeight := blockchainHeight + 1 - // Add score. - if err := s.stor.scores.appendBlockScore(block, blockHeight); err != nil { - return err - } - // Indicate new block for storage. - if err := s.rw.startBlock(block.BlockID()); err != nil { - return err - } - // Save block header to block storage. - if err := s.rw.writeBlockHeader(&block.BlockHeader); err != nil { + if err := s.beforeAppendBlock(block, blockHeight); err != nil { return err } transactions := block.Transactions @@ -1111,12 +1101,28 @@ func (s *stateManager) addNewBlock( parent: parentHeader, blockchainHeight: blockchainHeight, lastSnapshotStateHash: lastSnapshotStateHash, - snapshot: snapshot, } // Check and perform block's transactions, create balance diffs, write transactions to storage. if err := s.appender.appendBlock(params); err != nil { return err } + return s.afterAppendBlock(block, blockHeight) +} + +func (s *stateManager) beforeAppendBlock(block *proto.Block, blockHeight proto.Height) error { + // Add score. + if err := s.stor.scores.appendBlockScore(block, blockHeight); err != nil { + return err + } + // Indicate new block for storage. + if err := s.rw.startBlock(block.BlockID()); err != nil { + return err + } + // Save block header to block storage. + return s.rw.writeBlockHeader(&block.BlockHeader) +} + +func (s *stateManager) afterAppendBlock(block *proto.Block, blockHeight proto.Height) error { // Let block storage know that the current block is over. if err := s.rw.finishBlock(block.BlockID()); err != nil { return err @@ -1138,6 +1144,42 @@ func (s *stateManager) addNewBlock( return nil } +func (s *stateManager) addNewBlockWithSnapshot( + block, parent *proto.Block, + chans *verifierChans, + blockchainHeight uint64, + snapshot *proto.BlockSnapshot, + lastSnapshotStateHash crypto.Digest, +) error { + blockHeight := blockchainHeight + 1 + if err := s.beforeAppendBlock(block, blockHeight); err != nil { + return err + } + transactions := block.Transactions + if block.TransactionCount != transactions.Count() { + return errors.Errorf( + "block.TransactionCount != transactions.Count(), %d != %d", block.TransactionCount, transactions.Count()) + } + var parentHeader *proto.BlockHeader + if parent != nil { + parentHeader = &parent.BlockHeader + } + params := &appendBlockParams{ + transactions: transactions, + chans: chans, + block: &block.BlockHeader, + parent: parentHeader, + blockchainHeight: blockchainHeight, + lastSnapshotStateHash: lastSnapshotStateHash, + snapshot: snapshot, + } + // Check and perform block's transactions, create balance diffs, write transactions to storage. + if err := s.appender.appendBlockWithSnapshot(params); err != nil { + return err + } + return s.afterAppendBlock(block, blockHeight) +} + func (s *stateManager) reset() { s.rw.reset() s.stor.reset() @@ -1164,7 +1206,7 @@ func (s *stateManager) flush() error { func (s *stateManager) AddBlock(block []byte) (*proto.Block, error) { s.newBlocks.setNewBinary([][]byte{block}) - rs, err := s.addBlocks(nil) + rs, err := s.addBlocks() if err != nil { if err := s.rw.syncWithDb(); err != nil { zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) @@ -1174,9 +1216,9 @@ func (s *stateManager) AddBlock(block []byte) (*proto.Block, error) { return rs, nil } -func (s *stateManager) AddDeserializedBlock(block *proto.Block, snapshot *proto.BlockSnapshot) (*proto.Block, error) { +func (s *stateManager) AddDeserializedBlock(block *proto.Block) (*proto.Block, error) { s.newBlocks.setNew([]*proto.Block{block}) - rs, err := s.addBlocks([]*proto.BlockSnapshot{snapshot}) + rs, err := s.addBlocks() if err != nil { if err := s.rw.syncWithDb(); err != nil { zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) @@ -1188,7 +1230,7 @@ func (s *stateManager) AddDeserializedBlock(block *proto.Block, snapshot *proto. func (s *stateManager) AddBlocks(blockBytes [][]byte) error { s.newBlocks.setNewBinary(blockBytes) - if _, err := s.addBlocks(nil); err != nil { + if _, err := s.addBlocks(); err != nil { if err := s.rw.syncWithDb(); err != nil { zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) } @@ -1199,13 +1241,27 @@ func (s *stateManager) AddBlocks(blockBytes [][]byte) error { func (s *stateManager) AddDeserializedBlocks( blocks []*proto.Block, +) (*proto.Block, error) { + s.newBlocks.setNew(blocks) + lastBlock, err := s.addBlocks() + if err != nil { + if err = s.rw.syncWithDb(); err != nil { + zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) + } + return nil, err + } + return lastBlock, nil +} + +func (s *stateManager) AddDeserializedBlocksWithSnapshots( + blocks []*proto.Block, snapshots []*proto.BlockSnapshot, ) (*proto.Block, error) { - if s.enableLightNode && (len(blocks) != len(snapshots)) { + if len(blocks) != len(snapshots) { return nil, errors.New("the numbers of snapshots doesn't match the number of blocks") } s.newBlocks.setNew(blocks) - lastBlock, err := s.addBlocks(snapshots) + lastBlock, err := s.addBlocksWithSnapshots(snapshots) if err != nil { if err := s.rw.syncWithDb(); err != nil { zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) @@ -1485,8 +1541,7 @@ func getSnapshotByIndIfNotNil(snapshots []*proto.BlockSnapshot, pos int) *proto. return snapshots[pos] } -func (s *stateManager) addBlocks(snapshots []*proto.BlockSnapshot) (*proto.Block, error) { //nolint:gocognit,funlen - // TODO: fix lint +func (s *stateManager) addBlocks() (*proto.Block, error) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() defer func() { @@ -1526,42 +1581,157 @@ func (s *stateManager) addBlocks(snapshots []*proto.BlockSnapshot) (*proto.Block if errCurBlock != nil { return nil, wrapErr(DeserializationError, errCurBlock) } - // Assign unique block number for this block ID, add this number to the list of valid blocks. - if err = s.stateDB.addBlock(block.BlockID()); err != nil { - return nil, wrapErr(ModificationError, err) + + if err = s.beforeAddingBlock(block, lastAppliedBlock, blockchainCurHeight, chans); err != nil { + return nil, err } - // At some blockchain heights specific logic is performed. - // This includes voting for features, block rewards and so on. - if err = s.blockchainHeightAction(blockchainCurHeight, lastAppliedBlock.BlockID(), block.BlockID()); err != nil { - return nil, wrapErr(ModificationError, err) + + sh, errSh := s.stor.stateHashes.newestSnapshotStateHash(blockchainCurHeight) + if errSh != nil { + return nil, errors.Wrapf(errSh, "failed to get newest snapshot state hash for height %d", + blockchainCurHeight, + ) } - if vhErr := s.cv.ValidateHeaderBeforeBlockApplying(&block.BlockHeader, blockchainCurHeight); vhErr != nil { - return nil, vhErr + // Save block to storage, check its transactions, create and save balance diffs for its transactions. + if addErr := s.addNewBlock( + block, + lastAppliedBlock, + chans, + blockchainCurHeight, + sh, + ); addErr != nil { + return nil, addErr } - // Send block for signature verification, which works in separate goroutine. - task := &verifyTask{ - taskType: verifyBlock, - parentID: lastAppliedBlock.BlockID(), - block: block, + + if s.needToFinishVotingPeriod(blockchainCurHeight + 1) { + // If we need to finish voting period on the next block (h+1) then + // we have to check that protobuf will be activated on next block + s.checkProtobufActivation(blockchainCurHeight + 2) } - if err = chans.trySend(task); err != nil { - return nil, err + headers[pos] = block.BlockHeader + pos++ + ids = append(ids, block.BlockID()) + lastAppliedBlock = block + } + // Tasks chan can now be closed, since all the blocks and transactions have been already sent for verification. + // wait for all verifier goroutines + if verifyError := chans.closeAndWait(); verifyError != nil { + return nil, wrapErr(ValidationError, verifyError) + } + + // Retrieve and store legacy state hashes for each of new blocks. + if shErr := s.stor.handleLegacyStateHashes(height, ids); shErr != nil { + return nil, wrapErr(ModificationError, shErr) + } + // Validate consensus (i.e. that all the new blocks were mined fairly). + if err = s.cv.ValidateHeadersBatch(headers[:pos], height); err != nil { + return nil, wrapErr(ValidationError, err) + } + // After everything is validated, save all the changes to DB. + if err = s.flush(); err != nil { + return nil, wrapErr(ModificationError, err) + } + zap.S().Infof( + "Height: %d; Block ID: %s, GenSig: %s, ts: %d", + height+uint64(blocksNumber), + lastAppliedBlock.BlockID().String(), + base58.Encode(lastAppliedBlock.GenSignature), + lastAppliedBlock.Timestamp, + ) + return lastAppliedBlock, nil +} + +func (s *stateManager) beforeAddingBlock( + block, lastAppliedBlock *proto.Block, + blockchainCurHeight proto.Height, + chans *verifierChans, +) error { + // Assign unique block number for this block ID, add this number to the list of valid blocks. + if err := s.stateDB.addBlock(block.BlockID()); err != nil { + return wrapErr(ModificationError, err) + } + // At some blockchain heights specific logic is performed. + // This includes voting for features, block rewards and so on. + if err := s.blockchainHeightAction(blockchainCurHeight, lastAppliedBlock.BlockID(), block.BlockID()); err != nil { + return wrapErr(ModificationError, err) + } + if vhErr := s.cv.ValidateHeaderBeforeBlockApplying(&block.BlockHeader, blockchainCurHeight); vhErr != nil { + return vhErr + } + // Send block for signature verification, which works in separate goroutine. + task := &verifyTask{ + taskType: verifyBlock, + parentID: lastAppliedBlock.BlockID(), + block: block, + } + if err := chans.trySend(task); err != nil { + return err + } + hs, err := s.cv.GenerateHitSource(blockchainCurHeight, block.BlockHeader) + if err != nil { + return err + } + + return s.stor.hitSources.appendBlockHitSource(block, blockchainCurHeight+1, hs) +} + +func (s *stateManager) addBlocksWithSnapshots( + snapshots []*proto.BlockSnapshot, +) (*proto.Block, error) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + defer func() { + // Reset in-memory storages and load last block in defer. + s.reset() + if err := s.loadLastBlock(); err != nil { + zap.S().Fatalf("Failed to load last block: %v", err) } - hs, err := s.cv.GenerateHitSource(blockchainCurHeight, block.BlockHeader) - if err != nil { + s.newBlocks.reset() + }() + + blocksNumber := s.newBlocks.len() + if blocksNumber == 0 { + return nil, wrapErr(InvalidInputError, errors.New("no blocks provided")) + } + + // Read some useful values for later. + lastAppliedBlock, err := s.topBlock() + if err != nil { + return nil, wrapErr(RetrievalError, err) + } + zap.S().Debugf( + "StateManager: parent (top) block ID: %s, ts: %d", + lastAppliedBlock.BlockID().String(), lastAppliedBlock.Timestamp) + height, err := s.Height() + if err != nil { + return nil, wrapErr(RetrievalError, err) + } + headers := make([]proto.BlockHeader, blocksNumber) + + // Launch verifier that checks signatures of blocks and transactions. + chans := launchVerifier(ctx, s.verificationGoroutinesNum, s.settings.AddressSchemeCharacter) + + var ids []proto.BlockID + pos := 0 + for s.newBlocks.next() { + blockchainCurHeight := height + uint64(pos) + block, errCurBlock := s.newBlocks.current() + if errCurBlock != nil { + return nil, wrapErr(DeserializationError, errCurBlock) + } + + if err = s.beforeAddingBlock(block, lastAppliedBlock, blockchainCurHeight, chans); err != nil { return nil, err } - sh, err := s.stor.stateHashes.newestSnapshotStateHash(blockchainCurHeight) - if err != nil { - return nil, errors.Wrapf(err, "failed to get newest snapshot state hash for height %d", + + sh, errSh := s.stor.stateHashes.newestSnapshotStateHash(blockchainCurHeight) + if errSh != nil { + return nil, errors.Wrapf(errSh, "failed to get newest snapshot state hash for height %d", blockchainCurHeight, ) } - if err := s.stor.hitSources.appendBlockHitSource(block, blockchainCurHeight+1, hs); err != nil { - return nil, err - } // Save block to storage, check its transactions, create and save balance diffs for its transactions. - if addErr := s.addNewBlock( + if addErr := s.addNewBlockWithSnapshot( block, lastAppliedBlock, chans, @@ -1593,18 +1763,16 @@ func (s *stateManager) addBlocks(snapshots []*proto.BlockSnapshot) (*proto.Block return nil, wrapErr(ModificationError, shErr) } // Validate consensus (i.e. that all the new blocks were mined fairly). - if err := s.cv.ValidateHeadersBatch(headers[:pos], height); err != nil { + if err = s.cv.ValidateHeadersBatch(headers[:pos], height); err != nil { return nil, wrapErr(ValidationError, err) } // After everything is validated, save all the changes to DB. - if err := s.flush(); err != nil { + if err = s.flush(); err != nil { return nil, wrapErr(ModificationError, err) } zap.S().Infof( - "Height: %d; Block ID: %s, GenSig: %s, ts: %d", - height+uint64(blocksNumber), - lastAppliedBlock.BlockID().String(), - base58.Encode(lastAppliedBlock.GenSignature), + "Height: %d; Block ID: %s, GenSig: %s, ts: %d", height+uint64(blocksNumber), + lastAppliedBlock.BlockID().String(), base58.Encode(lastAppliedBlock.GenSignature), lastAppliedBlock.Timestamp, ) return lastAppliedBlock, nil diff --git a/pkg/state/threadsafe_wrapper.go b/pkg/state/threadsafe_wrapper.go index f5ac47e22..82e892553 100644 --- a/pkg/state/threadsafe_wrapper.go +++ b/pkg/state/threadsafe_wrapper.go @@ -423,11 +423,10 @@ func (a *ThreadSafeWriteWrapper) AddBlock(block []byte) (*proto.Block, error) { func (a *ThreadSafeWriteWrapper) AddDeserializedBlock( block *proto.Block, - snapshot *proto.BlockSnapshot, ) (*proto.Block, error) { a.lock() defer a.unlock() - return a.s.AddDeserializedBlock(block, snapshot) + return a.s.AddDeserializedBlock(block) } func (a *ThreadSafeWriteWrapper) AddBlocks(blocks [][]byte) error { @@ -438,11 +437,19 @@ func (a *ThreadSafeWriteWrapper) AddBlocks(blocks [][]byte) error { func (a *ThreadSafeWriteWrapper) AddDeserializedBlocks( blocks []*proto.Block, +) (*proto.Block, error) { + a.lock() + defer a.unlock() + return a.s.AddDeserializedBlocks(blocks) +} + +func (a *ThreadSafeWriteWrapper) AddDeserializedBlocksWithSnapshots( + blocks []*proto.Block, snapshots []*proto.BlockSnapshot, ) (*proto.Block, error) { a.lock() defer a.unlock() - return a.s.AddDeserializedBlocks(blocks, snapshots) + return a.s.AddDeserializedBlocksWithSnapshots(blocks, snapshots) } func (a *ThreadSafeWriteWrapper) RollbackToHeight(height proto.Height) error { From 3d7d7b0a6fbf86e5a9439c8f06aaa9daac96d53f Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Thu, 25 Jan 2024 12:34:32 +0300 Subject: [PATCH 098/139] fix test --- pkg/node/fsm/wait_micro_snapshot.go | 4 +-- pkg/node/fsm/wait_snapshot_state.go | 4 +-- pkg/state/appender.go | 39 +++++++++++++++++------------ 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/pkg/node/fsm/wait_micro_snapshot.go b/pkg/node/fsm/wait_micro_snapshot.go index 17c918c9f..46e6076b8 100644 --- a/pkg/node/fsm/wait_micro_snapshot.go +++ b/pkg/node/fsm/wait_micro_snapshot.go @@ -189,8 +189,8 @@ func initWaitMicroSnapshotStateInFSM(state *StateData, fsm *stateless.StateMachi proto.ContentIDGetBlockIds, proto.ContentIDBlockSnapshot, } - fsm.Configure(WaitSnapshotStateName). - OnEntry(func(ctx context.Context, args ...interface{}) error { + fsm.Configure(WaitSnapshotStateName). //nolint:dupl // it's state setup + OnEntry(func(ctx context.Context, args ...interface{}) error { info.skipMessageList.SetList(waitSnapshotSkipMessageList) return nil }). diff --git a/pkg/node/fsm/wait_snapshot_state.go b/pkg/node/fsm/wait_snapshot_state.go index cbdc8a0f8..4b560b757 100644 --- a/pkg/node/fsm/wait_snapshot_state.go +++ b/pkg/node/fsm/wait_snapshot_state.go @@ -123,8 +123,8 @@ func initWaitSnapshotStateInFSM(state *StateData, fsm *stateless.StateMachine, i proto.ContentIDPBTransaction, proto.ContentIDGetBlockIds, } - fsm.Configure(WaitSnapshotStateName). - OnEntry(func(ctx context.Context, args ...interface{}) error { + fsm.Configure(WaitSnapshotStateName). //nolint:dupl // it's state setup + OnEntry(func(ctx context.Context, args ...interface{}) error { info.skipMessageList.SetList(waitSnapshotSkipMessageList) return nil }). diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 2fde3f4b6..2552076d5 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -674,23 +674,22 @@ func (a *txAppender) appendTxs( } // Check and append transactions. var bs proto.BlockSnapshot - + appendTxArgs := &appendTxParams{ + chans: params.chans, + checkerInfo: info, + blockInfo: blockInfo, + block: params.block, + acceptFailed: blockV5Activated, + blockV5Activated: blockV5Activated, + rideV5Activated: info.rideV5Activated, + rideV6Activated: info.rideV6Activated, + consensusImprovementsActivated: consensusImprovementsActivated, + blockRewardDistributionActivated: blockRewardDistributionActivated, + invokeExpressionActivated: invokeExpressionActivated, + validatingUtx: false, + currentMinerPK: params.block.GeneratorPublicKey, + } for _, tx := range params.transactions { - appendTxArgs := &appendTxParams{ - chans: params.chans, - checkerInfo: info, - blockInfo: blockInfo, - block: params.block, - acceptFailed: blockV5Activated, - blockV5Activated: blockV5Activated, - rideV5Activated: info.rideV5Activated, - rideV6Activated: info.rideV6Activated, - consensusImprovementsActivated: consensusImprovementsActivated, - blockRewardDistributionActivated: blockRewardDistributionActivated, - invokeExpressionActivated: invokeExpressionActivated, - validatingUtx: false, - currentMinerPK: params.block.GeneratorPublicKey, - } txSnapshots, errAppendTx := a.appendTx(tx, appendTxArgs) if errAppendTx != nil { return nil, crypto.Digest{}, errAppendTx @@ -750,6 +749,10 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { if hasParent { checkerInfo.parentTimestamp = params.parent.Timestamp } + stateActionsCounterInBlockValidation := new(proto.StateActionsCounter) + snapshotApplierInfo := newBlockSnapshotsApplierInfo(checkerInfo, a.settings.AddressSchemeCharacter, + stateActionsCounterInBlockValidation) + a.txHandler.sa.SetApplierInfo(snapshotApplierInfo) blockInfo, err := a.currentBlockInfo() if err != nil { return errors.Wrapf(err, "failed to get current block info, blockchain height is %d", params.blockchainHeight) @@ -876,6 +879,10 @@ func (a *txAppender) appendBlockWithSnapshot(params *appendBlockParams) error { if hasParent { checkerInfo.parentTimestamp = params.parent.Timestamp } + stateActionsCounterInBlockValidation := new(proto.StateActionsCounter) + snapshotApplierInfo := newBlockSnapshotsApplierInfo(checkerInfo, a.settings.AddressSchemeCharacter, + stateActionsCounterInBlockValidation) + a.txHandler.sa.SetApplierInfo(snapshotApplierInfo) blockInfo, err := a.currentBlockInfo() if err != nil { return errors.Wrapf(err, "failed to get current block info, blockchain height is %d", params.blockchainHeight) From cf743d58861a6c19c013f4898e7cff53c042bdbc Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Fri, 26 Jan 2024 01:31:18 +0300 Subject: [PATCH 099/139] Add snapshot hash check for 'txAppender.appendBlock'. --- pkg/state/appender.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index ac742b3db..a604d4fab 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -774,16 +774,22 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { if err != nil { return err } + // check whether the calculated snapshot state hash equals with the provided one + if blockStateHash, present := params.block.GetStateHash(); present && blockStateHash != stateHash { + return errors.Wrapf(errBlockSnapshotStateHashMismatch, "state hash mismatch; provided '%s', caluclated '%s'", + blockStateHash.String(), stateHash.String(), + ) + } blockID := params.block.BlockID() - if ssErr := a.stor.snapshots.saveSnapshots(blockID, blockInfo.Height, *blockSnapshots); ssErr != nil { + if ssErr := a.stor.snapshots.saveSnapshots(blockID, currentBlockHeight, *blockSnapshots); ssErr != nil { return ssErr } // clean up legacy state hash records with zero diffs a.txHandler.sa.filterZeroDiffsSHOut(blockID) // TODO: check snapshot hash with the block snapshot hash if it exists - if shErr := a.stor.stateHashes.saveSnapshotStateHash(stateHash, blockInfo.Height, blockID); shErr != nil { - return errors.Wrapf(shErr, "failed to save block shasnpt hash at height %d", blockInfo.Height) + if shErr := a.stor.stateHashes.saveSnapshotStateHash(stateHash, currentBlockHeight, blockID); shErr != nil { + return errors.Wrapf(shErr, "failed to save block shasnpt hash at height %d", currentBlockHeight) } // Save fee distribution of this block. // This will be needed for createMinerAndRewardDiff() of next block due to NG. From cc643a29efe5754894da9345efe7d0dc358a25a0 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Fri, 26 Jan 2024 07:56:20 +0300 Subject: [PATCH 100/139] Timeout tasks for wait snapshot states of FSM can be cancelled. --- pkg/node/fsm/ng_state.go | 10 +++----- pkg/node/fsm/tasks/tasks.go | 39 +++++++++++++++++++++++------ pkg/node/fsm/wait_micro_snapshot.go | 20 ++++++++++++--- pkg/node/fsm/wait_snapshot_state.go | 17 ++++++++++--- 4 files changed, 66 insertions(+), 20 deletions(-) diff --git a/pkg/node/fsm/ng_state.go b/pkg/node/fsm/ng_state.go index a18a81f5b..d8702871a 100644 --- a/pkg/node/fsm/ng_state.go +++ b/pkg/node/fsm/ng_state.go @@ -2,7 +2,6 @@ package fsm import ( "context" - "time" "github.com/pkg/errors" "github.com/qmuntal/stateless" @@ -180,8 +179,8 @@ func (a *NGState) Block(peer peer.Peer, block *proto.Block) (State, Async, error if a.baseInfo.enableLightMode { pe := extension.NewPeerExtension(peer, a.baseInfo.scheme) pe.AskBlockSnapshot(block.BlockID()) - return newWaitSnapshotState(a.baseInfo, block, a.blocksCache), - tasks.Tasks(tasks.NewSnapshotTimeoutTask(time.Minute, block.BlockID(), tasks.BlockSnapshot)), nil + st, timeoutTask := newWaitSnapshotState(a.baseInfo, block, a.blocksCache) + return st, tasks.Tasks(timeoutTask), nil } _, err = a.baseInfo.blocksApplier.Apply( a.baseInfo.storage, @@ -252,9 +251,8 @@ func (a *NGState) MicroBlock(p peer.Peer, micro *proto.MicroBlock) (State, Async a.blocksCache.AddBlockState(block) return a, nil, nil } - - return newWaitMicroSnapshotState(a.baseInfo, micro, a.blocksCache), - tasks.Tasks(tasks.NewSnapshotTimeoutTask(time.Minute, micro.TotalBlockID, tasks.MicroBlockSnapshot)), nil + st, timeoutTask := newWaitMicroSnapshotState(a.baseInfo, micro, a.blocksCache) + return st, tasks.Tasks(timeoutTask), nil } // mineMicro handles a new microblock generated by miner. diff --git a/pkg/node/fsm/tasks/tasks.go b/pkg/node/fsm/tasks/tasks.go index 2397ea934..37b223c8a 100644 --- a/pkg/node/fsm/tasks/tasks.go +++ b/pkg/node/fsm/tasks/tasks.go @@ -178,7 +178,7 @@ func NewFuncTask(f func(ctx context.Context, output chan AsyncTask) error, taskT type SnapshotTimeoutTaskType int const ( - BlockSnapshot SnapshotTimeoutTaskType = iota + BlockSnapshot SnapshotTimeoutTaskType = iota + 1 MicroBlockSnapshot ) @@ -191,19 +191,36 @@ func (SnapshotTimeoutTaskData) taskDataMarker() {} type SnapshotTimeoutTask struct { timeout time.Duration + outdated <-chan struct{} SnapshotTimeoutTaskData SnapshotTimeoutTaskData } -func NewSnapshotTimeoutTask( +func NewBlockSnapshotTimeoutTask( timeout time.Duration, blockID proto.BlockID, - taskType SnapshotTimeoutTaskType, + outdated <-chan struct{}, ) SnapshotTimeoutTask { return SnapshotTimeoutTask{ - timeout: timeout, + timeout: timeout, + outdated: outdated, + SnapshotTimeoutTaskData: SnapshotTimeoutTaskData{ + BlockID: blockID, + SnapshotTaskType: BlockSnapshot, + }, + } +} + +func NewMicroBlockSnapshotTimeoutTask( + timeout time.Duration, + blockID proto.BlockID, + outdated <-chan struct{}, +) SnapshotTimeoutTask { + return SnapshotTimeoutTask{ + timeout: timeout, + outdated: outdated, SnapshotTimeoutTaskData: SnapshotTimeoutTaskData{ BlockID: blockID, - SnapshotTaskType: taskType, + SnapshotTaskType: MicroBlockSnapshot, }, } } @@ -213,14 +230,22 @@ func (SnapshotTimeoutTask) Type() int { } func (a SnapshotTimeoutTask) Run(ctx context.Context, output chan AsyncTask) error { + t := time.NewTimer(a.timeout) + defer func() { + if !t.Stop() { + <-t.C + } + }() select { case <-ctx.Done(): return ctx.Err() - case <-time.After(a.timeout): + case <-a.outdated: + return nil + case <-t.C: SendAsyncTask(output, AsyncTask{ TaskType: a.Type(), Data: a.SnapshotTimeoutTaskData, }) + return nil } - return nil } diff --git a/pkg/node/fsm/wait_micro_snapshot.go b/pkg/node/fsm/wait_micro_snapshot.go index 46e6076b8..7c70bdaab 100644 --- a/pkg/node/fsm/wait_micro_snapshot.go +++ b/pkg/node/fsm/wait_micro_snapshot.go @@ -2,6 +2,7 @@ package fsm import ( "context" + "time" "github.com/pkg/errors" "github.com/qmuntal/stateless" @@ -18,16 +19,21 @@ import ( type WaitMicroSnapshotState struct { baseInfo BaseInfo blocksCache blockStatesCache + timeoutTaskOutdated chan<- struct{} microBlockWaitingForSnapshot *proto.MicroBlock } -func newWaitMicroSnapshotState(baseInfo BaseInfo, block *proto.MicroBlock, cache blockStatesCache) State { +func newWaitMicroSnapshotState(baseInfo BaseInfo, micro *proto.MicroBlock, cache blockStatesCache) (State, tasks.Task) { baseInfo.syncPeer.Clear() - return &WaitMicroSnapshotState{ + timeoutTaskOutdated := make(chan struct{}) + st := &WaitMicroSnapshotState{ baseInfo: baseInfo, blocksCache: cache, - microBlockWaitingForSnapshot: block, + timeoutTaskOutdated: timeoutTaskOutdated, + microBlockWaitingForSnapshot: micro, } + task := tasks.NewMicroBlockSnapshotTimeoutTask(time.Minute, micro.TotalBlockID, timeoutTaskOutdated) + return st, task } func (a *WaitMicroSnapshotState) Errorf(err error) error { @@ -58,6 +64,8 @@ func (a *WaitMicroSnapshotState) Task(task tasks.AsyncTask) (State, Async, error case tasks.BlockSnapshot: return a, nil, nil case tasks.MicroBlockSnapshot: + a.microBlockWaitingForSnapshot = nil + a.timeoutTaskOutdated = nil return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, a.Errorf(errors.Errorf( "failed to get snapshot for microBlock '%s' - timeout", t.BlockID)) default: @@ -88,6 +96,11 @@ func (a *WaitMicroSnapshotState) MicroBlockSnapshot( metrics.FSMMicroBlockDeclined("ng", a.microBlockWaitingForSnapshot, err) return a, nil, a.Errorf(err) } + defer func() { + a.microBlockWaitingForSnapshot = nil + close(a.timeoutTaskOutdated) + a.timeoutTaskOutdated = nil + }() zap.S().Named(logging.FSMNamespace).Debugf( "[%s] Received snapshot for microblock '%s' successfully applied to state", a, block.BlockID(), ) @@ -95,7 +108,6 @@ func (a *WaitMicroSnapshotState) MicroBlockSnapshot( a.blocksCache.AddBlockState(block) a.blocksCache.AddSnapshot(block.BlockID(), snapshot) a.baseInfo.scheduler.Reschedule() - a.microBlockWaitingForSnapshot = nil // Notify all connected peers about new microblock, send them microblock inv network message if inv, ok := a.baseInfo.MicroBlockInvCache.Get(block.BlockID()); ok { //TODO: We have to exclude from recipients peers that already have this microblock diff --git a/pkg/node/fsm/wait_snapshot_state.go b/pkg/node/fsm/wait_snapshot_state.go index 4b560b757..be15dbe63 100644 --- a/pkg/node/fsm/wait_snapshot_state.go +++ b/pkg/node/fsm/wait_snapshot_state.go @@ -2,6 +2,7 @@ package fsm import ( "context" + "time" "github.com/pkg/errors" "github.com/qmuntal/stateless" @@ -17,16 +18,21 @@ import ( type WaitSnapshotState struct { baseInfo BaseInfo blocksCache blockStatesCache + timeoutTaskOutdated chan<- struct{} blockWaitingForSnapshot *proto.Block } -func newWaitSnapshotState(baseInfo BaseInfo, block *proto.Block, cache blockStatesCache) State { +func newWaitSnapshotState(baseInfo BaseInfo, block *proto.Block, cache blockStatesCache) (State, tasks.Task) { baseInfo.syncPeer.Clear() - return &WaitSnapshotState{ + timeoutTaskOutdated := make(chan struct{}) + st := &WaitSnapshotState{ baseInfo: baseInfo, blocksCache: cache, + timeoutTaskOutdated: timeoutTaskOutdated, blockWaitingForSnapshot: block, } + task := tasks.NewBlockSnapshotTimeoutTask(time.Minute, block.BlockID(), timeoutTaskOutdated) + return st, task } func (a *WaitSnapshotState) Errorf(err error) error { @@ -56,6 +62,7 @@ func (a *WaitSnapshotState) Task(task tasks.AsyncTask) (State, Async, error) { switch t.SnapshotTaskType { case tasks.BlockSnapshot: a.blockWaitingForSnapshot = nil + a.timeoutTaskOutdated = nil return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, a.Errorf(errors.Errorf( "failed to get snapshot for block '%s' - timeout", t.BlockID)) case tasks.MicroBlockSnapshot: @@ -89,6 +96,11 @@ func (a *WaitSnapshotState) BlockSnapshot( // metrics.FSMKeyBlockDeclined("ng", block, err) return a, nil, a.Errorf(errors.Wrapf(err, "peer '%s'", peer.ID())) } + defer func() { + a.blockWaitingForSnapshot = nil + close(a.timeoutTaskOutdated) + a.timeoutTaskOutdated = nil + }() metrics.FSMKeyBlockApplied("ng", a.blockWaitingForSnapshot) zap.S().Named(logging.FSMNamespace).Debugf("[%s] Handle received key block message: block '%s' applied to state", @@ -100,7 +112,6 @@ func (a *WaitSnapshotState) BlockSnapshot( a.baseInfo.scheduler.Reschedule() a.baseInfo.actions.SendScore(a.baseInfo.storage) a.baseInfo.CleanUtx() - a.blockWaitingForSnapshot = nil return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, nil } From 157625cede3bf3b804b52d67c0148b031ab72999 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Mon, 29 Jan 2024 17:22:39 +0300 Subject: [PATCH 101/139] remove copypasts --- pkg/node/blocks_applier/blocks_applier.go | 12 +- pkg/node/blocks_applier/node_mocks.go | 4 +- pkg/node/fsm/idle_state.go | 2 +- pkg/node/fsm/ng/inv_request.go | 7 +- pkg/node/fsm/ng/inv_request_test.go | 4 +- pkg/node/fsm/ng_state.go | 33 ++--- pkg/node/fsm/wait_micro_snapshot.go | 5 +- pkg/p2p/peer/extension/extension.go | 8 ++ pkg/state/appender.go | 68 +--------- pkg/state/state.go | 156 ++-------------------- 10 files changed, 46 insertions(+), 253 deletions(-) diff --git a/pkg/node/blocks_applier/blocks_applier.go b/pkg/node/blocks_applier/blocks_applier.go index a86af69a3..7d8af569a 100644 --- a/pkg/node/blocks_applier/blocks_applier.go +++ b/pkg/node/blocks_applier/blocks_applier.go @@ -61,7 +61,8 @@ func (a *innerBlocksApplier) apply( deltaHeight := currentHeight - parentHeight if deltaHeight > maxRollbackDeltaHeight { // max number that we can rollback - return 0, errors.Errorf("can't apply new blocks, rollback more than 100 blocks, %d", deltaHeight) + return 0, errors.Errorf( + "can't apply new blocks, rollback more than %d blocks, %d", maxRollbackDeltaHeight, deltaHeight) } // save previously added blocks. If new firstBlock failed to add, then return them back @@ -160,7 +161,8 @@ func (a *innerBlocksApplier) applyWithSnapshots( deltaHeight := currentHeight - parentHeight if deltaHeight > maxRollbackDeltaHeight { // max number that we can rollback - return 0, errors.Errorf("can't apply new blocks, rollback more than 100 blocks, %d", deltaHeight) + return 0, errors.Errorf( + "can't apply new blocks, rollback more than %d blocks, %d", maxRollbackDeltaHeight, deltaHeight) } // save previously added blocks. If new firstBlock failed to add, then return them back @@ -264,9 +266,9 @@ func (a *innerBlocksApplier) applyMicro( _, err = storage.AddDeserializedBlocks([]*proto.Block{block}) if err != nil { // return back saved blocks - _, err2 := storage.AddDeserializedBlocks([]*proto.Block{currentBlock}) - if err2 != nil { - return 0, errors.Wrap(err2, "failed rollback block") + _, errAdd := storage.AddDeserializedBlocks([]*proto.Block{currentBlock}) + if errAdd != nil { + return 0, errors.Wrap(errAdd, "failed rollback block") } return 0, errors.Wrapf(err, "failed apply new block '%s'", block.BlockID().String()) } diff --git a/pkg/node/blocks_applier/node_mocks.go b/pkg/node/blocks_applier/node_mocks.go index ad16e6442..3a3da2d84 100644 --- a/pkg/node/blocks_applier/node_mocks.go +++ b/pkg/node/blocks_applier/node_mocks.go @@ -306,9 +306,7 @@ func (a *MockStateManager) AddDeserializedBlocksWithSnapshots( if out, err = a.AddDeserializedBlock(b); err != nil { return nil, err } - if snapshots != nil { - a.snapshots = append(a.snapshots, snapshots[i]) - } + a.snapshots = append(a.snapshots, snapshots[i]) } return out, nil } diff --git a/pkg/node/fsm/idle_state.go b/pkg/node/fsm/idle_state.go index 070908b22..9e4b41106 100644 --- a/pkg/node/fsm/idle_state.go +++ b/pkg/node/fsm/idle_state.go @@ -17,7 +17,7 @@ import ( type InvRequester interface { Add2Cache(id []byte) (existed bool) - Request(p types.MessageSender, id []byte, enableLightNode bool) (existed bool) + Request(p types.MessageSender, id []byte) (existed bool) } type IdleState struct { diff --git a/pkg/node/fsm/ng/inv_request.go b/pkg/node/fsm/ng/inv_request.go index ad77652ba..c9e366dd7 100644 --- a/pkg/node/fsm/ng/inv_request.go +++ b/pkg/node/fsm/ng/inv_request.go @@ -25,17 +25,12 @@ func (a *InvRequesterImpl) Add2Cache(id []byte) (existed bool) { return false } -func (a *InvRequesterImpl) Request(p types.MessageSender, id []byte, enableLightNode bool) bool { +func (a *InvRequesterImpl) Request(p types.MessageSender, id []byte) bool { existed := a.Add2Cache(id) if !existed { p.SendMessage(&proto.MicroBlockRequestMessage{ TotalBlockSig: id, }) - if enableLightNode { - p.SendMessage(&proto.MicroBlockSnapshotRequestMessage{ - BlockIDBytes: id, - }) - } } return existed } diff --git a/pkg/node/fsm/ng/inv_request_test.go b/pkg/node/fsm/ng/inv_request_test.go index d0c0dd792..951896cbc 100644 --- a/pkg/node/fsm/ng/inv_request_test.go +++ b/pkg/node/fsm/ng/inv_request_test.go @@ -21,9 +21,9 @@ func TestInvRequesterImpl_Request(t *testing.T) { buf := &messSender{} n := NewInvRequester() - n.Request(buf, proto.NewBlockIDFromSignature(crypto.Signature{}).Bytes(), false) + n.Request(buf, proto.NewBlockIDFromSignature(crypto.Signature{}).Bytes()) require.Equal(t, 1, len(buf.messages)) - n.Request(buf, proto.NewBlockIDFromSignature(crypto.Signature{}).Bytes(), false) + n.Request(buf, proto.NewBlockIDFromSignature(crypto.Signature{}).Bytes()) require.Equal(t, 1, len(buf.messages)) } diff --git a/pkg/node/fsm/ng_state.go b/pkg/node/fsm/ng_state.go index d8702871a..b286cb12f 100644 --- a/pkg/node/fsm/ng_state.go +++ b/pkg/node/fsm/ng_state.go @@ -18,10 +18,8 @@ import ( ) type NGState struct { - baseInfo BaseInfo - blocksCache blockStatesCache - blockWaitingForSnapshot *proto.Block - microBlockWaitingForSnapshot *proto.MicroBlock + baseInfo BaseInfo + blocksCache blockStatesCache } func newNGState(baseInfo BaseInfo) State { @@ -138,12 +136,6 @@ func (a *NGState) rollbackToStateFromCacheInLightNode(parentID proto.BlockID) er } func (a *NGState) Block(peer peer.Peer, block *proto.Block) (State, Async, error) { - if a.blockWaitingForSnapshot != nil { - return a, nil, a.Errorf(errors.Errorf( - "skip block %s, waiting snapshot for block %s", - block.BlockID().String(), - a.blockWaitingForSnapshot.BlockID().String())) - } ok, err := a.baseInfo.blocksApplier.BlockExists(a.baseInfo.storage, block) if err != nil { return a, nil, a.Errorf(errors.Wrapf(err, "peer '%s'", peer.ID())) @@ -230,12 +222,6 @@ func (a *NGState) MinedBlock( } func (a *NGState) MicroBlock(p peer.Peer, micro *proto.MicroBlock) (State, Async, error) { - if a.microBlockWaitingForSnapshot != nil { - return a, nil, a.Errorf(errors.Errorf( - "skip micro block %s, waiting snapshot for micro block %s", - micro.TotalBlockID.String(), - a.microBlockWaitingForSnapshot.TotalBlockID.String())) - } metrics.FSMMicroBlockReceived("ng", micro, p.Handshake().NodeName) if !a.baseInfo.enableLightMode { block, err := a.checkAndAppendMicroBlock(micro, nil) // the TopBlock() is used here @@ -247,10 +233,12 @@ func (a *NGState) MicroBlock(p peer.Peer, micro *proto.MicroBlock) (State, Async "[%s] Received microblock '%s' (referencing '%s') successfully applied to state", a, block.BlockID(), micro.Reference, ) - a.baseInfo.MicroBlockCache.AddMicroBlockWithSnapshot(block.BlockID(), micro, &proto.BlockSnapshot{}) + a.baseInfo.MicroBlockCache.AddMicroBlockWithSnapshot(block.BlockID(), micro, nil) a.blocksCache.AddBlockState(block) return a, nil, nil } + pe := extension.NewPeerExtension(p, a.baseInfo.scheme) + pe.AskMicroBlockSnapshot(micro.TotalBlockID) st, timeoutTask := newWaitMicroSnapshotState(a.baseInfo, micro, a.blocksCache) return st, tasks.Tasks(timeoutTask), nil } @@ -376,7 +364,7 @@ func (a *NGState) checkAndAppendMicroBlock( func (a *NGState) MicroBlockInv(p peer.Peer, inv *proto.MicroBlockInv) (State, Async, error) { metrics.MicroBlockInv(inv, p.Handshake().NodeName) // TODO: add logs about microblock request - existed := a.baseInfo.invRequester.Request(p, inv.TotalBlockID.Bytes(), a.baseInfo.enableLightMode) + existed := a.baseInfo.invRequester.Request(p, inv.TotalBlockID.Bytes()) if existed { zap.S().Named(logging.FSMNamespace).Debugf("[%s] Microblock inv received: block '%s' already in cache", a, inv.TotalBlockID) @@ -432,12 +420,9 @@ func (c *blockStatesCache) GetSnapshot(blockID proto.BlockID) (*proto.BlockSnaps } func initNGStateInFSM(state *StateData, fsm *stateless.StateMachine, info BaseInfo) { - var ngSkipMessageList proto.PeerMessageIDs - if !info.enableLightMode { - ngSkipMessageList = append(ngSkipMessageList, []proto.PeerMessageID{ - proto.ContentIDMicroBlockSnapshot, - proto.ContentIDBlockSnapshot, - }...) + var ngSkipMessageList = proto.PeerMessageIDs{ + proto.ContentIDMicroBlockSnapshot, + proto.ContentIDBlockSnapshot, } fsm.Configure(NGStateName). OnEntry(func(ctx context.Context, args ...interface{}) error { diff --git a/pkg/node/fsm/wait_micro_snapshot.go b/pkg/node/fsm/wait_micro_snapshot.go index 7c70bdaab..75671acde 100644 --- a/pkg/node/fsm/wait_micro_snapshot.go +++ b/pkg/node/fsm/wait_micro_snapshot.go @@ -83,9 +83,6 @@ func (a *WaitMicroSnapshotState) MicroBlockSnapshot( blockID proto.BlockID, snapshot proto.BlockSnapshot, ) (State, Async, error) { - if a.microBlockWaitingForSnapshot == nil { - return a, nil, nil - } if a.microBlockWaitingForSnapshot.TotalBlockID != blockID { return a, nil, a.Errorf(errors.Errorf( "New snapshot doesn't match with microBlock %s", a.microBlockWaitingForSnapshot.TotalBlockID)) @@ -142,6 +139,8 @@ func (a *WaitMicroSnapshotState) checkAndAppendMicroBlock( if err != nil { return nil, err } + // TODO: check if light node feature activated + 1000 blocks + newBlock.StateHash = micro.StateHash newBlock.BlockSignature = micro.TotalResBlockSigField ok, err = newBlock.VerifySignature(a.baseInfo.scheme) if err != nil { diff --git a/pkg/p2p/peer/extension/extension.go b/pkg/p2p/peer/extension/extension.go index 7e3d1055a..940a9349f 100644 --- a/pkg/p2p/peer/extension/extension.go +++ b/pkg/p2p/peer/extension/extension.go @@ -15,6 +15,7 @@ type PeerExtension interface { AskBlocksIDs(id []proto.BlockID) AskBlock(id proto.BlockID) AskBlockSnapshot(id proto.BlockID) + AskMicroBlockSnapshot(id proto.BlockID) SendMicroBlock(micro *proto.MicroBlock) error SendTransaction(t proto.Transaction) error } @@ -73,6 +74,13 @@ func (a PeerWrapperImpl) AskBlockSnapshot(id proto.BlockID) { a.p.SendMessage(&proto.GetBlockSnapshotMessage{BlockID: id}) } +func (a PeerWrapperImpl) AskMicroBlockSnapshot(id proto.BlockID) { + zap.S().Named(logging.NetworkNamespace).Debugf( + "[%s] Requesting micro block snapshot for micro block %s", a.p.ID().String(), id.ShortString(), + ) + a.p.SendMessage(&proto.MicroBlockSnapshotRequestMessage{BlockIDBytes: id.Bytes()}) +} + func (a PeerWrapperImpl) SendMicroBlock(micro *proto.MicroBlock) error { if a.p.Handshake().Version.Cmp(peerVersionWithProtobuf) < 0 { bts, err := micro.MarshalBinary(a.scheme) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index a604d4fab..32e564bf5 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -769,8 +769,11 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { return err } var blockSnapshots *proto.BlockSnapshot - - blockSnapshots, stateHash, err = a.appendTxs(params, checkerInfo, stateHash, hasher) + if params.snapshot != nil { + blockSnapshots, stateHash, err = a.applySnapshotsInLightNode(params, stateHash, hasher) + } else { + blockSnapshots, stateHash, err = a.appendTxs(params, checkerInfo, stateHash, hasher) + } if err != nil { return err } @@ -871,67 +874,6 @@ func (a *txAppender) createInitialDiffAndStateHash( return stateHash, nil } -func (a *txAppender) appendBlockWithSnapshot(params *appendBlockParams) error { - // Reset block complexity counter. - defer func() { - a.sc.resetComplexity() - a.totalScriptsRuns = 0 - }() - checkerInfo, err := a.createCheckerInfo(params) - if err != nil { - return err - } - hasParent := params.parent != nil - if hasParent { - checkerInfo.parentTimestamp = params.parent.Timestamp - } - stateActionsCounterInBlockValidation := new(proto.StateActionsCounter) - snapshotApplierInfo := newBlockSnapshotsApplierInfo(checkerInfo, a.settings.AddressSchemeCharacter, - stateActionsCounterInBlockValidation) - a.txHandler.sa.SetApplierInfo(snapshotApplierInfo) - blockInfo, err := a.currentBlockInfo() - if err != nil { - return errors.Wrapf(err, "failed to get current block info, blockchain height is %d", params.blockchainHeight) - } - currentBlockHeight := blockInfo.Height - hasher, err := newTxSnapshotHasherDefault() - if err != nil { - return errors.Wrapf(err, "failed to create tx snapshot default hasher, block height is %d", currentBlockHeight) - } - defer hasher.Release() - - stateHash, err := a.createInitialDiffAndStateHash(params, hasParent, blockInfo, hasher) - if err != nil { - return err - } - var blockSnapshots *proto.BlockSnapshot - - blockSnapshots, stateHash, err = a.applySnapshotsInLightNode(params, stateHash, hasher) - if err != nil { - return err - } - // check whether the calculated snapshot state hash equals with the provided one - if blockStateHash, present := params.block.GetStateHash(); present && blockStateHash != stateHash { - return errors.Wrapf(errBlockSnapshotStateHashMismatch, "state hash mismatch; provided '%s', caluclated '%s'", - blockStateHash.String(), stateHash.String(), - ) - } - blockID := params.block.BlockID() - if ssErr := a.stor.snapshots.saveSnapshots(blockID, currentBlockHeight, *blockSnapshots); ssErr != nil { - return errors.Wrapf(ssErr, "failed to save block snapshots at height %d", currentBlockHeight) - } - - // clean up legacy state hash records with zero diffs - a.txHandler.sa.filterZeroDiffsSHOut(blockID) - // TODO: check snapshot hash with the block snapshot hash if it exists - if shErr := a.stor.stateHashes.saveSnapshotStateHash(stateHash, currentBlockHeight, blockID); shErr != nil { - return errors.Wrapf(shErr, "failed to save block snapshot hash at height %d", currentBlockHeight) - } - // Save fee distribution of this block. - // This will be needed for createMinerAndRewardDiff() of next block due to NG. - return a.blockDiffer.saveCurFeeDistr(params.block) -} - // used only in tests now. All diffs are applied in snapshotApplier. func (a *txAppender) applyAllDiffs() error { a.recentTxIds = make(map[string]struct{}) diff --git a/pkg/state/state.go b/pkg/state/state.go index 4433a4c0b..de96f3925 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -606,7 +606,7 @@ func (s *stateManager) addGenesisBlock() error { chans := launchVerifier(ctx, s.verificationGoroutinesNum, s.settings.AddressSchemeCharacter) - if err := s.addNewBlock(s.genesis, nil, chans, 0, initSH); err != nil { + if err := s.addNewBlock(s.genesis, nil, chans, 0, nil, initSH); err != nil { return err } if err := s.stor.hitSources.appendBlockHitSource(s.genesis, 1, s.genesis.GenSignature); err != nil { @@ -1080,6 +1080,7 @@ func (s *stateManager) addNewBlock( block, parent *proto.Block, chans *verifierChans, blockchainHeight uint64, + snapshot *proto.BlockSnapshot, lastSnapshotStateHash crypto.Digest, ) error { blockHeight := blockchainHeight + 1 @@ -1101,6 +1102,7 @@ func (s *stateManager) addNewBlock( parent: parentHeader, blockchainHeight: blockchainHeight, lastSnapshotStateHash: lastSnapshotStateHash, + snapshot: snapshot, } // Check and perform block's transactions, create balance diffs, write transactions to storage. if err := s.appender.appendBlock(params); err != nil { @@ -1144,42 +1146,6 @@ func (s *stateManager) afterAppendBlock(block *proto.Block, blockHeight proto.He return nil } -func (s *stateManager) addNewBlockWithSnapshot( - block, parent *proto.Block, - chans *verifierChans, - blockchainHeight uint64, - snapshot *proto.BlockSnapshot, - lastSnapshotStateHash crypto.Digest, -) error { - blockHeight := blockchainHeight + 1 - if err := s.beforeAppendBlock(block, blockHeight); err != nil { - return err - } - transactions := block.Transactions - if block.TransactionCount != transactions.Count() { - return errors.Errorf( - "block.TransactionCount != transactions.Count(), %d != %d", block.TransactionCount, transactions.Count()) - } - var parentHeader *proto.BlockHeader - if parent != nil { - parentHeader = &parent.BlockHeader - } - params := &appendBlockParams{ - transactions: transactions, - chans: chans, - block: &block.BlockHeader, - parent: parentHeader, - blockchainHeight: blockchainHeight, - lastSnapshotStateHash: lastSnapshotStateHash, - snapshot: snapshot, - } - // Check and perform block's transactions, create balance diffs, write transactions to storage. - if err := s.appender.appendBlockWithSnapshot(params); err != nil { - return err - } - return s.afterAppendBlock(block, blockHeight) -} - func (s *stateManager) reset() { s.rw.reset() s.stor.reset() @@ -1206,7 +1172,7 @@ func (s *stateManager) flush() error { func (s *stateManager) AddBlock(block []byte) (*proto.Block, error) { s.newBlocks.setNewBinary([][]byte{block}) - rs, err := s.addBlocks() + rs, err := s.addBlocks(nil) if err != nil { if err := s.rw.syncWithDb(); err != nil { zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) @@ -1218,7 +1184,7 @@ func (s *stateManager) AddBlock(block []byte) (*proto.Block, error) { func (s *stateManager) AddDeserializedBlock(block *proto.Block) (*proto.Block, error) { s.newBlocks.setNew([]*proto.Block{block}) - rs, err := s.addBlocks() + rs, err := s.addBlocks(nil) if err != nil { if err := s.rw.syncWithDb(); err != nil { zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) @@ -1230,7 +1196,7 @@ func (s *stateManager) AddDeserializedBlock(block *proto.Block) (*proto.Block, e func (s *stateManager) AddBlocks(blockBytes [][]byte) error { s.newBlocks.setNewBinary(blockBytes) - if _, err := s.addBlocks(); err != nil { + if _, err := s.addBlocks(nil); err != nil { if err := s.rw.syncWithDb(); err != nil { zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) } @@ -1243,7 +1209,7 @@ func (s *stateManager) AddDeserializedBlocks( blocks []*proto.Block, ) (*proto.Block, error) { s.newBlocks.setNew(blocks) - lastBlock, err := s.addBlocks() + lastBlock, err := s.addBlocks(nil) if err != nil { if err = s.rw.syncWithDb(); err != nil { zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) @@ -1261,7 +1227,7 @@ func (s *stateManager) AddDeserializedBlocksWithSnapshots( return nil, errors.New("the numbers of snapshots doesn't match the number of blocks") } s.newBlocks.setNew(blocks) - lastBlock, err := s.addBlocksWithSnapshots(snapshots) + lastBlock, err := s.addBlocks(snapshots) if err != nil { if err := s.rw.syncWithDb(); err != nil { zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) @@ -1541,7 +1507,7 @@ func getSnapshotByIndIfNotNil(snapshots []*proto.BlockSnapshot, pos int) *proto. return snapshots[pos] } -func (s *stateManager) addBlocks() (*proto.Block, error) { +func (s *stateManager) addBlocks(snapshots []*proto.BlockSnapshot) (*proto.Block, error) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() defer func() { @@ -1598,6 +1564,7 @@ func (s *stateManager) addBlocks() (*proto.Block, error) { lastAppliedBlock, chans, blockchainCurHeight, + getSnapshotByIndIfNotNil(snapshots, pos), sh, ); addErr != nil { return nil, addErr @@ -1675,109 +1642,6 @@ func (s *stateManager) beforeAddingBlock( return s.stor.hitSources.appendBlockHitSource(block, blockchainCurHeight+1, hs) } -func (s *stateManager) addBlocksWithSnapshots( - snapshots []*proto.BlockSnapshot, -) (*proto.Block, error) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - defer func() { - // Reset in-memory storages and load last block in defer. - s.reset() - if err := s.loadLastBlock(); err != nil { - zap.S().Fatalf("Failed to load last block: %v", err) - } - s.newBlocks.reset() - }() - - blocksNumber := s.newBlocks.len() - if blocksNumber == 0 { - return nil, wrapErr(InvalidInputError, errors.New("no blocks provided")) - } - - // Read some useful values for later. - lastAppliedBlock, err := s.topBlock() - if err != nil { - return nil, wrapErr(RetrievalError, err) - } - zap.S().Debugf( - "StateManager: parent (top) block ID: %s, ts: %d", - lastAppliedBlock.BlockID().String(), lastAppliedBlock.Timestamp) - height, err := s.Height() - if err != nil { - return nil, wrapErr(RetrievalError, err) - } - headers := make([]proto.BlockHeader, blocksNumber) - - // Launch verifier that checks signatures of blocks and transactions. - chans := launchVerifier(ctx, s.verificationGoroutinesNum, s.settings.AddressSchemeCharacter) - - var ids []proto.BlockID - pos := 0 - for s.newBlocks.next() { - blockchainCurHeight := height + uint64(pos) - block, errCurBlock := s.newBlocks.current() - if errCurBlock != nil { - return nil, wrapErr(DeserializationError, errCurBlock) - } - - if err = s.beforeAddingBlock(block, lastAppliedBlock, blockchainCurHeight, chans); err != nil { - return nil, err - } - - sh, errSh := s.stor.stateHashes.newestSnapshotStateHash(blockchainCurHeight) - if errSh != nil { - return nil, errors.Wrapf(errSh, "failed to get newest snapshot state hash for height %d", - blockchainCurHeight, - ) - } - // Save block to storage, check its transactions, create and save balance diffs for its transactions. - if addErr := s.addNewBlockWithSnapshot( - block, - lastAppliedBlock, - chans, - blockchainCurHeight, - getSnapshotByIndIfNotNil(snapshots, pos), - sh, - ); addErr != nil { - return nil, addErr - } - - if s.needToFinishVotingPeriod(blockchainCurHeight + 1) { - // If we need to finish voting period on the next block (h+1) then - // we have to check that protobuf will be activated on next block - s.checkProtobufActivation(blockchainCurHeight + 2) - } - headers[pos] = block.BlockHeader - pos++ - ids = append(ids, block.BlockID()) - lastAppliedBlock = block - } - // Tasks chan can now be closed, since all the blocks and transactions have been already sent for verification. - // wait for all verifier goroutines - if verifyError := chans.closeAndWait(); verifyError != nil { - return nil, wrapErr(ValidationError, verifyError) - } - - // Retrieve and store legacy state hashes for each of new blocks. - if shErr := s.stor.handleLegacyStateHashes(height, ids); shErr != nil { - return nil, wrapErr(ModificationError, shErr) - } - // Validate consensus (i.e. that all the new blocks were mined fairly). - if err = s.cv.ValidateHeadersBatch(headers[:pos], height); err != nil { - return nil, wrapErr(ValidationError, err) - } - // After everything is validated, save all the changes to DB. - if err = s.flush(); err != nil { - return nil, wrapErr(ModificationError, err) - } - zap.S().Infof( - "Height: %d; Block ID: %s, GenSig: %s, ts: %d", height+uint64(blocksNumber), - lastAppliedBlock.BlockID().String(), base58.Encode(lastAppliedBlock.GenSignature), - lastAppliedBlock.Timestamp, - ) - return lastAppliedBlock, nil -} - func (s *stateManager) checkRollbackHeight(height uint64) error { maxHeight, err := s.Height() if err != nil { From 388a770431252e395fd5c375066e0cdd8820bcd7 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Tue, 30 Jan 2024 03:34:05 +0300 Subject: [PATCH 102/139] Fixed bug in 'MicroBlockCache.GetSnapshot'. --- pkg/libs/microblock_cache/microblock_cache.go | 20 ++++++++++++++++--- pkg/node/fsm/ng_state.go | 4 ++-- pkg/services/services.go | 1 + 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/pkg/libs/microblock_cache/microblock_cache.go b/pkg/libs/microblock_cache/microblock_cache.go index 904bf5f57..10e58cac3 100644 --- a/pkg/libs/microblock_cache/microblock_cache.go +++ b/pkg/libs/microblock_cache/microblock_cache.go @@ -8,8 +8,8 @@ import ( const microBlockCacheSize = 24 type microBlockWithSnapshot struct { - microBlock *proto.MicroBlock - snapshot *proto.BlockSnapshot + microBlock *proto.MicroBlock // always not nil + snapshot *proto.BlockSnapshot // can be nil } type MicroBlockCache struct { @@ -22,6 +22,16 @@ func NewMicroBlockCache() *MicroBlockCache { } } +func (a *MicroBlockCache) AddMicroBlock( + blockID proto.BlockID, + micro *proto.MicroBlock, +) { + a.cache.Add2(blockID.Bytes(), µBlockWithSnapshot{ + microBlock: micro, + snapshot: nil, // intentionally nil + }) +} + func (a *MicroBlockCache) AddMicroBlockWithSnapshot( blockID proto.BlockID, micro *proto.MicroBlock, @@ -46,7 +56,11 @@ func (a *MicroBlockCache) GetSnapshot(sig proto.BlockID) (*proto.BlockSnapshot, if !ok { return nil, false } - return rs.(*microBlockWithSnapshot).snapshot, true + var ( + snapshot = rs.(*microBlockWithSnapshot).snapshot + existInCache = snapshot != nil + ) + return snapshot, existInCache } type MicroblockInvCache struct { diff --git a/pkg/node/fsm/ng_state.go b/pkg/node/fsm/ng_state.go index b286cb12f..e5ee9b2fb 100644 --- a/pkg/node/fsm/ng_state.go +++ b/pkg/node/fsm/ng_state.go @@ -233,7 +233,7 @@ func (a *NGState) MicroBlock(p peer.Peer, micro *proto.MicroBlock) (State, Async "[%s] Received microblock '%s' (referencing '%s') successfully applied to state", a, block.BlockID(), micro.Reference, ) - a.baseInfo.MicroBlockCache.AddMicroBlockWithSnapshot(block.BlockID(), micro, nil) + a.baseInfo.MicroBlockCache.AddMicroBlock(block.BlockID(), micro) a.blocksCache.AddBlockState(block) return a, nil, nil } @@ -285,7 +285,7 @@ func (a *NGState) mineMicro( return a, nil, a.Errorf(errors.Wrap(err, "failed to broadcast generated microblock")) } - a.baseInfo.MicroBlockCache.AddMicroBlockWithSnapshot(block.BlockID(), micro, nil) + a.baseInfo.MicroBlockCache.AddMicroBlock(block.BlockID(), micro) a.baseInfo.MicroBlockInvCache.Add(block.BlockID(), inv) return a, tasks.Tasks(tasks.NewMineMicroTask(a.baseInfo.microblockInterval, block, rest, keyPair, vrf)), nil diff --git a/pkg/services/services.go b/pkg/services/services.go index 015a67605..635c5db96 100644 --- a/pkg/services/services.go +++ b/pkg/services/services.go @@ -32,6 +32,7 @@ type BlocksApplier interface { } type MicroBlockCache interface { + AddMicroBlock(blockID proto.BlockID, micro *proto.MicroBlock) AddMicroBlockWithSnapshot(blockID proto.BlockID, micro *proto.MicroBlock, snapshot *proto.BlockSnapshot) GetBlock(sig proto.BlockID) (*proto.MicroBlock, bool) GetSnapshot(sig proto.BlockID) (*proto.BlockSnapshot, bool) From 38aab2a0918f72551f262be2df1aedaf4df5f8b4 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Tue, 30 Jan 2024 05:06:34 +0300 Subject: [PATCH 103/139] Add block snapshots as an optional return parameter for 'newBlocks.current'. --- pkg/state/appender.go | 65 +++++++++++++++++++++++------------------- pkg/state/state.go | 66 ++++++++++++++++++++++++++----------------- 2 files changed, 76 insertions(+), 55 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 32e564bf5..8e6269fbf 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -157,7 +157,7 @@ type appendBlockParams struct { block, parent *proto.BlockHeader blockchainHeight proto.Height lastSnapshotStateHash crypto.Digest - snapshot *proto.BlockSnapshot + optionalSnapshot *proto.BlockSnapshot } func (a *txAppender) orderIsScripted(order proto.Order) (bool, error) { @@ -614,36 +614,41 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) (txS return snapshot, nil } -func (a *txAppender) applySnapshotsInLightNode( +func (a *txAppender) applySnapshotInLightNode( params *appendBlockParams, + snapshot proto.BlockSnapshot, stateHash crypto.Digest, hasher *txSnapshotHasher, -) (*proto.BlockSnapshot, crypto.Digest, error) { +) (crypto.Digest, error) { + if len(snapshot.TxSnapshots) != len(params.transactions) { // sanity check + return crypto.Digest{}, errors.New("number of tx snapshots doesn't match number of transactions") + } blockInfo, errBlockInfo := a.currentBlockInfo() if errBlockInfo != nil { - return nil, crypto.Digest{}, errBlockInfo + return crypto.Digest{}, errBlockInfo } - for i, txs := range params.snapshot.TxSnapshots { - txID, idErr := params.transactions[i].GetID(a.settings.AddressSchemeCharacter) + for i, txs := range snapshot.TxSnapshots { + tx := params.transactions[i] + txID, idErr := tx.GetID(a.settings.AddressSchemeCharacter) if idErr != nil { - return nil, crypto.Digest{}, idErr + return crypto.Digest{}, idErr } if len(txs) == 0 { // sanity check - return nil, crypto.Digest{}, errors.Errorf("snapshot of txID %q cannot be empty", base58.Encode(txID)) + return crypto.Digest{}, errors.Errorf("snapshot of txID %q cannot be empty", base58.Encode(txID)) } txSh, shErr := calculateTxSnapshotStateHash(hasher, txID, blockInfo.Height, stateHash, txs) if shErr != nil { - return nil, crypto.Digest{}, errors.Wrapf(shErr, "failed to calculate tx snapshot hash for txID %q at height %d", + return crypto.Digest{}, errors.Wrapf(shErr, "failed to calculate tx snapshot hash for txID %q at height %d", base58.Encode(txID), blockInfo.Height, ) } stateHash = txSh regSnapshots := txSnapshot{regular: txs} - if err := regSnapshots.Apply(a.txHandler.sa, params.transactions[i], false); err != nil { - return nil, crypto.Digest{}, errors.Wrap(err, "failed to apply tx snapshot") + if err := regSnapshots.Apply(a.txHandler.sa, tx, false); err != nil { + return crypto.Digest{}, errors.Wrap(err, "failed to apply tx snapshot") } } - return params.snapshot, stateHash, nil + return stateHash, nil } func (a *txAppender) appendTxs( @@ -651,26 +656,26 @@ func (a *txAppender) appendTxs( info *checkerInfo, stateHash crypto.Digest, hasher *txSnapshotHasher, -) (*proto.BlockSnapshot, crypto.Digest, error) { +) (proto.BlockSnapshot, crypto.Digest, error) { blockInfo, errBlockInfo := a.currentBlockInfo() if errBlockInfo != nil { - return nil, crypto.Digest{}, errBlockInfo + return proto.BlockSnapshot{}, crypto.Digest{}, errBlockInfo } blockV5Activated, err := a.stor.features.newestIsActivated(int16(settings.BlockV5)) if err != nil { - return nil, crypto.Digest{}, err + return proto.BlockSnapshot{}, crypto.Digest{}, err } consensusImprovementsActivated, err := a.stor.features.newestIsActivated(int16(settings.ConsensusImprovements)) if err != nil { - return nil, crypto.Digest{}, err + return proto.BlockSnapshot{}, crypto.Digest{}, err } blockRewardDistributionActivated, err := a.stor.features.newestIsActivated(int16(settings.BlockRewardDistribution)) if err != nil { - return nil, crypto.Digest{}, err + return proto.BlockSnapshot{}, crypto.Digest{}, err } invokeExpressionActivated, err := a.stor.features.newestIsActivated(int16(settings.InvokeExpression)) if err != nil { - return nil, crypto.Digest{}, err + return proto.BlockSnapshot{}, crypto.Digest{}, err } // Check and append transactions. var bs proto.BlockSnapshot @@ -692,27 +697,28 @@ func (a *txAppender) appendTxs( for _, tx := range params.transactions { txSnapshots, errAppendTx := a.appendTx(tx, appendTxArgs) if errAppendTx != nil { - return nil, crypto.Digest{}, errAppendTx + return proto.BlockSnapshot{}, crypto.Digest{}, errAppendTx } bs.AppendTxSnapshot(txSnapshots.regular) txID, idErr := tx.GetID(a.settings.AddressSchemeCharacter) if idErr != nil { - return nil, crypto.Digest{}, idErr + return proto.BlockSnapshot{}, crypto.Digest{}, idErr } if len(txSnapshots.regular) == 0 { // sanity check - return nil, crypto.Digest{}, errors.Errorf("snapshot of txID %q cannot be empty", base58.Encode(txID)) + return proto.BlockSnapshot{}, crypto.Digest{}, + errors.Errorf("snapshot of txID %q cannot be empty", base58.Encode(txID)) } txSh, shErr := calculateTxSnapshotStateHash(hasher, txID, blockInfo.Height, stateHash, txSnapshots.regular) if shErr != nil { - return nil, crypto.Digest{}, errors.Wrapf(shErr, "failed to calculate tx snapshot hash for txID %q at height %d", - base58.Encode(txID), blockInfo.Height, + return proto.BlockSnapshot{}, crypto.Digest{}, errors.Wrapf(shErr, + "failed to calculate tx snapshot hash for txID %q at height %d", base58.Encode(txID), blockInfo.Height, ) } stateHash = txSh // update stateHash in order to accumulate state hashes into block snapshot hash } - return &bs, stateHash, nil + return bs, stateHash, nil } func calculateInitialSnapshotStateHash( @@ -768,11 +774,12 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { if err != nil { return err } - var blockSnapshots *proto.BlockSnapshot - if params.snapshot != nil { - blockSnapshots, stateHash, err = a.applySnapshotsInLightNode(params, stateHash, hasher) + var blockSnapshot proto.BlockSnapshot + if params.optionalSnapshot != nil { + blockSnapshot = *params.optionalSnapshot + stateHash, err = a.applySnapshotInLightNode(params, blockSnapshot, stateHash, hasher) } else { - blockSnapshots, stateHash, err = a.appendTxs(params, checkerInfo, stateHash, hasher) + blockSnapshot, stateHash, err = a.appendTxs(params, checkerInfo, stateHash, hasher) } if err != nil { return err @@ -785,7 +792,7 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { } blockID := params.block.BlockID() - if ssErr := a.stor.snapshots.saveSnapshots(blockID, currentBlockHeight, *blockSnapshots); ssErr != nil { + if ssErr := a.stor.snapshots.saveSnapshots(blockID, currentBlockHeight, blockSnapshot); ssErr != nil { return ssErr } // clean up legacy state hash records with zero diffs diff --git a/pkg/state/state.go b/pkg/state/state.go index de96f3925..9c15159b4 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -264,6 +264,7 @@ type newBlocks struct { binary bool binBlocks [][]byte blocks []*proto.Block + snapshots []*proto.BlockSnapshot curPos int rw *blockReadWriter @@ -302,6 +303,17 @@ func (n *newBlocks) setNew(blocks []*proto.Block) { n.binary = false } +func (n *newBlocks) setNewWithSnapshots(blocks []*proto.Block, snapshots []*proto.BlockSnapshot) error { + if len(blocks) != len(snapshots) { + return errors.New("the numbers of snapshots doesn't match the number of blocks") + } + n.reset() + n.blocks = blocks + n.snapshots = snapshots + n.binary = false + return nil +} + func (n *newBlocks) next() bool { n.curPos++ if n.binary { @@ -324,27 +336,37 @@ func (n *newBlocks) unmarshalBlock(block *proto.Block, blockBytes []byte) error return nil } -func (n *newBlocks) current() (*proto.Block, error) { +func (n *newBlocks) current() (*proto.Block, *proto.BlockSnapshot, error) { if !n.binary { if n.curPos > len(n.blocks) || n.curPos < 1 { - return nil, errors.New("bad current position") + return nil, nil, errors.New("bad current position") } - return n.blocks[n.curPos-1], nil + var ( + pos = n.curPos - 1 + block = n.blocks[pos] + optionalSnapshot *proto.BlockSnapshot + ) + if len(n.snapshots) == len(n.blocks) { // return snapshot if it is set + optionalSnapshot = n.snapshots[pos] + return block, optionalSnapshot, nil + } + return block, optionalSnapshot, nil } if n.curPos > len(n.binBlocks) || n.curPos < 1 { - return nil, errors.New("bad current position") + return nil, nil, errors.New("bad current position") } blockBytes := n.binBlocks[n.curPos-1] b := &proto.Block{} if err := n.unmarshalBlock(b, blockBytes); err != nil { - return nil, err + return nil, nil, err } - return b, nil + return b, nil, nil } func (n *newBlocks) reset() { n.binBlocks = nil n.blocks = nil + n.snapshots = nil n.curPos = 0 } @@ -1080,7 +1102,7 @@ func (s *stateManager) addNewBlock( block, parent *proto.Block, chans *verifierChans, blockchainHeight uint64, - snapshot *proto.BlockSnapshot, + optionalSnapshot *proto.BlockSnapshot, lastSnapshotStateHash crypto.Digest, ) error { blockHeight := blockchainHeight + 1 @@ -1102,7 +1124,7 @@ func (s *stateManager) addNewBlock( parent: parentHeader, blockchainHeight: blockchainHeight, lastSnapshotStateHash: lastSnapshotStateHash, - snapshot: snapshot, + optionalSnapshot: optionalSnapshot, } // Check and perform block's transactions, create balance diffs, write transactions to storage. if err := s.appender.appendBlock(params); err != nil { @@ -1172,7 +1194,7 @@ func (s *stateManager) flush() error { func (s *stateManager) AddBlock(block []byte) (*proto.Block, error) { s.newBlocks.setNewBinary([][]byte{block}) - rs, err := s.addBlocks(nil) + rs, err := s.addBlocks() if err != nil { if err := s.rw.syncWithDb(); err != nil { zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) @@ -1184,7 +1206,7 @@ func (s *stateManager) AddBlock(block []byte) (*proto.Block, error) { func (s *stateManager) AddDeserializedBlock(block *proto.Block) (*proto.Block, error) { s.newBlocks.setNew([]*proto.Block{block}) - rs, err := s.addBlocks(nil) + rs, err := s.addBlocks() if err != nil { if err := s.rw.syncWithDb(); err != nil { zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) @@ -1196,7 +1218,7 @@ func (s *stateManager) AddDeserializedBlock(block *proto.Block) (*proto.Block, e func (s *stateManager) AddBlocks(blockBytes [][]byte) error { s.newBlocks.setNewBinary(blockBytes) - if _, err := s.addBlocks(nil); err != nil { + if _, err := s.addBlocks(); err != nil { if err := s.rw.syncWithDb(); err != nil { zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) } @@ -1209,7 +1231,7 @@ func (s *stateManager) AddDeserializedBlocks( blocks []*proto.Block, ) (*proto.Block, error) { s.newBlocks.setNew(blocks) - lastBlock, err := s.addBlocks(nil) + lastBlock, err := s.addBlocks() if err != nil { if err = s.rw.syncWithDb(); err != nil { zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) @@ -1223,11 +1245,10 @@ func (s *stateManager) AddDeserializedBlocksWithSnapshots( blocks []*proto.Block, snapshots []*proto.BlockSnapshot, ) (*proto.Block, error) { - if len(blocks) != len(snapshots) { - return nil, errors.New("the numbers of snapshots doesn't match the number of blocks") + if err := s.newBlocks.setNewWithSnapshots(blocks, snapshots); err != nil { + return nil, errors.Wrap(err, "failed to set new blocks with snapshots") } - s.newBlocks.setNew(blocks) - lastBlock, err := s.addBlocks(snapshots) + lastBlock, err := s.addBlocks() if err != nil { if err := s.rw.syncWithDb(); err != nil { zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", err) @@ -1500,14 +1521,7 @@ func (s *stateManager) recalculateVotesAfterCappedRewardActivationInVotingPeriod return nil } -func getSnapshotByIndIfNotNil(snapshots []*proto.BlockSnapshot, pos int) *proto.BlockSnapshot { - if len(snapshots) == 0 { - return nil - } - return snapshots[pos] -} - -func (s *stateManager) addBlocks(snapshots []*proto.BlockSnapshot) (*proto.Block, error) { +func (s *stateManager) addBlocks() (*proto.Block, error) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() defer func() { @@ -1543,7 +1557,7 @@ func (s *stateManager) addBlocks(snapshots []*proto.BlockSnapshot) (*proto.Block pos := 0 for s.newBlocks.next() { blockchainCurHeight := height + uint64(pos) - block, errCurBlock := s.newBlocks.current() + block, optionalSnapshot, errCurBlock := s.newBlocks.current() if errCurBlock != nil { return nil, wrapErr(DeserializationError, errCurBlock) } @@ -1564,7 +1578,7 @@ func (s *stateManager) addBlocks(snapshots []*proto.BlockSnapshot) (*proto.Block lastAppliedBlock, chans, blockchainCurHeight, - getSnapshotByIndIfNotNil(snapshots, pos), + optionalSnapshot, sh, ); addErr != nil { return nil, addErr From dd7c9bf3a1bc940227ccc922b8d068cabab563c1 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Tue, 30 Jan 2024 11:52:49 +0300 Subject: [PATCH 104/139] move snapshot requests to defer --- pkg/node/fsm/ng_state.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pkg/node/fsm/ng_state.go b/pkg/node/fsm/ng_state.go index e5ee9b2fb..11811ec60 100644 --- a/pkg/node/fsm/ng_state.go +++ b/pkg/node/fsm/ng_state.go @@ -169,8 +169,10 @@ func (a *NGState) Block(peer peer.Peer, block *proto.Block) (State, Async, error } if a.baseInfo.enableLightMode { - pe := extension.NewPeerExtension(peer, a.baseInfo.scheme) - pe.AskBlockSnapshot(block.BlockID()) + defer func() { + pe := extension.NewPeerExtension(peer, a.baseInfo.scheme) + pe.AskBlockSnapshot(block.BlockID()) + }() st, timeoutTask := newWaitSnapshotState(a.baseInfo, block, a.blocksCache) return st, tasks.Tasks(timeoutTask), nil } @@ -237,8 +239,10 @@ func (a *NGState) MicroBlock(p peer.Peer, micro *proto.MicroBlock) (State, Async a.blocksCache.AddBlockState(block) return a, nil, nil } - pe := extension.NewPeerExtension(p, a.baseInfo.scheme) - pe.AskMicroBlockSnapshot(micro.TotalBlockID) + defer func() { + pe := extension.NewPeerExtension(p, a.baseInfo.scheme) + pe.AskMicroBlockSnapshot(micro.TotalBlockID) + }() st, timeoutTask := newWaitMicroSnapshotState(a.baseInfo, micro, a.blocksCache) return st, tasks.Tasks(timeoutTask), nil } From 3a2ea6983bdfe651a38995c7973f54289516a622 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Wed, 31 Jan 2024 01:21:39 +0300 Subject: [PATCH 105/139] Refactor a bit 'newBlocks.current'. --- pkg/state/state.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/state/state.go b/pkg/state/state.go index 9c15159b4..9acc28361 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -346,9 +346,8 @@ func (n *newBlocks) current() (*proto.Block, *proto.BlockSnapshot, error) { block = n.blocks[pos] optionalSnapshot *proto.BlockSnapshot ) - if len(n.snapshots) == len(n.blocks) { // return snapshot if it is set + if len(n.snapshots) == len(n.blocks) { // return block with snapshot if it is set optionalSnapshot = n.snapshots[pos] - return block, optionalSnapshot, nil } return block, optionalSnapshot, nil } From d4db37f296fb6c7ea40f3d978723836b62ce0d58 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Fri, 9 Feb 2024 01:23:32 +0300 Subject: [PATCH 106/139] Linter fixes. --- pkg/node/fsm/fsm_common.go | 2 +- pkg/node/fsm/halt_state.go | 2 +- pkg/node/fsm/idle_state.go | 2 +- pkg/node/fsm/persist_state.go | 2 +- pkg/node/fsm/wait_micro_snapshot.go | 4 ++-- pkg/node/fsm/wait_snapshot_state.go | 4 ++-- pkg/proto/proto.go | 16 ++++++++-------- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/pkg/node/fsm/fsm_common.go b/pkg/node/fsm/fsm_common.go index 6b8fb0977..b75e92153 100644 --- a/pkg/node/fsm/fsm_common.go +++ b/pkg/node/fsm/fsm_common.go @@ -220,7 +220,7 @@ func broadcastMicroBlockInv(info BaseInfo, inv *proto.MicroBlockInv) error { Body: invBts, } ) - info.peers.EachConnected(func(p peer.Peer, score *proto.Score) { + info.peers.EachConnected(func(p peer.Peer, _ *proto.Score) { p.SendMessage(msg) cnt++ }) diff --git a/pkg/node/fsm/halt_state.go b/pkg/node/fsm/halt_state.go index 5a074fe82..2d2722a76 100644 --- a/pkg/node/fsm/halt_state.go +++ b/pkg/node/fsm/halt_state.go @@ -54,7 +54,7 @@ func initHaltStateInFSM(_ *StateData, fsm *stateless.StateMachine, info BaseInfo proto.ContentIDPBBlock, proto.ContentIDPBMicroBlock, proto.ContentIDPBTransaction, - proto.ContentIDGetBlockIds, + proto.ContentIDGetBlockIDs, proto.ContentIDBlockSnapshot, proto.ContentIDGetBlockSnapshot, proto.ContentIDMicroBlockSnapshot, diff --git a/pkg/node/fsm/idle_state.go b/pkg/node/fsm/idle_state.go index 9e4b41106..c915419a1 100644 --- a/pkg/node/fsm/idle_state.go +++ b/pkg/node/fsm/idle_state.go @@ -110,7 +110,7 @@ func initIdleStateInFSM(state *StateData, fsm *stateless.StateMachine, b BaseInf proto.ContentIDPBBlock, proto.ContentIDPBMicroBlock, proto.ContentIDPBTransaction, - proto.ContentIDBlockIds, + proto.ContentIDBlockIDs, proto.ContentIDBlockSnapshot, proto.ContentIDMicroBlockSnapshot, proto.ContentIDMicroBlockSnapshotRequest, diff --git a/pkg/node/fsm/persist_state.go b/pkg/node/fsm/persist_state.go index 1bec34962..ca1162575 100644 --- a/pkg/node/fsm/persist_state.go +++ b/pkg/node/fsm/persist_state.go @@ -76,7 +76,7 @@ func initPersistStateInFSM(state *StateData, fsm *stateless.StateMachine, info B proto.ContentIDPBBlock, proto.ContentIDPBMicroBlock, proto.ContentIDPBTransaction, - proto.ContentIDGetBlockIds, + proto.ContentIDGetBlockIDs, proto.ContentIDBlockSnapshot, proto.ContentIDMicroBlockSnapshot, proto.ContentIDGetBlockSnapshot, diff --git a/pkg/node/fsm/wait_micro_snapshot.go b/pkg/node/fsm/wait_micro_snapshot.go index 75671acde..b46e871e8 100644 --- a/pkg/node/fsm/wait_micro_snapshot.go +++ b/pkg/node/fsm/wait_micro_snapshot.go @@ -197,11 +197,11 @@ func initWaitMicroSnapshotStateInFSM(state *StateData, fsm *stateless.StateMachi proto.ContentIDPBBlock, proto.ContentIDPBMicroBlock, proto.ContentIDPBTransaction, - proto.ContentIDGetBlockIds, + proto.ContentIDGetBlockIDs, proto.ContentIDBlockSnapshot, } fsm.Configure(WaitSnapshotStateName). //nolint:dupl // it's state setup - OnEntry(func(ctx context.Context, args ...interface{}) error { + OnEntry(func(_ context.Context, _ ...interface{}) error { info.skipMessageList.SetList(waitSnapshotSkipMessageList) return nil }). diff --git a/pkg/node/fsm/wait_snapshot_state.go b/pkg/node/fsm/wait_snapshot_state.go index be15dbe63..5a1456c9a 100644 --- a/pkg/node/fsm/wait_snapshot_state.go +++ b/pkg/node/fsm/wait_snapshot_state.go @@ -132,10 +132,10 @@ func initWaitSnapshotStateInFSM(state *StateData, fsm *stateless.StateMachine, i proto.ContentIDPBBlock, proto.ContentIDPBMicroBlock, proto.ContentIDPBTransaction, - proto.ContentIDGetBlockIds, + proto.ContentIDGetBlockIDs, } fsm.Configure(WaitSnapshotStateName). //nolint:dupl // it's state setup - OnEntry(func(ctx context.Context, args ...interface{}) error { + OnEntry(func(_ context.Context, _ ...interface{}) error { info.skipMessageList.SetList(waitSnapshotSkipMessageList) return nil }). diff --git a/pkg/proto/proto.go b/pkg/proto/proto.go index de5684101..8566172c0 100644 --- a/pkg/proto/proto.go +++ b/pkg/proto/proto.go @@ -49,8 +49,8 @@ const ( ContentIDPBBlock PeerMessageID = 29 ContentIDPBMicroBlock PeerMessageID = 30 ContentIDPBTransaction PeerMessageID = 31 - ContentIDGetBlockIds PeerMessageID = 32 - ContentIDBlockIds PeerMessageID = 33 + ContentIDGetBlockIDs PeerMessageID = 32 + ContentIDBlockIDs PeerMessageID = 33 ContentIDGetBlockSnapshot PeerMessageID = 34 ContentIDMicroBlockSnapshotRequest PeerMessageID = 35 ContentIDBlockSnapshot PeerMessageID = 36 @@ -1811,9 +1811,9 @@ func UnmarshalMessage(b []byte) (Message, error) { m = &PBMicroBlockMessage{} case ContentIDPBTransaction: m = &PBTransactionMessage{} - case ContentIDGetBlockIds: + case ContentIDGetBlockIDs: m = &GetBlockIdsMessage{} - case ContentIDBlockIds: + case ContentIDBlockIDs: m = &BlockIdsMessage{} case ContentIDGetBlockSnapshot: m = &GetBlockSnapshotMessage{} @@ -1851,7 +1851,7 @@ func (m *GetBlockIdsMessage) MarshalBinary() ([]byte, error) { var h Header h.Length = maxHeaderLength + uint32(len(body)) - 4 h.Magic = headerMagic - h.ContentID = ContentIDGetBlockIds + h.ContentID = ContentIDGetBlockIDs h.PayloadLength = uint32(len(body)) dig, err := crypto.FastHash(body) if err != nil { @@ -1880,7 +1880,7 @@ func (m *GetBlockIdsMessage) UnmarshalBinary(data []byte) error { if h.Magic != headerMagic { return fmt.Errorf("wrong magic in Header: %x", h.Magic) } - if h.ContentID != ContentIDGetBlockIds { + if h.ContentID != ContentIDGetBlockIDs { return fmt.Errorf("wrong ContentID in Header: %x", h.ContentID) } data = data[17:] @@ -1947,7 +1947,7 @@ func (m *BlockIdsMessage) MarshalBinary() ([]byte, error) { var h Header h.Length = maxHeaderLength + uint32(len(body)) - 4 h.Magic = headerMagic - h.ContentID = ContentIDBlockIds + h.ContentID = ContentIDBlockIDs h.PayloadLength = uint32(len(body)) dig, err := crypto.FastHash(body) if err != nil { @@ -1977,7 +1977,7 @@ func (m *BlockIdsMessage) UnmarshalBinary(data []byte) error { if h.Magic != headerMagic { return fmt.Errorf("wrong magic in Header: %x", h.Magic) } - if h.ContentID != ContentIDBlockIds { + if h.ContentID != ContentIDBlockIDs { return fmt.Errorf("wrong ContentID in Header: %x", h.ContentID) } data = data[17:] From 76bf98b1b036abfd678d7e913f370d168cfde94f Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Mon, 12 Feb 2024 12:09:17 +0300 Subject: [PATCH 107/139] Remove irrelevant TODO. --- pkg/grpc/protobuf-schemas | 2 +- pkg/state/appender.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/grpc/protobuf-schemas b/pkg/grpc/protobuf-schemas index 5ca3b91d6..4bd52dd19 160000 --- a/pkg/grpc/protobuf-schemas +++ b/pkg/grpc/protobuf-schemas @@ -1 +1 @@ -Subproject commit 5ca3b91d65462b649f2b4406e29d31a8bb6f5104 +Subproject commit 4bd52dd19c3dd73f49d4dab21861e89955f97ed2 diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 94c49bc6b..cb3ae26a8 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -797,7 +797,7 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { } // clean up legacy state hash records with zero diffs a.txHandler.sa.filterZeroDiffsSHOut(blockID) - // TODO: check snapshot hash with the block snapshot hash if it exists + if shErr := a.stor.stateHashes.saveSnapshotStateHash(stateHash, currentBlockHeight, blockID); shErr != nil { return errors.Wrapf(shErr, "failed to save block shasnpt hash at height %d", currentBlockHeight) } From 3c118c6bef0cc4f12290f03be09a1c1592660002 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Mon, 19 Feb 2024 14:31:04 +0300 Subject: [PATCH 108/139] fix channel size for proto msgs --- cmd/node/node.go | 2 +- cmd/retransmitter/main.go | 2 +- pkg/node/fsm/sync_state.go | 6 ++---- pkg/p2p/peer/handle_test.go | 6 +++--- pkg/p2p/peer/peer.go | 9 +++++++-- pkg/proto/protobuf_converters.go | 18 +++++++++--------- 6 files changed, 23 insertions(+), 20 deletions(-) diff --git a/cmd/node/node.go b/cmd/node/node.go index 64222de70..ec90a0af5 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -421,7 +421,7 @@ func main() { return } utx := utxpool.New(uint64(1024*mb), utxValidator, cfg) - parent := peer.NewParent() + parent := peer.NewParent(nc.enableLightMode) nodeNonce, err := rand.Int(rand.Reader, new(big.Int).SetUint64(math.MaxInt32)) if err != nil { diff --git a/cmd/retransmitter/main.go b/cmd/retransmitter/main.go index 07f619586..7ae2cd9a3 100644 --- a/cmd/retransmitter/main.go +++ b/cmd/retransmitter/main.go @@ -131,7 +131,7 @@ func main() { return } - parent := peer.NewParent() + parent := peer.NewParent(false) spawner := retransmit.NewPeerSpawner(skipUselessMessages, parent, wavesNetwork, declAddr) scheme := schemes[wavesNetwork] behaviour := retransmit.NewBehaviour(knownPeers, spawner, scheme) diff --git a/pkg/node/fsm/sync_state.go b/pkg/node/fsm/sync_state.go index f874934df..a8175b69a 100644 --- a/pkg/node/fsm/sync_state.go +++ b/pkg/node/fsm/sync_state.go @@ -182,10 +182,7 @@ func (a *SyncState) Block(p peer.Peer, block *proto.Block) (State, Async, error) if err != nil { return newSyncState(a.baseInfo, a.conf, internal), nil, a.Errorf(err) } - if !a.baseInfo.enableLightMode { - return a.applyBlocksWithSnapshots(a.baseInfo, a.conf.Now(a.baseInfo.tm), internal) - } - return a, nil, nil + return a.applyBlocksWithSnapshots(a.baseInfo, a.conf.Now(a.baseInfo.tm), internal) } func (a *SyncState) BlockSnapshot( @@ -196,6 +193,7 @@ func (a *SyncState) BlockSnapshot( if !p.Equal(a.conf.peerSyncWith) { return a, nil, nil } + zap.S().Named(logging.FSMNamespace).Debugf("[Sync][%s] Received snapshot for block %s", p.ID(), blockID.String()) internal, err := a.internal.SetSnapshot(blockID, &snapshot) if err != nil { return newSyncState(a.baseInfo, a.conf, internal), nil, a.Errorf(err) diff --git a/pkg/p2p/peer/handle_test.go b/pkg/p2p/peer/handle_test.go index e2e16c97d..4c38b0571 100644 --- a/pkg/p2p/peer/handle_test.go +++ b/pkg/p2p/peer/handle_test.go @@ -29,7 +29,7 @@ func TestHandleStopContext(t *testing.T) { <-time.After(1 * time.Millisecond) cancel() }() - parent := NewParent() + parent := NewParent(false) remote := NewRemote() peer := &mockPeer{CloseFunc: func() error { return nil }} err := Handle(ctx, peer, parent, remote) @@ -44,7 +44,7 @@ func TestHandleStopContext(t *testing.T) { func TestHandleReceive(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) remote := NewRemote() - parent := NewParent() + parent := NewParent(false) var wg sync.WaitGroup wg.Add(1) go func() { @@ -69,7 +69,7 @@ func TestHandleReceive(t *testing.T) { func TestHandleError(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) remote := NewRemote() - parent := NewParent() + parent := NewParent(false) var wg sync.WaitGroup wg.Add(1) go func() { diff --git a/pkg/p2p/peer/peer.go b/pkg/p2p/peer/peer.go index d603ebb60..66b4a19cd 100644 --- a/pkg/p2p/peer/peer.go +++ b/pkg/p2p/peer/peer.go @@ -28,9 +28,14 @@ type Parent struct { SkipMessageList *messages.SkipMessageList } -func NewParent() Parent { +func NewParent(enableLightNode bool) Parent { + messageChSize := 100 + if enableLightNode { + // because in light node we send block and snapshot request messages + messageChSize = 200 + } return Parent{ - MessageCh: make(chan ProtoMessage, 100), + MessageCh: make(chan ProtoMessage, messageChSize), InfoCh: make(chan InfoMessage, 100), SkipMessageList: &messages.SkipMessageList{}, } diff --git a/pkg/proto/protobuf_converters.go b/pkg/proto/protobuf_converters.go index 2b6672467..8a0cb3dd4 100644 --- a/pkg/proto/protobuf_converters.go +++ b/pkg/proto/protobuf_converters.go @@ -225,13 +225,13 @@ func sponsorshipFromProto(txSnapshotProto *g.TransactionStateSnapshot, res *[]At return nil } -// TxSnapshotsFromProtobuf Unmarshalling order (how in proto schemas): -// WavesBalances and AssetBalances -// LeaseBalances +// TxSnapshotsFromProtobuf Unmarshalling order (don't change it if it is not necessary, order is important): // NewAsset // AssetVolume // AssetDescription // AssetScript +// WavesBalances and AssetBalances +// LeaseBalances // Alias // FilledVolumes // NewLeases @@ -242,27 +242,27 @@ func sponsorshipFromProto(txSnapshotProto *g.TransactionStateSnapshot, res *[]At // TxStatus. func TxSnapshotsFromProtobuf(scheme Scheme, txSnapshotProto *g.TransactionStateSnapshot) ([]AtomicSnapshot, error) { var txSnapshots []AtomicSnapshot - err := balancesFromProto(scheme, txSnapshotProto, &txSnapshots) + err := newAssetFromProto(txSnapshotProto, &txSnapshots) if err != nil { return nil, err } - err = leaseBalancesFromProto(scheme, txSnapshotProto, &txSnapshots) + err = assetVolumeFromProto(txSnapshotProto, &txSnapshots) if err != nil { return nil, err } - err = newAssetFromProto(txSnapshotProto, &txSnapshots) + err = assetDescriptionFromProto(txSnapshotProto, &txSnapshots) if err != nil { return nil, err } - err = assetVolumeFromProto(txSnapshotProto, &txSnapshots) + err = assetScriptFromProto(txSnapshotProto, &txSnapshots) if err != nil { return nil, err } - err = assetDescriptionFromProto(txSnapshotProto, &txSnapshots) + err = balancesFromProto(scheme, txSnapshotProto, &txSnapshots) if err != nil { return nil, err } - err = assetScriptFromProto(txSnapshotProto, &txSnapshots) + err = leaseBalancesFromProto(scheme, txSnapshotProto, &txSnapshots) if err != nil { return nil, err } From aefa542ef913eab673e14461ea89589bf5e3c3b2 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Tue, 20 Feb 2024 00:28:16 +0300 Subject: [PATCH 109/139] Fix light node fee distribution (#1341) * Fix TODO comment in 'snapshot_generator_internal_test.go'. * Use 'error.As' in 'wrapErr' func according to the linter recommendation. * Use 'errors.Is' according to the linter recommendation. * Rename 'needToRecalc' variable to 'needToRecalculate'. * Add 'default' case for 'switch' in 'txAppender.handleFallible'. * Add TODO for 'txAppender.applySnapshotInLightNode'. * Refactor 'newStateManager' function. * Reuse 'currentBlockInfo' struct in 'applySnapshotInLightNode' and 'appendTxs' methods of 'txAppender'. * Coun miner fee while processing transactions snapshots in 'txAppender.applySnapshotInLightNode'. * Count miner fees after transactions processing. * Fix mistake with wrapping wrong error variable while calculating miner's fees. * Count miner tx fee after tx application. * Count miner tx fees in 'commitTxApplication'. --- pkg/state/appender.go | 25 ++- pkg/state/snapshot_generator_internal_test.go | 2 +- pkg/state/state.go | 157 +++++++++--------- 3 files changed, 95 insertions(+), 89 deletions(-) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 60ad63f86..0d5d46db6 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -370,9 +370,7 @@ func (a *txAppender) commitTxApplication( } if !params.validatingUtx { - // TODO: snapshots for miner fee should be generated here, but not saved - // They must be saved in snapshot applier - // Count tx fee. + // Count tx fee. This should not affect transaction execution. It only accumulates miner fee. if err := a.blockDiffer.countMinerFee(tx); err != nil { return txSnapshot{}, wrapErr(TxCommitmentError, errors.Errorf("failed to count miner fee: %v", err)) } @@ -617,6 +615,7 @@ func (a *txAppender) appendTx(tx proto.Transaction, params *appendTxParams) (txS func (a *txAppender) applySnapshotInLightNode( params *appendBlockParams, + blockInfo *proto.BlockInfo, snapshot proto.BlockSnapshot, stateHash crypto.Digest, hasher *txSnapshotHasher, @@ -624,10 +623,6 @@ func (a *txAppender) applySnapshotInLightNode( if len(snapshot.TxSnapshots) != len(params.transactions) { // sanity check return crypto.Digest{}, errors.New("number of tx snapshots doesn't match number of transactions") } - blockInfo, errBlockInfo := a.currentBlockInfo() - if errBlockInfo != nil { - return crypto.Digest{}, errBlockInfo - } for i, txs := range snapshot.TxSnapshots { tx := params.transactions[i] txID, idErr := tx.GetID(a.settings.AddressSchemeCharacter) @@ -648,6 +643,10 @@ func (a *txAppender) applySnapshotInLightNode( if err := regSnapshots.Apply(a.txHandler.sa, tx, false); err != nil { return crypto.Digest{}, errors.Wrap(err, "failed to apply tx snapshot") } + if fErr := a.blockDiffer.countMinerFee(tx); fErr != nil { + return crypto.Digest{}, errors.Wrapf(fErr, "failed to count miner fee for tx %d", i+1) + } + // TODO: In future we have to store the list of affected addresses for each transaction here. } return stateHash, nil } @@ -655,13 +654,10 @@ func (a *txAppender) applySnapshotInLightNode( func (a *txAppender) appendTxs( params *appendBlockParams, info *checkerInfo, + blockInfo *proto.BlockInfo, stateHash crypto.Digest, hasher *txSnapshotHasher, ) (proto.BlockSnapshot, crypto.Digest, error) { - blockInfo, errBlockInfo := a.currentBlockInfo() - if errBlockInfo != nil { - return proto.BlockSnapshot{}, crypto.Digest{}, errBlockInfo - } blockV5Activated, err := a.stor.features.newestIsActivated(int16(settings.BlockV5)) if err != nil { return proto.BlockSnapshot{}, crypto.Digest{}, err @@ -799,9 +795,9 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { var blockSnapshot proto.BlockSnapshot if params.optionalSnapshot != nil { blockSnapshot = *params.optionalSnapshot - stateHash, err = a.applySnapshotInLightNode(params, blockSnapshot, stateHash, hasher) + stateHash, err = a.applySnapshotInLightNode(params, blockInfo, blockSnapshot, stateHash, hasher) } else { - blockSnapshot, stateHash, err = a.appendTxs(params, checkerInfo, stateHash, hasher) + blockSnapshot, stateHash, err = a.appendTxs(params, checkerInfo, blockInfo, stateHash, hasher) } if err != nil { return err @@ -1087,8 +1083,9 @@ func (a *txAppender) handleFallible( case proto.ExchangeTransaction: applicationRes, err := a.handleExchange(tx, info) return nil, applicationRes, err + default: + return nil, nil, errors.Errorf("transaction (%T) is not fallible", tx) } - return nil, nil, errors.New("transaction is not fallible") } // For UTX validation. diff --git a/pkg/state/snapshot_generator_internal_test.go b/pkg/state/snapshot_generator_internal_test.go index 647f6eaa2..1ee8d30a9 100644 --- a/pkg/state/snapshot_generator_internal_test.go +++ b/pkg/state/snapshot_generator_internal_test.go @@ -121,7 +121,7 @@ func TestDefaultTransferWavesAndAssetSnapshot(t *testing.T) { to.stor.flush(t) } -// TODO send only txBalanceChanges to perfomer +// TODO send only txBalanceChanges to performer func TestDefaultIssueTransactionSnapshot(t *testing.T) { to := createSnapshotGeneratorTestObjects(t) diff --git a/pkg/state/state.go b/pkg/state/state.go index f09def3c5..f2fe6513b 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -35,8 +35,9 @@ const ( var empty struct{} func wrapErr(stateErrorType ErrorType, err error) error { - switch err.(type) { - case StateError: + var stateError StateError + switch { + case errors.As(err, &stateError): return err default: return NewStateError(stateErrorType, err) @@ -399,16 +400,77 @@ type stateManager struct { enableLightNode bool } -func newStateManager( //nolint:funlen,gocognit +func initDatabase( + dataDir, blockStorageDir string, + amend bool, + params StateParams, +) (*keyvalue.KeyVal, keyvalue.Batch, *stateDB, bool, error) { + dbDir := filepath.Join(dataDir, keyvalueDir) + zap.S().Info("Initializing state database, will take up to few minutes...") + params.DbParams.BloomFilterParams.Store.WithPath(filepath.Join(blockStorageDir, "bloom")) + db, err := keyvalue.NewKeyVal(dbDir, params.DbParams) + if err != nil { + return nil, nil, nil, false, wrapErr(Other, errors.Wrap(err, "failed to create db")) + } + zap.S().Info("Finished initializing database") + dbBatch, err := db.NewBatch() + if err != nil { + return nil, nil, nil, false, wrapErr(Other, errors.Wrap(err, "failed to create db batch")) + } + sdb, err := newStateDB(db, dbBatch, params) + if err != nil { + return nil, nil, nil, false, wrapErr(Other, errors.Wrap(err, "failed to create stateDB")) + } + if cErr := checkCompatibility(sdb, params); cErr != nil { + return nil, nil, nil, false, wrapErr(IncompatibilityError, cErr) + } + handledAmend, err := handleAmendFlag(sdb, amend) + if err != nil { + return nil, nil, nil, false, wrapErr(Other, errors.Wrap(err, "failed to handle amend flag")) + } + return db, dbBatch, sdb, handledAmend, nil +} + +func initGenesis(state *stateManager, height uint64, settings *settings.BlockchainSettings) error { + state.setGenesisBlock(&settings.Genesis) + // 0 state height means that no blocks are found in state, so blockchain history is empty and we have to add genesis + if height == 0 { + // Assign unique block number for this block ID, add this number to the list of valid blocks + if err := state.stateDB.addBlock(settings.Genesis.BlockID()); err != nil { + return err + } + if err := state.addGenesisBlock(); err != nil { + return errors.Wrap(err, "failed to apply/save genesis") + } + // We apply pre-activated features after genesis block, so they aren't active in genesis itself + if err := state.applyPreActivatedFeatures(settings.PreactivatedFeatures, settings.Genesis.BlockID()); err != nil { + return errors.Wrap(err, "failed to apply pre-activated features") + } + } + + // check the correct blockchain is being loaded + genesis, err := state.BlockByHeight(1) + if err != nil { + return errors.Wrap(err, "failed to get genesis block from state") + } + err = settings.Genesis.GenerateBlockID(settings.AddressSchemeCharacter) + if err != nil { + return errors.Wrap(err, "failed to generate genesis block id from config") + } + if !bytes.Equal(genesis.ID.Bytes(), settings.Genesis.ID.Bytes()) { + return errors.New("genesis blocks from state and config mismatch") + } + return nil +} + +func newStateManager( dataDir string, amend bool, params StateParams, settings *settings.BlockchainSettings, enableLightNode bool, ) (*stateManager, error) { - // TODO(anton): fix lint - err := validateSettings(settings) - if err != nil { + if err := validateSettings(settings); err != nil { return nil, err } if _, err := os.Stat(dataDir); errors.Is(err, fs.ErrNotExist) { @@ -423,42 +485,23 @@ func newStateManager( //nolint:funlen,gocognit } } // Initialize database. - dbDir := filepath.Join(dataDir, keyvalueDir) - zap.S().Info("Initializing state database, will take up to few minutes...") - params.DbParams.BloomFilterParams.Store.WithPath(filepath.Join(blockStorageDir, "bloom")) - db, err := keyvalue.NewKeyVal(dbDir, params.DbParams) + db, dbBatch, sdb, handledAmend, err := initDatabase(dataDir, blockStorageDir, amend, params) if err != nil { - return nil, wrapErr(Other, errors.Wrap(err, "failed to create db")) - } - zap.S().Info("Finished initializing database") - dbBatch, err := db.NewBatch() - if err != nil { - return nil, wrapErr(Other, errors.Wrap(err, "failed to create db batch")) - } - stateDB, err := newStateDB(db, dbBatch, params) - if err != nil { - return nil, wrapErr(Other, errors.Wrap(err, "failed to create stateDB")) - } - if err := checkCompatibility(stateDB, params); err != nil { - return nil, wrapErr(IncompatibilityError, err) - } - handledAmend, err := handleAmendFlag(stateDB, amend) - if err != nil { - return nil, wrapErr(Other, errors.Wrap(err, "failed to handle amend flag")) + return nil, err } // rw is storage for blocks. rw, err := newBlockReadWriter( blockStorageDir, params.OffsetLen, params.HeaderOffsetLen, - stateDB, + sdb, settings.AddressSchemeCharacter, ) if err != nil { return nil, wrapErr(Other, errors.Errorf("failed to create block storage: %v", err)) } - stateDB.setRw(rw) - hs, err := newHistoryStorage(db, dbBatch, stateDB, handledAmend) + sdb.setRw(rw) + hs, err := newHistoryStorage(db, dbBatch, sdb, handledAmend) if err != nil { return nil, wrapErr(Other, errors.Errorf("failed to create history storage: %v", err)) } @@ -473,19 +516,13 @@ func newStateManager( //nolint:funlen,gocognit maxFileSize: MaxAddressTransactionsFileSize, providesData: params.ProvideExtendedApi, } - atx, err := newAddressTransactions( - db, - stateDB, - rw, - atxParams, - handledAmend, - ) + atx, err := newAddressTransactions(db, sdb, rw, atxParams, handledAmend) if err != nil { return nil, wrapErr(Other, errors.Errorf("failed to create address transactions storage: %v", err)) } state := &stateManager{ mu: &sync.RWMutex{}, - stateDB: stateDB, + stateDB: sdb, stor: stor, rw: rw, settings: settings, @@ -496,11 +533,8 @@ func newStateManager( //nolint:funlen,gocognit } // Set fields which depend on state. // Consensus validator is needed to check block headers. - snapshotApplier := newBlockSnapshotsApplier( - nil, - newSnapshotApplierStorages(stor, rw), - ) - appender, err := newTxAppender(state, rw, stor, settings, stateDB, atx, &snapshotApplier) + snapshotApplier := newBlockSnapshotsApplier(nil, newSnapshotApplierStorages(stor, rw)) + appender, err := newTxAppender(state, rw, stor, settings, sdb, atx, &snapshotApplier) if err != nil { return nil, wrapErr(Other, err) } @@ -511,35 +545,10 @@ func newStateManager( //nolint:funlen,gocognit if err != nil { return nil, err } - state.setGenesisBlock(&settings.Genesis) - // 0 state height means that no blocks are found in state, so blockchain history is empty and we have to add genesis - if height == 0 { - // Assign unique block number for this block ID, add this number to the list of valid blocks - if err := state.stateDB.addBlock(settings.Genesis.BlockID()); err != nil { - return nil, err - } - if err := state.addGenesisBlock(); err != nil { - return nil, errors.Wrap(err, "failed to apply/save genesis") - } - // We apply pre-activated features after genesis block, so they aren't active in genesis itself - if err := state.applyPreActivatedFeatures(settings.PreactivatedFeatures, settings.Genesis.BlockID()); err != nil { - return nil, errors.Wrap(err, "failed to apply pre-activated features") - } - } - // check the correct blockchain is being loaded - genesis, err := state.BlockByHeight(1) - if err != nil { - return nil, errors.Wrap(err, "failed to get genesis block from state") - } - err = settings.Genesis.GenerateBlockID(settings.AddressSchemeCharacter) - if err != nil { - return nil, errors.Wrap(err, "failed to generate genesis block id from config") + if gErr := initGenesis(state, height, settings); gErr != nil { + return nil, gErr } - if !bytes.Equal(genesis.ID.Bytes(), settings.Genesis.ID.Bytes()) { - return nil, errors.Errorf("genesis blocks from state and config mismatch") - } - if err := state.loadLastBlock(); err != nil { return nil, wrapErr(RetrievalError, err) } @@ -856,7 +865,7 @@ func (s *stateManager) newestAssetBalance(addr proto.AddressID, asset proto.Asse // Retrieve the latest balance diff as for the moment of this function call. key := assetBalanceKey{address: addr, asset: asset} diff, err := s.appender.diffStorInvoke.latestDiffByKey(string(key.bytes())) - if err == errNotFound { + if errors.Is(err, errNotFound) { // If there is no diff, old balance is the newest. return balance, nil } else if err != nil { @@ -879,7 +888,7 @@ func (s *stateManager) newestWavesBalanceProfile(addr proto.AddressID) (balanceP // Retrieve the latest balance diff as for the moment of this function call. key := wavesBalanceKey{address: addr} diff, err := s.appender.diffStorInvoke.latestDiffByKey(string(key.bytes())) - if err == errNotFound { + if errors.Is(err, errNotFound) { // If there is no diff, old balance is the newest. return profile, nil } else if err != nil { @@ -1414,11 +1423,11 @@ func (s *stateManager) blockchainHeightAction(blockchainHeight uint64, lastBlock } } - needToRecalc, err := s.needToRecalculateVotesAfterCappedRewardActivationInVotingPeriod(blockchainHeight) + needToRecalculate, err := s.needToRecalculateVotesAfterCappedRewardActivationInVotingPeriod(blockchainHeight) if err != nil { return err } - if needToRecalc { // one time action + if needToRecalculate { // one time action if err := s.recalculateVotesAfterCappedRewardActivationInVotingPeriod(blockchainHeight, lastBlock); err != nil { return errors.Wrap(err, "failed to recalculate monetary policy votes") } From 17a66f0691cef9a07d45b1d4d2c55a733f32ccd2 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Wed, 21 Feb 2024 08:58:29 +0300 Subject: [PATCH 110/139] fix other channel size --- pkg/node/actions_by_type.go | 1 + pkg/p2p/peer/peer.go | 15 ++++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/pkg/node/actions_by_type.go b/pkg/node/actions_by_type.go index b9ce27acc..1a77fe5df 100644 --- a/pkg/node/actions_by_type.go +++ b/pkg/node/actions_by_type.go @@ -322,6 +322,7 @@ func BlockSnapshotAction(services services.Services, mess peer.ProtoMessage, fsm if err != nil { return nil, err } + zap.S().Named(logging.NetworkNamespace).Debugf("Snapshot for block '%s' received", blockID.String()) return fsm.BlockSnapshot(mess.ID, blockID, blockSnapshot) } diff --git a/pkg/p2p/peer/peer.go b/pkg/p2p/peer/peer.go index 66b4a19cd..df3a08e7e 100644 --- a/pkg/p2p/peer/peer.go +++ b/pkg/p2p/peer/peer.go @@ -8,6 +8,11 @@ import ( "github.com/wavesplatform/gowaves/pkg/proto" ) +const ( + defaultChSize = 100 + chSizeInLightMode = defaultChSize * 2 +) + type Remote struct { ToCh chan []byte FromCh chan *bytebufferpool.ByteBuffer @@ -16,8 +21,8 @@ type Remote struct { func NewRemote() Remote { return Remote{ - ToCh: make(chan []byte, 100), - FromCh: make(chan *bytebufferpool.ByteBuffer, 100), + ToCh: make(chan []byte, chSizeInLightMode), + FromCh: make(chan *bytebufferpool.ByteBuffer, chSizeInLightMode), ErrCh: make(chan error, 10), } } @@ -29,14 +34,14 @@ type Parent struct { } func NewParent(enableLightNode bool) Parent { - messageChSize := 100 + messageChSize := defaultChSize if enableLightNode { // because in light node we send block and snapshot request messages - messageChSize = 200 + messageChSize = chSizeInLightMode } return Parent{ MessageCh: make(chan ProtoMessage, messageChSize), - InfoCh: make(chan InfoMessage, 100), + InfoCh: make(chan InfoMessage, chSizeInLightMode), SkipMessageList: &messages.SkipMessageList{}, } } From df1ae2f159d51c20dc13c511cec8ad6b801fb77d Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Wed, 21 Feb 2024 09:51:09 +0300 Subject: [PATCH 111/139] fix state name --- pkg/node/fsm/fsm.go | 13 +++++++------ pkg/node/fsm/wait_micro_snapshot.go | 4 ++-- pkg/p2p/peer/peer.go | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/pkg/node/fsm/fsm.go b/pkg/node/fsm/fsm.go index cb3770283..980a9172b 100644 --- a/pkg/node/fsm/fsm.go +++ b/pkg/node/fsm/fsm.go @@ -97,12 +97,13 @@ func (a *BaseInfo) CleanUtx() { // States. const ( - IdleStateName = "Idle" - NGStateName = "NG" - WaitSnapshotStateName = "WaitSnapshotLight" - PersistStateName = "Persist" - SyncStateName = "Sync" - HaltStateName = "Halt" + IdleStateName = "Idle" + NGStateName = "NG" + WaitSnapshotStateName = "WaitSnapshot" + WaitMicroSnapshotStateName = "WaitMicroSnapshot" + PersistStateName = "Persist" + SyncStateName = "Sync" + HaltStateName = "Halt" ) // Events. diff --git a/pkg/node/fsm/wait_micro_snapshot.go b/pkg/node/fsm/wait_micro_snapshot.go index b46e871e8..02871b272 100644 --- a/pkg/node/fsm/wait_micro_snapshot.go +++ b/pkg/node/fsm/wait_micro_snapshot.go @@ -200,8 +200,8 @@ func initWaitMicroSnapshotStateInFSM(state *StateData, fsm *stateless.StateMachi proto.ContentIDGetBlockIDs, proto.ContentIDBlockSnapshot, } - fsm.Configure(WaitSnapshotStateName). //nolint:dupl // it's state setup - OnEntry(func(_ context.Context, _ ...interface{}) error { + fsm.Configure(WaitMicroSnapshotStateName). //nolint:dupl // it's state setup + OnEntry(func(_ context.Context, _ ...interface{}) error { info.skipMessageList.SetList(waitSnapshotSkipMessageList) return nil }). diff --git a/pkg/p2p/peer/peer.go b/pkg/p2p/peer/peer.go index df3a08e7e..4499af199 100644 --- a/pkg/p2p/peer/peer.go +++ b/pkg/p2p/peer/peer.go @@ -41,7 +41,7 @@ func NewParent(enableLightNode bool) Parent { } return Parent{ MessageCh: make(chan ProtoMessage, messageChSize), - InfoCh: make(chan InfoMessage, chSizeInLightMode), + InfoCh: make(chan InfoMessage, messageChSize), SkipMessageList: &messages.SkipMessageList{}, } } From 313d70d106203ff34a5ff12a5539f4142c46fa43 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Thu, 22 Feb 2024 05:33:37 +0300 Subject: [PATCH 112/139] Add 'cleanupBeforeTransition' deferred calls for 'WaitMicroSnapshotState' and 'WaitSnapshotState'. --- pkg/node/fsm/wait_micro_snapshot.go | 18 +++++++++++------- pkg/node/fsm/wait_snapshot_state.go | 17 ++++++++++------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/pkg/node/fsm/wait_micro_snapshot.go b/pkg/node/fsm/wait_micro_snapshot.go index 02871b272..e31f3fb1f 100644 --- a/pkg/node/fsm/wait_micro_snapshot.go +++ b/pkg/node/fsm/wait_micro_snapshot.go @@ -64,8 +64,7 @@ func (a *WaitMicroSnapshotState) Task(task tasks.AsyncTask) (State, Async, error case tasks.BlockSnapshot: return a, nil, nil case tasks.MicroBlockSnapshot: - a.microBlockWaitingForSnapshot = nil - a.timeoutTaskOutdated = nil + defer a.cleanupBeforeTransition() return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, a.Errorf(errors.Errorf( "failed to get snapshot for microBlock '%s' - timeout", t.BlockID)) default: @@ -93,11 +92,8 @@ func (a *WaitMicroSnapshotState) MicroBlockSnapshot( metrics.FSMMicroBlockDeclined("ng", a.microBlockWaitingForSnapshot, err) return a, nil, a.Errorf(err) } - defer func() { - a.microBlockWaitingForSnapshot = nil - close(a.timeoutTaskOutdated) - a.timeoutTaskOutdated = nil - }() + defer a.cleanupBeforeTransition() + zap.S().Named(logging.FSMNamespace).Debugf( "[%s] Received snapshot for microblock '%s' successfully applied to state", a, block.BlockID(), ) @@ -115,6 +111,14 @@ func (a *WaitMicroSnapshotState) MicroBlockSnapshot( return a, nil, nil } +func (a *WaitMicroSnapshotState) cleanupBeforeTransition() { + a.microBlockWaitingForSnapshot = nil + if a.timeoutTaskOutdated != nil { + close(a.timeoutTaskOutdated) + a.timeoutTaskOutdated = nil + } +} + func (a *WaitMicroSnapshotState) checkAndAppendMicroBlock( micro *proto.MicroBlock, snapshot *proto.BlockSnapshot, diff --git a/pkg/node/fsm/wait_snapshot_state.go b/pkg/node/fsm/wait_snapshot_state.go index 5a1456c9a..d79108a10 100644 --- a/pkg/node/fsm/wait_snapshot_state.go +++ b/pkg/node/fsm/wait_snapshot_state.go @@ -61,8 +61,7 @@ func (a *WaitSnapshotState) Task(task tasks.AsyncTask) (State, Async, error) { } switch t.SnapshotTaskType { case tasks.BlockSnapshot: - a.blockWaitingForSnapshot = nil - a.timeoutTaskOutdated = nil + defer a.cleanupBeforeTransition() return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, a.Errorf(errors.Errorf( "failed to get snapshot for block '%s' - timeout", t.BlockID)) case tasks.MicroBlockSnapshot: @@ -96,11 +95,7 @@ func (a *WaitSnapshotState) BlockSnapshot( // metrics.FSMKeyBlockDeclined("ng", block, err) return a, nil, a.Errorf(errors.Wrapf(err, "peer '%s'", peer.ID())) } - defer func() { - a.blockWaitingForSnapshot = nil - close(a.timeoutTaskOutdated) - a.timeoutTaskOutdated = nil - }() + defer a.cleanupBeforeTransition() metrics.FSMKeyBlockApplied("ng", a.blockWaitingForSnapshot) zap.S().Named(logging.FSMNamespace).Debugf("[%s] Handle received key block message: block '%s' applied to state", @@ -115,6 +110,14 @@ func (a *WaitSnapshotState) BlockSnapshot( return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, nil } +func (a *WaitSnapshotState) cleanupBeforeTransition() { + a.blockWaitingForSnapshot = nil + if a.timeoutTaskOutdated != nil { + close(a.timeoutTaskOutdated) + a.timeoutTaskOutdated = nil + } +} + func initWaitSnapshotStateInFSM(state *StateData, fsm *stateless.StateMachine, info BaseInfo) { waitSnapshotSkipMessageList := proto.PeerMessageIDs{ proto.ContentIDGetPeers, From 47370b51ec9c1c3971a6c4dedcd3b670c164dea7 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Thu, 22 Feb 2024 05:34:04 +0300 Subject: [PATCH 113/139] Simplified a bit 'syncSkipMessageList' for SYNC in full mode --- pkg/node/fsm/sync_state.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/node/fsm/sync_state.go b/pkg/node/fsm/sync_state.go index a8175b69a..456a4b90b 100644 --- a/pkg/node/fsm/sync_state.go +++ b/pkg/node/fsm/sync_state.go @@ -320,9 +320,7 @@ func initSyncStateInFSM(state *StateData, fsm *stateless.StateMachine, info Base proto.ContentIDMicroBlockSnapshotRequest, } if !info.enableLightMode { - syncSkipMessageList = append(syncSkipMessageList, []proto.PeerMessageID{ - proto.ContentIDBlockSnapshot, - }...) + syncSkipMessageList = append(syncSkipMessageList, proto.ContentIDBlockSnapshot) } fsm.Configure(SyncStateName). Ignore(MicroBlockEvent). From 6047df91d3319b55e71011894ca798e63d25a0be Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Tue, 27 Feb 2024 08:06:29 +0300 Subject: [PATCH 114/139] fix microBlockSnapshot state name --- pkg/node/fsm/wait_micro_snapshot.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/node/fsm/wait_micro_snapshot.go b/pkg/node/fsm/wait_micro_snapshot.go index e31f3fb1f..6e3ec458c 100644 --- a/pkg/node/fsm/wait_micro_snapshot.go +++ b/pkg/node/fsm/wait_micro_snapshot.go @@ -41,7 +41,7 @@ func (a *WaitMicroSnapshotState) Errorf(err error) error { } func (a *WaitMicroSnapshotState) String() string { - return WaitSnapshotStateName + return WaitMicroSnapshotStateName } func (a *WaitMicroSnapshotState) Task(task tasks.AsyncTask) (State, Async, error) { @@ -49,7 +49,7 @@ func (a *WaitMicroSnapshotState) Task(task tasks.AsyncTask) (State, Async, error case tasks.Ping: return a, nil, nil case tasks.AskPeers: - zap.S().Named(logging.FSMNamespace).Debug("[WaitSnapshot] Requesting peers") + zap.S().Named(logging.FSMNamespace).Debug("[WaitMicroSnapshot] Requesting peers") a.baseInfo.peers.AskPeers() return a, nil, nil case tasks.MineMicro: @@ -105,10 +105,10 @@ func (a *WaitMicroSnapshotState) MicroBlockSnapshot( if inv, ok := a.baseInfo.MicroBlockInvCache.Get(block.BlockID()); ok { //TODO: We have to exclude from recipients peers that already have this microblock if err = broadcastMicroBlockInv(a.baseInfo, inv); err != nil { - return a, nil, a.Errorf(errors.Wrap(err, "failed to handle microblock message")) + return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, a.Errorf(errors.Wrap(err, "failed to handle microblock message")) } } - return a, nil, nil + return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, nil } func (a *WaitMicroSnapshotState) cleanupBeforeTransition() { From a600bce2e919f12df12e36c85d26864830175c73 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Wed, 28 Feb 2024 07:36:20 +0300 Subject: [PATCH 115/139] initialize snapshot chache --- pkg/node/fsm/ng_state.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pkg/node/fsm/ng_state.go b/pkg/node/fsm/ng_state.go index 11811ec60..73caf45a0 100644 --- a/pkg/node/fsm/ng_state.go +++ b/pkg/node/fsm/ng_state.go @@ -26,7 +26,7 @@ func newNGState(baseInfo BaseInfo) State { baseInfo.syncPeer.Clear() return &NGState{ baseInfo: baseInfo, - blocksCache: blockStatesCache{blockStates: map[proto.BlockID]proto.Block{}}, + blocksCache: newBlockStatesCache(), } } @@ -219,7 +219,7 @@ func (a *NGState) MinedBlock( a.baseInfo.actions.SendScore(a.baseInfo.storage) a.baseInfo.CleanUtx() - a.blocksCache = blockStatesCache{blockStates: map[proto.BlockID]proto.Block{}} + a.blocksCache = newBlockStatesCache() return a, tasks.Tasks(tasks.NewMineMicroTask(0, block, limits, keyPair, vrf)), nil } @@ -389,6 +389,13 @@ type blockStatesCache struct { snapshots map[proto.BlockID]proto.BlockSnapshot } +func newBlockStatesCache() blockStatesCache { + return blockStatesCache{ + blockStates: map[proto.BlockID]proto.Block{}, + snapshots: map[proto.BlockID]proto.BlockSnapshot{}, + } +} + func (c *blockStatesCache) AddBlockState(block *proto.Block) { c.blockStates[block.ID] = *block zap.S().Named(logging.FSMNamespace).Debugf("[NG] Block '%s' added to cache, total blocks in cache: %d", From b934eebbdfee5513afa4d2a58e702ba2ec7ca508 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Wed, 28 Feb 2024 08:18:20 +0300 Subject: [PATCH 116/139] fix linter --- pkg/node/fsm/wait_micro_snapshot.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/node/fsm/wait_micro_snapshot.go b/pkg/node/fsm/wait_micro_snapshot.go index 6e3ec458c..f58f7ad50 100644 --- a/pkg/node/fsm/wait_micro_snapshot.go +++ b/pkg/node/fsm/wait_micro_snapshot.go @@ -105,7 +105,8 @@ func (a *WaitMicroSnapshotState) MicroBlockSnapshot( if inv, ok := a.baseInfo.MicroBlockInvCache.Get(block.BlockID()); ok { //TODO: We have to exclude from recipients peers that already have this microblock if err = broadcastMicroBlockInv(a.baseInfo, inv); err != nil { - return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, a.Errorf(errors.Wrap(err, "failed to handle microblock message")) + return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, + a.Errorf(errors.Wrap(err, "failed to handle microblock message")) } } return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, nil @@ -205,7 +206,7 @@ func initWaitMicroSnapshotStateInFSM(state *StateData, fsm *stateless.StateMachi proto.ContentIDBlockSnapshot, } fsm.Configure(WaitMicroSnapshotStateName). //nolint:dupl // it's state setup - OnEntry(func(_ context.Context, _ ...interface{}) error { + OnEntry(func(_ context.Context, _ ...interface{}) error { info.skipMessageList.SetList(waitSnapshotSkipMessageList) return nil }). From 15c658cc5367e0a9c1ab4a15d8888f5e5fc73070 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Wed, 28 Feb 2024 08:30:38 +0300 Subject: [PATCH 117/139] fix linters --- pkg/node/fsm/wait_micro_snapshot.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/node/fsm/wait_micro_snapshot.go b/pkg/node/fsm/wait_micro_snapshot.go index f58f7ad50..82e724466 100644 --- a/pkg/node/fsm/wait_micro_snapshot.go +++ b/pkg/node/fsm/wait_micro_snapshot.go @@ -206,7 +206,7 @@ func initWaitMicroSnapshotStateInFSM(state *StateData, fsm *stateless.StateMachi proto.ContentIDBlockSnapshot, } fsm.Configure(WaitMicroSnapshotStateName). //nolint:dupl // it's state setup - OnEntry(func(_ context.Context, _ ...interface{}) error { + OnEntry(func(_ context.Context, _ ...interface{}) error { info.skipMessageList.SetList(waitSnapshotSkipMessageList) return nil }). From a290f447f45647c3cf52c1b065eba8702ebaae84 Mon Sep 17 00:00:00 2001 From: Aleksandr Dolgavin Date: Fri, 1 Mar 2024 06:16:23 -0800 Subject: [PATCH 118/139] Add snapshots to importer (#1290) * Added snapshots import to importer * Added flags * Added snapshots to importer * Importer refactoring. Extracted blockReader and snapshotReader. Linter errors fixed. Blockchain scheme fixed. * Linter action version updated. * Golangci-lint version updated to 1.55.2. * Importer global refactoring. * Use new min and max fucntions from Go 1.21. * Unused newSnapshots type removed. * Small style fix. Additional check on data size while deserializing snapshots. --------- Co-authored-by: Alexey Kiselev --- cmd/importer/importer.go | 333 +++++++++++++++++++-------- pkg/importer/blocks_importer.go | 80 +++++++ pkg/importer/blocks_reader.go | 53 +++++ pkg/importer/importer.go | 107 ++------- pkg/importer/snapshots_importer.go | 102 ++++++++ pkg/importer/snapshots_reader.go | 64 +++++ pkg/importer/speed_regulator.go | 53 +++++ pkg/mock/state.go | 28 +++ pkg/proto/block_snapshot.go | 36 +++ pkg/state/api.go | 3 + pkg/state/headers_validation_test.go | 5 +- pkg/state/state.go | 24 ++ pkg/state/state_test.go | 44 ++-- pkg/state/threadsafe_wrapper.go | 6 + 14 files changed, 733 insertions(+), 205 deletions(-) create mode 100644 pkg/importer/blocks_importer.go create mode 100644 pkg/importer/blocks_reader.go create mode 100644 pkg/importer/snapshots_importer.go create mode 100644 pkg/importer/snapshots_reader.go create mode 100644 pkg/importer/speed_regulator.go diff --git a/cmd/importer/importer.go b/cmd/importer/importer.go index 883759161..9793cdc07 100644 --- a/cmd/importer/importer.go +++ b/cmd/importer/importer.go @@ -10,6 +10,7 @@ import ( "runtime/pprof" "strings" "time" + "unicode" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -27,145 +28,283 @@ const ( ) func main() { + err := run() + if err != nil { + zap.S().Error(capitalize(err.Error())) + os.Exit(1) + } +} + +type cfg struct { + logLevel *zapcore.Level + cfgPath string + blockchainType string + blockchainPath string + balancesPath string + dataDirPath string + nBlocks int + verificationGoroutinesNum int + writeBufferSize int + buildDataForExtendedAPI bool + buildStateHashes bool + lightNodeMode bool + snapshotsPath string + cpuProfilePath string + memProfilePath string +} + +func parseFlags() (cfg, error) { const ( defaultBlocksNumber = 1000 defaultBufferSize = 16 ) - var ( - logLevel = zap.LevelFlag("log-level", zapcore.InfoLevel, - "Logging level. Supported levels: DEBUG, INFO, WARN, ERROR, FATAL. Default logging level INFO.") - cfgPath = flag.String("cfg-path", "", - "Path to blockchain settings JSON file for custom blockchains. Not set by default.") - blockchainType = flag.String("blockchain-type", "mainnet", - "Blockchain type. Allowed values: mainnet/testnet/stagenet/custom. Default is 'mainnet'.") - blockchainPath = flag.String("blockchain-path", "", "Path to binary blockchain file.") - balancesPath = flag.String("balances-path", "", - "Path to JSON with correct balances after applying blocks.") - dataDirPath = flag.String("data-path", "", "Path to directory with previously created state.") - nBlocks = flag.Int("blocks-number", defaultBlocksNumber, "Number of blocks to import.") - verificationGoroutinesNum = flag.Int("verification-goroutines-num", runtime.NumCPU()*2, - " Number of goroutines that will be run for verification of transactions/blocks signatures.") - writeBufferSize = flag.Int("write-buffer", defaultBufferSize, "Write buffer size in MiB.") - buildDataForExtendedAPI = flag.Bool("build-extended-api", false, - "Build and store additional data required for extended API in state. "+ - "WARNING: this slows down the import, use only if you do really need extended API.") - buildStateHashes = flag.Bool("build-state-hashes", false, - "Calculate and store state hashes for each block height.") - // Debug. - cpuProfilePath = flag.String("cpuprofile", "", "Write cpu profile to this file.") - memProfilePath = flag.String("memprofile", "", "Write memory profile to this file.") - ) - + c := cfg{} + c.logLevel = zap.LevelFlag("log-level", zapcore.InfoLevel, + "Logging level. Supported levels: DEBUG, INFO, WARN, ERROR, FATAL. Default logging level INFO.") + flag.StringVar(&c.cfgPath, "cfg-path", "", + "Path to blockchain settings JSON file for custom blockchains. Not set by default.") + flag.StringVar(&c.blockchainType, "blockchain-type", "mainnet", + "Blockchain type. Allowed values: mainnet/testnet/stagenet/custom. Default is 'mainnet'.") + flag.StringVar(&c.blockchainPath, "blockchain-path", "", "Path to binary blockchain file.") + flag.StringVar(&c.balancesPath, "balances-path", "", + "Path to JSON with correct balances after applying blocks.") + flag.StringVar(&c.dataDirPath, "data-path", "", "Path to directory with previously created state.") + flag.IntVar(&c.nBlocks, "blocks-number", defaultBlocksNumber, "Number of blocks to import.") + flag.IntVar(&c.verificationGoroutinesNum, "verification-goroutines-num", runtime.NumCPU()*2, + " Number of goroutines that will be run for verification of transactions/blocks signatures.") + flag.IntVar(&c.writeBufferSize, "write-buffer", defaultBufferSize, "Write buffer size in MiB.") + flag.BoolVar(&c.buildDataForExtendedAPI, "build-extended-api", false, + "Build and store additional data required for extended API in state. "+ + "WARNING: this slows down the import, use only if you do really need extended API.") + flag.BoolVar(&c.buildStateHashes, "build-state-hashes", false, + "Calculate and store state hashes for each block height.") + flag.BoolVar(&c.lightNodeMode, "light-node", false, + "Run the node in the light mode in which snapshots are imported without validation") + flag.StringVar(&c.snapshotsPath, "snapshots-path", "", "Path to binary snapshots file.") + // Debug. + flag.StringVar(&c.cpuProfilePath, "cpuprofile", "", "Write cpu profile to this file.") + flag.StringVar(&c.memProfilePath, "memprofile", "", "Write memory profile to this file.") flag.Parse() - logger := logging.SetupSimpleLogger(*logLevel) - defer func() { - err := logger.Sync() - if err != nil && errors.Is(err, os.ErrInvalid) { - panic(fmt.Sprintf("Failed to close logging subsystem: %v\n", err)) + if c.blockchainPath == "" { + return cfg{}, errors.New("option blockchain-path is not specified, please specify it") + } + if c.dataDirPath == "" { + return cfg{}, errors.New("option data-path is not specified, please specify it") + } + if c.lightNodeMode && c.snapshotsPath == "" { + return cfg{}, errors.New("option snapshots-path is not specified in light mode, please specify it") + } + + return c, nil +} + +func (c *cfg) params(maxFDs int) state.StateParams { + const clearance = 10 + params := state.DefaultStateParams() + params.StorageParams.DbParams.OpenFilesCacheCapacity = maxFDs - clearance + params.VerificationGoroutinesNum = c.verificationGoroutinesNum + params.DbParams.WriteBuffer = c.writeBufferSize * MiB + params.StoreExtendedApiData = c.buildDataForExtendedAPI + params.BuildStateHashes = c.buildStateHashes + params.ProvideExtendedApi = false // We do not need to provide any APIs during import. + params.LightNodeMode = c.lightNodeMode + return params +} + +func (c *cfg) setupLogger() func() { + logger := logging.SetupSimpleLogger(*c.logLevel) + return func() { + if sErr := logger.Sync(); sErr != nil && errors.Is(sErr, os.ErrInvalid) { + zap.S().Errorf("Failed to close logging subsystem: %v", sErr) } - }() - zap.S().Infof("Gowaves Importer version: %s", versioning.Version) + } +} - maxFDs, err := fdlimit.MaxFDs() - if err != nil { - zap.S().Fatalf("Initialization error: %v", err) +func (c *cfg) setupCPUProfile() (func(), error) { + if c.cpuProfilePath == "" { + return func() {}, nil } - _, err = fdlimit.RaiseMaxFDs(maxFDs) + f, err := os.Create(c.cpuProfilePath) if err != nil { - zap.S().Fatalf("Initialization error: %v", err) + return nil, fmt.Errorf("failed to create CPU profile: %w", err) + } + if err = pprof.StartCPUProfile(f); err != nil { + return nil, fmt.Errorf("failed to start CPU profile: %w", err) } + return func() { + pprof.StopCPUProfile() + if clErr := f.Close(); clErr != nil { + zap.S().Errorf("Failed to close CPU profile: %v", clErr) + } + }, nil +} - if *blockchainPath == "" { - zap.S().Fatalf("You must specify blockchain-path option.") +func run() error { + c, err := parseFlags() + if err != nil { + return err } - if *dataDirPath == "" { - zap.S().Fatalf("You must specify data-path option.") + + logSync := c.setupLogger() + defer logSync() + + zap.S().Infof("Gowaves Importer version: %s", versioning.Version) + + fds, err := riseFDLimit() + if err != nil { + return err } // Debug. - if *cpuProfilePath != "" { - f, err := os.Create(*cpuProfilePath) - if err != nil { - zap.S().Fatal("Could not create CPU profile: ", err) - } - defer func() { _ = f.Close() }() - if err := pprof.StartCPUProfile(f); err != nil { - zap.S().Fatal("Could not start CPU profile: ", err) - } - defer pprof.StopCPUProfile() + cpfClose, err := c.setupCPUProfile() + if err != nil { + return err } + defer cpfClose() // https://godoc.org/github.com/coocood/freecache#NewCache debug.SetGCPercent(20) - var ss *settings.BlockchainSettings - if strings.ToLower(*blockchainType) == "custom" && *cfgPath != "" { - f, err := os.Open(*cfgPath) - if err != nil { - zap.S().Fatalf("Failed to open custom blockchain settings: %v", err) - } - defer func() { _ = f.Close() }() - ss, err = settings.ReadBlockchainSettings(f) - if err != nil { - zap.S().Fatalf("Failed to read custom blockchain settings: %v", err) - } - } else { - ss, err = settings.BlockchainSettingsByTypeName(*blockchainType) - if err != nil { - zap.S().Fatalf("Failed to load blockchain settings: %v", err) - } - } - params := state.DefaultStateParams() - params.StorageParams.DbParams.OpenFilesCacheCapacity = int(maxFDs - 10) - params.VerificationGoroutinesNum = *verificationGoroutinesNum - params.DbParams.WriteBuffer = *writeBufferSize * MiB - params.StoreExtendedApiData = *buildDataForExtendedAPI - params.BuildStateHashes = *buildStateHashes - // We do not need to provide any APIs during import. - params.ProvideExtendedApi = false - - st, err := state.NewState(*dataDirPath, false, params, ss, false) + ss, err := configureBlockchainSettings(c.blockchainType, c.cfgPath) if err != nil { - zap.S().Fatalf("Failed to create state: %v", err) + return err } + st, err := state.NewState(c.dataDirPath, false, c.params(fds), ss, false) + if err != nil { + return fmt.Errorf("failed to create state: %w", err) + } defer func() { - if err := st.Close(); err != nil { - zap.S().Fatalf("Failed to close State: %v", err) + if clErr := st.Close(); clErr != nil { + zap.S().Errorf("Failed to close State: %v", clErr) } }() + imp, impClose, err := selectImporter(c, ss, st) + if err != nil { + return fmt.Errorf("failed to create importer: %w", err) + } + defer impClose() + height, err := st.Height() if err != nil { - zap.S().Fatalf("Failed to get current height: %v", err) + return fmt.Errorf("failed to get current height: %w", err) + } + if height > 1 { + zap.S().Infof("Skipping to height %d", height) + if skErr := imp.SkipToHeight(height); skErr != nil { + return fmt.Errorf("failed to skip to state height: %w", skErr) + } } + start := time.Now() - if err := importer.ApplyFromFile(st, *blockchainPath, uint64(*nBlocks), height); err != nil { - height, err1 := st.Height() - if err1 != nil { - zap.S().Fatalf("Failed to get current height: %v", err1) + if impErr := imp.Import(uint64(c.nBlocks)); impErr != nil { + h, hErr := st.Height() + if hErr != nil { + return fmt.Errorf("failed to get current height: %w", hErr) } - zap.S().Fatalf("Failed to apply blocks after height %d: %v", height, err) + return fmt.Errorf("failed to apply blocks after height %d: %w", h, impErr) } elapsed := time.Since(start) zap.S().Infof("Import took %s", elapsed) - if len(*balancesPath) != 0 { - if err := importer.CheckBalances(st, *balancesPath); err != nil { - zap.S().Fatalf("Balances check failed: %v", err) + + if len(c.balancesPath) != 0 { + if balErr := importer.CheckBalances(st, c.balancesPath); balErr != nil { + return fmt.Errorf("failed to check balances: %w", balErr) } } // Debug. - if *memProfilePath != "" { - f, err := os.Create(*memProfilePath) + if mpfErr := configureMemProfile(c.memProfilePath); mpfErr != nil { + return mpfErr + } + + return nil +} + +func selectImporter(c cfg, ss *settings.BlockchainSettings, st importer.State) (importer.Importer, func(), error) { + if c.lightNodeMode { + imp, err := importer.NewSnapshotsImporter(ss.AddressSchemeCharacter, st, c.blockchainPath, c.snapshotsPath) if err != nil { - zap.S().Fatal("Could not create memory profile: ", err) + return nil, nil, fmt.Errorf("failed to create snapshots importer: %w", err) } - defer func() { _ = f.Close() }() - runtime.GC() // get up-to-date statistics - if err := pprof.WriteHeapProfile(f); err != nil { - zap.S().Fatal("Could not write memory profile: ", err) + return imp, func() { + if clErr := imp.Close(); clErr != nil { + zap.S().Errorf("Failed to close snapshots importer: %v", clErr) + } + }, nil + } + imp, err := importer.NewBlocksImporter(ss.AddressSchemeCharacter, st, c.blockchainPath) + if err != nil { + return nil, nil, fmt.Errorf("failed to create blocks importer: %w", err) + } + return imp, func() { + if clErr := imp.Close(); clErr != nil { + zap.S().Errorf("Failed to close blocks importer: %v", clErr) } + }, nil +} + +func configureMemProfile(memProfilePath string) error { + if memProfilePath == "" { + return nil + } + f, err := os.Create(memProfilePath) + if err != nil { + return fmt.Errorf("failed to create memory profile: %w", err) } + defer func() { + if clErr := f.Close(); clErr != nil { + zap.S().Errorf("Failed to close memory profile: %v", clErr) + } + }() + runtime.GC() // get up-to-date statistics + if err = pprof.WriteHeapProfile(f); err != nil { + return fmt.Errorf("failed to write memory profile: %w", err) + } + return nil +} + +func configureBlockchainSettings(blockchainType, cfgPath string) (*settings.BlockchainSettings, error) { + var ss *settings.BlockchainSettings + if strings.ToLower(blockchainType) == "custom" && cfgPath != "" { + f, err := os.Open(cfgPath) + if err != nil { + return nil, fmt.Errorf("failed to open custom blockchain settings: %w", err) + } + defer func() { + if clErr := f.Close(); clErr != nil { + zap.S().Errorf("Failed to close custom blockchain settings: %v", clErr) + } + }() + ss, err = settings.ReadBlockchainSettings(f) + if err != nil { + return nil, fmt.Errorf("failed to read custom blockchain settings: %w", err) + } + return ss, nil + } + ss, err := settings.BlockchainSettingsByTypeName(blockchainType) + if err != nil { + return nil, fmt.Errorf("failed to load blockchain settings: %w", err) + } + return ss, nil +} + +func riseFDLimit() (int, error) { + maxFDs, err := fdlimit.MaxFDs() + if err != nil { + return 0, fmt.Errorf("failed to initialize importer: %w", err) + } + _, err = fdlimit.RaiseMaxFDs(maxFDs) + if err != nil { + return 0, fmt.Errorf("failed to initialize importer: %w", err) + } + return int(maxFDs), nil +} + +func capitalize(str string) string { + runes := []rune(str) + runes[0] = unicode.ToUpper(runes[0]) + return string(runes) } diff --git a/pkg/importer/blocks_importer.go b/pkg/importer/blocks_importer.go new file mode 100644 index 000000000..239e2e7af --- /dev/null +++ b/pkg/importer/blocks_importer.go @@ -0,0 +1,80 @@ +package importer + +import ( + "fmt" + "time" + + "github.com/wavesplatform/gowaves/pkg/proto" +) + +type BlocksImporter struct { + scheme proto.Scheme + st State + + br *blocksReader + reg *speedRegulator + + h uint64 +} + +func NewBlocksImporter(scheme proto.Scheme, st State, blocksPath string) (*BlocksImporter, error) { + br, err := newBlocksReader(blocksPath) + if err != nil { + return nil, fmt.Errorf("failed to create blocks importer: %w", err) + } + return &BlocksImporter{scheme: scheme, st: st, br: br, reg: newSpeedRegulator()}, nil +} + +func (imp *BlocksImporter) SkipToHeight(height proto.Height) error { + imp.h = uint64(1) + if height < imp.h { + return fmt.Errorf("invalid initial height: %d", height) + } + for { + if imp.h == height { + return nil + } + size, err := imp.br.readSize() + if err != nil { + return fmt.Errorf("failed to skip to height %d: %w", height, err) + } + imp.reg.updateTotalSize(size) + imp.br.skip(size) + imp.h++ + } +} + +func (imp *BlocksImporter) Import(number uint64) error { + var blocks [MaxBlocksBatchSize][]byte + index := uint64(0) + for height := imp.h; height <= number; height++ { + size, err := imp.br.readSize() + if err != nil { + return fmt.Errorf("failed to import: %w", err) + } + imp.reg.updateTotalSize(size) + block, err := imp.br.readBlock(size) + if err != nil { + return fmt.Errorf("failed to import: %w", err) + } + blocks[index] = block + index++ + if imp.reg.incomplete() && (index != MaxBlocksBatchSize) && (height != number) { + continue + } + start := time.Now() + if abErr := imp.st.AddBlocks(blocks[:index]); abErr != nil { + return abErr + } + imp.reg.calculateSpeed(start) + index = 0 + if pErr := maybePersistTxs(imp.st); pErr != nil { + return pErr + } + } + return nil +} + +func (imp *BlocksImporter) Close() error { + return imp.br.close() +} diff --git a/pkg/importer/blocks_reader.go b/pkg/importer/blocks_reader.go new file mode 100644 index 000000000..ea1d68223 --- /dev/null +++ b/pkg/importer/blocks_reader.go @@ -0,0 +1,53 @@ +package importer + +import ( + "encoding/binary" + "errors" + "fmt" + "os" +) + +type blocksReader struct { + f *os.File + pos int64 +} + +func newBlocksReader(blockchainPath string) (*blocksReader, error) { + f, err := os.Open(blockchainPath) + if err != nil { + return nil, fmt.Errorf("failed to open blocks file: %w", err) + } + return &blocksReader{f: f, pos: 0}, nil +} + +func (br *blocksReader) readSize() (uint32, error) { + buf := make([]byte, uint32Size) + n, err := br.f.ReadAt(buf, br.pos) + if err != nil { + return 0, fmt.Errorf("failed to read block size: %w", err) + } + br.pos += int64(n) + size := binary.BigEndian.Uint32(buf) + if size > MaxBlockSize || size == 0 { + return 0, errors.New("corrupted blockchain file: invalid block size") + } + return size, nil +} + +func (br *blocksReader) skip(size uint32) { + br.pos += int64(size) +} + +func (br *blocksReader) readBlock(size uint32) ([]byte, error) { + buf := make([]byte, size) + n, err := br.f.ReadAt(buf, br.pos) + if err != nil { + return nil, fmt.Errorf("failed to read block: %w", err) + } + br.pos += int64(n) + return buf, nil +} + +func (br *blocksReader) close() error { + return br.f.Close() +} diff --git a/pkg/importer/importer.go b/pkg/importer/importer.go index ffd819bf6..035497e4e 100644 --- a/pkg/importer/importer.go +++ b/pkg/importer/importer.go @@ -1,11 +1,9 @@ package importer import ( - "encoding/binary" "encoding/json" "os" "path/filepath" - "time" "github.com/pkg/errors" "go.uber.org/zap" @@ -19,15 +17,18 @@ const ( initTotalBatchSize = 5 * MiB sizeAdjustment = 1 * MiB + uint32Size = 4 - MaxTotalBatchSize = 20 * MiB - MaxTotalBatchSizeForNetworkSync = 6 * MiB - MaxBlocksBatchSize = 50000 - MaxBlockSize = 2 * MiB + MaxTotalBatchSize = 20 * MiB + MaxBlocksBatchSize = 50000 + MaxBlockSize = 2 * MiB ) +var errNoop = errors.New("noop") + type State interface { AddBlocks(blocks [][]byte) error + AddBlocksWithSnapshots(blocks [][]byte, snapshots []*proto.BlockSnapshot) error WavesAddressesNumber() (uint64, error) WavesBalance(account proto.Recipient) (uint64, error) AssetBalance(account proto.Recipient, assetID proto.AssetID) (uint64, error) @@ -35,6 +36,12 @@ type State interface { PersistAddressTransactions() error } +type Importer interface { + SkipToHeight(uint64) error + Import(uint64) error + Close() error +} + func maybePersistTxs(st State) error { // Check if we need to persist transactions for extended API. persistTxs, err := st.ShouldPersistAddressTransactions() @@ -47,94 +54,24 @@ func maybePersistTxs(st State) error { return nil } -func calculateNextMaxSizeAndDirection(maxSize int, speed, prevSpeed float64, increasingSize bool) (int, bool) { - if speed > prevSpeed && increasingSize { - maxSize += sizeAdjustment - if maxSize > MaxTotalBatchSize { - maxSize = MaxTotalBatchSize - } - } else if speed > prevSpeed && !increasingSize { - maxSize -= sizeAdjustment - if maxSize < initTotalBatchSize { - maxSize = initTotalBatchSize - } - } else if speed < prevSpeed && increasingSize { - increasingSize = false - maxSize -= sizeAdjustment - if maxSize < initTotalBatchSize { - maxSize = initTotalBatchSize - } - } else if speed < prevSpeed && !increasingSize { - increasingSize = true - maxSize += sizeAdjustment - if maxSize > MaxTotalBatchSize { - maxSize = MaxTotalBatchSize - } - } - return maxSize, increasingSize -} - // ApplyFromFile reads blocks from blockchainPath, applying them from height startHeight and until nBlocks+1. // Setting optimize to true speeds up the import, but it is only safe when importing blockchain from scratch // when no rollbacks are possible at all. -func ApplyFromFile(st State, blockchainPath string, nBlocks, startHeight uint64) error { - blockchain, err := os.Open(blockchainPath) // #nosec: in this case check for prevent G304 (CWE-22) is not necessary +func ApplyFromFile(scheme proto.Scheme, st State, blockchainPath string, nBlocks, startHeight uint64) error { + imp, err := NewBlocksImporter(scheme, st, blockchainPath) if err != nil { - return errors.Errorf("failed to open blockchain file: %v", err) + return err } - defer func() { - if err := blockchain.Close(); err != nil { - zap.S().Fatalf("Failed to close blockchain file: %v", err) + if clErr := imp.Close(); clErr != nil { + zap.S().Fatalf("Failed to close importer: %v", clErr) } }() - sb := make([]byte, 4) - var blocks [MaxBlocksBatchSize][]byte - blocksIndex := 0 - readPos := int64(0) - totalSize := 0 - prevSpeed := float64(0) - increasingSize := true - maxSize := initTotalBatchSize - for height := uint64(1); height <= nBlocks; height++ { - if _, err := blockchain.ReadAt(sb, readPos); err != nil { - return err - } - size := binary.BigEndian.Uint32(sb) - if size > MaxBlockSize || size == 0 { - return errors.New("corrupted blockchain file: invalid block size") - } - totalSize += int(size) - readPos += 4 - if height < startHeight { - readPos += int64(size) - continue - } - block := make([]byte, size) - if _, err := blockchain.ReadAt(block, readPos); err != nil { - return err - } - readPos += int64(size) - blocks[blocksIndex] = block - blocksIndex++ - if (totalSize < maxSize) && (blocksIndex != MaxBlocksBatchSize) && (height != nBlocks) { - continue - } - start := time.Now() - if err := st.AddBlocks(blocks[:blocksIndex]); err != nil { - return err - } - elapsed := time.Since(start) - speed := float64(totalSize) / float64(elapsed) - maxSize, increasingSize = calculateNextMaxSizeAndDirection(maxSize, speed, prevSpeed, increasingSize) - prevSpeed = speed - totalSize = 0 - blocksIndex = 0 - if err := maybePersistTxs(st); err != nil { - return err - } + err = imp.SkipToHeight(startHeight) + if err != nil { + return err } - return nil + return imp.Import(nBlocks) } func CheckBalances(st State, balancesPath string) error { diff --git a/pkg/importer/snapshots_importer.go b/pkg/importer/snapshots_importer.go new file mode 100644 index 000000000..c40f2945a --- /dev/null +++ b/pkg/importer/snapshots_importer.go @@ -0,0 +1,102 @@ +package importer + +import ( + "errors" + "fmt" + "time" + + "github.com/wavesplatform/gowaves/pkg/proto" +) + +type SnapshotsImporter struct { + scheme proto.Scheme + st State + + br *blocksReader + sr *snapshotsReader + reg *speedRegulator + + h uint64 +} + +func NewSnapshotsImporter(scheme proto.Scheme, st State, blocksPath, snapshotsPath string) (*SnapshotsImporter, error) { + br, err := newBlocksReader(blocksPath) + if err != nil { + return nil, fmt.Errorf("failed to create snapshots importer: %w", err) + } + sr, err := newSnapshotsReader(scheme, snapshotsPath) + if err != nil { + return nil, fmt.Errorf("failed to create snapshots importer: %w", err) + } + return &SnapshotsImporter{scheme: scheme, st: st, br: br, sr: sr, reg: newSpeedRegulator()}, nil +} + +func (imp *SnapshotsImporter) SkipToHeight(height proto.Height) error { + imp.h = uint64(1) + if height < imp.h { + return fmt.Errorf("invalid initial height: %d", height) + } + for { + if imp.h == height { + return nil + } + size, err := imp.br.readSize() + if err != nil { + return fmt.Errorf("failed to skip to height %d: %w", height, err) + } + imp.reg.updateTotalSize(size) + imp.br.skip(size) + size, err = imp.sr.readSize() + if err != nil { + return fmt.Errorf("failed to skip to height %d: %w", height, err) + } + imp.sr.skip(size) + imp.h++ + } +} + +func (imp *SnapshotsImporter) Import(number uint64) error { + var blocks [MaxBlocksBatchSize][]byte + var snapshots [MaxBlocksBatchSize]*proto.BlockSnapshot + index := 0 + for count := imp.h; count <= number; count++ { + // reading snapshots + snapshot, err := imp.sr.readSnapshot() + if err != nil && !errors.Is(err, errNoop) { + return err + } + snapshots[index] = snapshot + + size, sErr := imp.br.readSize() + if sErr != nil { + return sErr + } + imp.reg.updateTotalSize(size) + block, rErr := imp.br.readBlock(size) + if rErr != nil { + return rErr + } + blocks[index] = block + index++ + if imp.reg.incomplete() && (index != MaxBlocksBatchSize) && (count != number) { + continue + } + start := time.Now() + if abErr := imp.st.AddBlocksWithSnapshots(blocks[:index], snapshots[:index]); abErr != nil { + return abErr + } + imp.reg.calculateSpeed(start) + index = 0 + if pErr := maybePersistTxs(imp.st); pErr != nil { + return pErr + } + } + return nil +} + +func (imp *SnapshotsImporter) Close() error { + if err := imp.sr.close(); err != nil { + return err + } + return imp.br.close() +} diff --git a/pkg/importer/snapshots_reader.go b/pkg/importer/snapshots_reader.go new file mode 100644 index 000000000..e05c3f301 --- /dev/null +++ b/pkg/importer/snapshots_reader.go @@ -0,0 +1,64 @@ +package importer + +import ( + "encoding/binary" + "errors" + "fmt" + "os" + + "github.com/wavesplatform/gowaves/pkg/proto" +) + +type snapshotsReader struct { + scheme proto.Scheme + f *os.File + pos int64 +} + +func newSnapshotsReader(scheme proto.Scheme, snapshotsPath string) (*snapshotsReader, error) { + f, err := os.Open(snapshotsPath) + if err != nil { + return nil, fmt.Errorf("failed to open snapshots file: %w", err) + } + return &snapshotsReader{scheme: scheme, f: f, pos: 0}, nil +} + +func (sr *snapshotsReader) readSize() (uint32, error) { + buf := make([]byte, uint32Size) + n, err := sr.f.ReadAt(buf, sr.pos) + if err != nil { + return 0, fmt.Errorf("failed to read block snapshot size: %w", err) + } + sr.pos += int64(n) + size := binary.BigEndian.Uint32(buf) + if size == 0 { + return 0, errors.New("corrupted snapshots file: invalid snapshot size") + } + return size, nil +} + +func (sr *snapshotsReader) skip(size uint32) { + sr.pos += int64(size) +} + +func (sr *snapshotsReader) readSnapshot() (*proto.BlockSnapshot, error) { + size, sErr := sr.readSize() + if sErr != nil { + return nil, sErr + } + buf := make([]byte, size) + n, rErr := sr.f.ReadAt(buf, sr.pos) + if rErr != nil { + return nil, fmt.Errorf("failed to read snapshot: %w", rErr) + } + sr.pos += int64(n) + snapshot := &proto.BlockSnapshot{} + if err := snapshot.UnmarshalBinaryImport(buf, sr.scheme); err != nil { + return nil, fmt.Errorf("failed to unmarshal snapshot: %w", err) + } + return snapshot, nil +} + +func (sr *snapshotsReader) close() error { + return sr.f.Close() +} diff --git a/pkg/importer/speed_regulator.go b/pkg/importer/speed_regulator.go new file mode 100644 index 000000000..4e3462397 --- /dev/null +++ b/pkg/importer/speed_regulator.go @@ -0,0 +1,53 @@ +package importer + +import "time" + +type speedRegulator struct { + prevSpeed float64 + speed float64 + maxSize int + increasing bool + totalSize int +} + +func newSpeedRegulator() *speedRegulator { + return &speedRegulator{maxSize: initTotalBatchSize, increasing: true} +} + +func (r *speedRegulator) updateTotalSize(size uint32) { + r.totalSize += int(size) +} + +func (r *speedRegulator) incomplete() bool { + return r.totalSize < r.maxSize +} + +func (r *speedRegulator) calculateSpeed(start time.Time) { + elapsed := time.Since(start) + r.speed = float64(r.totalSize) / float64(elapsed) + r.maxSize, r.increasing = r.calculateNextMaxSizeAndDirection() + r.prevSpeed = r.speed + r.totalSize = 0 +} + +func (r *speedRegulator) calculateNextMaxSizeAndDirection() (int, bool) { + maxSize := r.maxSize + increasing := r.increasing + switch { + case r.speed > r.prevSpeed && r.increasing: + maxSize += sizeAdjustment + maxSize = min(maxSize, MaxTotalBatchSize) + case r.speed > r.prevSpeed && !r.increasing: + maxSize -= sizeAdjustment + maxSize = max(maxSize, initTotalBatchSize) + case r.speed < r.prevSpeed && r.increasing: + increasing = false + maxSize -= sizeAdjustment + maxSize = max(maxSize, initTotalBatchSize) + case r.speed < r.prevSpeed && !r.increasing: + increasing = true + maxSize += sizeAdjustment + maxSize = min(maxSize, MaxTotalBatchSize) + } + return maxSize, increasing +} diff --git a/pkg/mock/state.go b/pkg/mock/state.go index 9107d5f4c..b8bda70bc 100644 --- a/pkg/mock/state.go +++ b/pkg/mock/state.go @@ -1100,6 +1100,20 @@ func (mr *MockStateModifierMockRecorder) AddBlocks(blocks interface{}) *gomock.C return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddBlocks", reflect.TypeOf((*MockStateModifier)(nil).AddBlocks), blocks) } +// AddBlocksWithSnapshots mocks base method. +func (m *MockStateModifier) AddBlocksWithSnapshots(blocks [][]byte, snapshots []*proto.BlockSnapshot) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AddBlocksWithSnapshots", blocks, snapshots) + ret0, _ := ret[0].(error) + return ret0 +} + +// AddBlocksWithSnapshots indicates an expected call of AddBlocksWithSnapshots. +func (mr *MockStateModifierMockRecorder) AddBlocksWithSnapshots(blocks, snapshots interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddBlocksWithSnapshots", reflect.TypeOf((*MockStateModifier)(nil).AddBlocksWithSnapshots), blocks, snapshots) +} + // AddDeserializedBlock mocks base method. func (m *MockStateModifier) AddDeserializedBlock(block *proto.Block) (*proto.Block, error) { m.ctrl.T.Helper() @@ -1373,6 +1387,20 @@ func (mr *MockStateMockRecorder) AddBlocks(blocks interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddBlocks", reflect.TypeOf((*MockState)(nil).AddBlocks), blocks) } +// AddBlocksWithSnapshots mocks base method. +func (m *MockState) AddBlocksWithSnapshots(blocks [][]byte, snapshots []*proto.BlockSnapshot) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AddBlocksWithSnapshots", blocks, snapshots) + ret0, _ := ret[0].(error) + return ret0 +} + +// AddBlocksWithSnapshots indicates an expected call of AddBlocksWithSnapshots. +func (mr *MockStateMockRecorder) AddBlocksWithSnapshots(blocks, snapshots interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddBlocksWithSnapshots", reflect.TypeOf((*MockState)(nil).AddBlocksWithSnapshots), blocks, snapshots) +} + // AddDeserializedBlock mocks base method. func (m *MockState) AddDeserializedBlock(block *proto.Block) (*proto.Block, error) { m.ctrl.T.Helper() diff --git a/pkg/proto/block_snapshot.go b/pkg/proto/block_snapshot.go index 9d9f84fe0..99eb1bfa4 100644 --- a/pkg/proto/block_snapshot.go +++ b/pkg/proto/block_snapshot.go @@ -325,3 +325,39 @@ func (s *txSnapshotJSON) ApplyTransactionsStatus(snapshot TransactionStatusSnaps s.ApplicationStatus = snapshot.Status return nil } + +func (bs *BlockSnapshot) UnmarshalBinaryImport(data []byte, scheme Scheme) error { + if len(data) < uint32Size { + return errors.Errorf("BlockSnapshot UnmarshallBinary: invalid data size") + } + snapshotsBytesSize := binary.BigEndian.Uint32(data[0:uint32Size]) + data = data[uint32Size:] // skip size + if snapshotsBytesSize != uint32(len(data)) { + return errors.Errorf("invalid snapshots data size") + } + var txSnapshots [][]AtomicSnapshot + for i := uint32(0); snapshotsBytesSize > 0; i++ { + if len(data) < uint32Size { + return errors.Errorf("BlockSnapshot UnmarshallBinary: invalid data size") + } + oneSnapshotSize := binary.BigEndian.Uint32(data[0:uint32Size]) + var tsProto g.TransactionStateSnapshot + data = data[uint32Size:] // skip size + if uint32(len(data)) < oneSnapshotSize { + return errors.Errorf("BlockSnapshot UnmarshallBinary: invalid snapshot size") + } + err := tsProto.UnmarshalVT(data[0:oneSnapshotSize]) + if err != nil { + return err + } + atomicTS, err := TxSnapshotsFromProtobuf(scheme, &tsProto) + if err != nil { + return err + } + txSnapshots = append(txSnapshots, atomicTS) + data = data[oneSnapshotSize:] + snapshotsBytesSize -= oneSnapshotSize + uint32Size + } + bs.TxSnapshots = txSnapshots + return nil +} diff --git a/pkg/state/api.go b/pkg/state/api.go index 2d97272d6..8d3c7c685 100644 --- a/pkg/state/api.go +++ b/pkg/state/api.go @@ -152,6 +152,7 @@ type StateModifier interface { AddDeserializedBlock(block *proto.Block) (*proto.Block, error) // AddBlocks adds batch of new blocks to state. AddBlocks(blocks [][]byte) error + AddBlocksWithSnapshots(blocks [][]byte, snapshots []*proto.BlockSnapshot) error // AddDeserializedBlocks marshals blocks to binary and calls AddBlocks. AddDeserializedBlocks(blocks []*proto.Block) (*proto.Block, error) AddDeserializedBlocksWithSnapshots(blocks []*proto.Block, snapshots []*proto.BlockSnapshot) (*proto.Block, error) @@ -263,6 +264,8 @@ type StateParams struct { ProvideExtendedApi bool // BuildStateHashes enables building and storing state hashes by height. BuildStateHashes bool + + LightNodeMode bool } func DefaultStateParams() StateParams { diff --git a/pkg/state/headers_validation_test.go b/pkg/state/headers_validation_test.go index 75c343e14..f40c3fe02 100644 --- a/pkg/state/headers_validation_test.go +++ b/pkg/state/headers_validation_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/keyvalue" "github.com/wavesplatform/gowaves/pkg/libs/ntptime" @@ -34,8 +35,8 @@ func applyBlocks(t *testing.T, blocks []proto.Block, st State, scheme proto.Sche if blocksIndex != blocksBatchSize && height != blocksNumber { continue } - if err := st.AddBlocks(blocksBatch[:blocksIndex]); err != nil { - return err + if aErr := st.AddBlocks(blocksBatch[:blocksIndex]); aErr != nil { + return aErr } blocksIndex = 0 } diff --git a/pkg/state/state.go b/pkg/state/state.go index a0117b8b3..76acfa63e 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -317,6 +317,17 @@ func (n *newBlocks) setNewWithSnapshots(blocks []*proto.Block, snapshots []*prot return nil } +func (n *newBlocks) setNewBinaryWithSnapshots(blocks [][]byte, snapshots []*proto.BlockSnapshot) error { + if len(blocks) != len(snapshots) { + return errors.New("the numbers of snapshots doesn't match the number of blocks") + } + n.reset() + n.binBlocks = blocks + n.snapshots = snapshots + n.binary = true + return nil +} + func (n *newBlocks) next() bool { n.curPos++ if n.binary { @@ -1239,6 +1250,19 @@ func (s *stateManager) AddBlocks(blockBytes [][]byte) error { return nil } +func (s *stateManager) AddBlocksWithSnapshots(blockBytes [][]byte, snapshots []*proto.BlockSnapshot) error { + if err := s.newBlocks.setNewBinaryWithSnapshots(blockBytes, snapshots); err != nil { + return errors.Wrap(err, "failed to set new blocks with snapshots") + } + if _, err := s.addBlocks(); err != nil { + if snErr := s.rw.syncWithDb(); snErr != nil { + zap.S().Fatalf("Failed to add blocks and can not sync block storage with the database after failure: %v", snErr) + } + return err + } + return nil +} + func (s *stateManager) AddDeserializedBlocks( blocks []*proto.Block, ) (*proto.Block, error) { diff --git a/pkg/state/state_test.go b/pkg/state/state_test.go index da5b89d6b..6e1a2ea89 100644 --- a/pkg/state/state_test.go +++ b/pkg/state/state_test.go @@ -125,7 +125,7 @@ func TestValidationWithoutBlocks(t *testing.T) { assert.NoError(t, err, "readBlocksFromTestPath() failed") last := blocks[len(blocks)-1] txs := last.Transactions - err = importer.ApplyFromFile(manager, blocksPath, height, 1) + err = importer.ApplyFromFile(proto.MainNetScheme, manager, blocksPath, height, 1) assert.NoError(t, err, "ApplyFromFile() failed") err = validateTxs(manager, last.Timestamp, txs) assert.NoError(t, err, "validateTxs() failed") @@ -183,23 +183,23 @@ func TestStateRollback(t *testing.T) { } for _, tc := range tests { - height, err := manager.Height() - if err != nil { - t.Fatalf("Height(): %v\n", err) + height, hErr := manager.Height() + if hErr != nil { + t.Fatalf("Height(): %v\n", hErr) } if tc.nextHeight > height { - if err := importer.ApplyFromFile(manager, blocksPath, tc.nextHeight-1, height); err != nil { - t.Fatalf("Failed to import: %v\n", err) + if aErr := importer.ApplyFromFile(proto.MainNetScheme, manager, blocksPath, tc.nextHeight-1, height); aErr != nil { + t.Fatalf("Failed to import: %v\n", aErr) } } else { - if err := manager.RollbackToHeight(tc.nextHeight); err != nil { - t.Fatalf("Rollback(): %v\n", err) + if rErr := manager.RollbackToHeight(tc.nextHeight); rErr != nil { + t.Fatalf("Rollback(): %v\n", rErr) } } - if err := importer.CheckBalances(manager, tc.balancesPath); err != nil { - t.Fatalf("CheckBalances(): %v\n", err) + if cErr := importer.CheckBalances(manager, tc.balancesPath); cErr != nil { + t.Fatalf("CheckBalances(): %v\n", cErr) } - if err := manager.RollbackToHeight(tc.minRollbackHeight - 1); err == nil { + if rErr := manager.RollbackToHeight(tc.minRollbackHeight - 1); rErr == nil { t.Fatalf("Rollback() did not fail with height less than minimum valid.") } } @@ -224,15 +224,17 @@ func TestStateIntegrated(t *testing.T) { // Test what happens in case of failure: we add blocks starting from wrong height. // State should be rolled back to previous state and ready to use after. wrongStartHeight := uint64(100) - if err := importer.ApplyFromFile(manager, blocksPath, blocksToImport, wrongStartHeight); err == nil { + if aErr := importer.ApplyFromFile(proto.MainNetScheme, manager, blocksPath, blocksToImport, + wrongStartHeight); aErr == nil { t.Errorf("Import starting from wrong height must fail but it doesn't.") } // Test normal import. - if err := importer.ApplyFromFile(manager, blocksPath, blocksToImport, 1); err != nil { - t.Fatalf("Failed to import: %v\n", err) + if aErr := importer.ApplyFromFile(proto.MainNetScheme, manager, blocksPath, blocksToImport, + 1); aErr != nil { + t.Fatalf("Failed to import: %v\n", aErr) } - if err := importer.CheckBalances(manager, balancesPath); err != nil { - t.Fatalf("CheckBalances(): %v\n", err) + if cErr := importer.CheckBalances(manager, balancesPath); cErr != nil { + t.Fatalf("CheckBalances(): %v\n", cErr) } score, err := manager.ScoreAtHeight(blocksToImport + 1) if err != nil { @@ -298,7 +300,7 @@ func TestPreactivatedFeatures(t *testing.T) { assert.Equal(t, true, approved) // Apply blocks. height := uint64(75) - err = importer.ApplyFromFile(manager, blocksPath, height, 1) + err = importer.ApplyFromFile(proto.MainNetScheme, manager, blocksPath, height, 1) assert.NoError(t, err, "ApplyFromFile() failed") // Check activation and approval heights. activationHeight, err := manager.ActivationHeight(featureID) @@ -316,7 +318,7 @@ func TestDisallowDuplicateTxIds(t *testing.T) { // Apply blocks. height := uint64(75) - err = importer.ApplyFromFile(manager, blocksPath, height, 1) + err = importer.ApplyFromFile(proto.MainNetScheme, manager, blocksPath, height, 1) assert.NoError(t, err, "ApplyFromFile() failed") // Now validate tx with ID which is already in the state. tx := existingGenesisTx(t) @@ -335,7 +337,7 @@ func TestTransactionByID(t *testing.T) { // Apply blocks. height := uint64(75) - err = importer.ApplyFromFile(manager, blocksPath, height, 1) + err = importer.ApplyFromFile(proto.MainNetScheme, manager, blocksPath, height, 1) assert.NoError(t, err, "ApplyFromFile() failed") // Retrieve existing MainNet genesis tx by its ID. @@ -364,7 +366,7 @@ func TestStateManager_TopBlock(t *testing.T) { assert.Equal(t, genesis, manager.TopBlock()) height := proto.Height(100) - err = importer.ApplyFromFile(manager, blocksPath, height-1, 1) + err = importer.ApplyFromFile(proto.MainNetScheme, manager, blocksPath, height-1, 1) assert.NoError(t, err, "ApplyFromFile() failed") correct, err := manager.BlockByHeight(height) @@ -410,7 +412,7 @@ func TestStateHashAtHeight(t *testing.T) { blocksPath, err := blocksPath() assert.NoError(t, err) - err = importer.ApplyFromFile(manager, blocksPath, 9499, 1) + err = importer.ApplyFromFile(proto.MainNetScheme, manager, blocksPath, 9499, 1) assert.NoError(t, err, "ApplyFromFile() failed") stateHash, err := manager.LegacyStateHashAtHeight(9500) assert.NoError(t, err, "LegacyStateHashAtHeight failed") diff --git a/pkg/state/threadsafe_wrapper.go b/pkg/state/threadsafe_wrapper.go index 82e892553..ba2b7bed0 100644 --- a/pkg/state/threadsafe_wrapper.go +++ b/pkg/state/threadsafe_wrapper.go @@ -435,6 +435,12 @@ func (a *ThreadSafeWriteWrapper) AddBlocks(blocks [][]byte) error { return a.s.AddBlocks(blocks) } +func (a *ThreadSafeWriteWrapper) AddBlocksWithSnapshots(blocks [][]byte, snapshots []*proto.BlockSnapshot) error { + a.lock() + defer a.unlock() + return a.s.AddBlocksWithSnapshots(blocks, snapshots) +} + func (a *ThreadSafeWriteWrapper) AddDeserializedBlocks( blocks []*proto.Block, ) (*proto.Block, error) { From c755679c29081a1d071b002c972b8d58a8a97f1e Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Mon, 4 Mar 2024 12:14:06 +0400 Subject: [PATCH 119/139] Fix gosec issues. --- cmd/importer/importer.go | 5 +++-- pkg/importer/blocks_reader.go | 3 ++- pkg/importer/snapshots_reader.go | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/cmd/importer/importer.go b/cmd/importer/importer.go index 9793cdc07..9ddb71e44 100644 --- a/cmd/importer/importer.go +++ b/cmd/importer/importer.go @@ -5,6 +5,7 @@ import ( "flag" "fmt" "os" + "path/filepath" "runtime" "runtime/debug" "runtime/pprof" @@ -250,7 +251,7 @@ func configureMemProfile(memProfilePath string) error { if memProfilePath == "" { return nil } - f, err := os.Create(memProfilePath) + f, err := os.Create(filepath.Clean(memProfilePath)) if err != nil { return fmt.Errorf("failed to create memory profile: %w", err) } @@ -269,7 +270,7 @@ func configureMemProfile(memProfilePath string) error { func configureBlockchainSettings(blockchainType, cfgPath string) (*settings.BlockchainSettings, error) { var ss *settings.BlockchainSettings if strings.ToLower(blockchainType) == "custom" && cfgPath != "" { - f, err := os.Open(cfgPath) + f, err := os.Open(filepath.Clean(cfgPath)) if err != nil { return nil, fmt.Errorf("failed to open custom blockchain settings: %w", err) } diff --git a/pkg/importer/blocks_reader.go b/pkg/importer/blocks_reader.go index ea1d68223..b2e4c608f 100644 --- a/pkg/importer/blocks_reader.go +++ b/pkg/importer/blocks_reader.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "os" + "path/filepath" ) type blocksReader struct { @@ -13,7 +14,7 @@ type blocksReader struct { } func newBlocksReader(blockchainPath string) (*blocksReader, error) { - f, err := os.Open(blockchainPath) + f, err := os.Open(filepath.Clean(blockchainPath)) if err != nil { return nil, fmt.Errorf("failed to open blocks file: %w", err) } diff --git a/pkg/importer/snapshots_reader.go b/pkg/importer/snapshots_reader.go index e05c3f301..e3a71a649 100644 --- a/pkg/importer/snapshots_reader.go +++ b/pkg/importer/snapshots_reader.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "os" + "path/filepath" "github.com/wavesplatform/gowaves/pkg/proto" ) @@ -16,7 +17,7 @@ type snapshotsReader struct { } func newSnapshotsReader(scheme proto.Scheme, snapshotsPath string) (*snapshotsReader, error) { - f, err := os.Open(snapshotsPath) + f, err := os.Open(filepath.Clean(snapshotsPath)) if err != nil { return nil, fmt.Errorf("failed to open snapshots file: %w", err) } From 7696ebb02aafede02fddc7d33c11d74599e8523e Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Tue, 5 Mar 2024 10:36:57 +0300 Subject: [PATCH 120/139] return to ng if failed to apply block/microblock --- pkg/node/fsm/wait_micro_snapshot.go | 4 ++-- pkg/node/fsm/wait_snapshot_state.go | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pkg/node/fsm/wait_micro_snapshot.go b/pkg/node/fsm/wait_micro_snapshot.go index 82e724466..ca9c7c2eb 100644 --- a/pkg/node/fsm/wait_micro_snapshot.go +++ b/pkg/node/fsm/wait_micro_snapshot.go @@ -86,13 +86,13 @@ func (a *WaitMicroSnapshotState) MicroBlockSnapshot( return a, nil, a.Errorf(errors.Errorf( "New snapshot doesn't match with microBlock %s", a.microBlockWaitingForSnapshot.TotalBlockID)) } + defer a.cleanupBeforeTransition() // the TopBlock() is used here block, err := a.checkAndAppendMicroBlock(a.microBlockWaitingForSnapshot, &snapshot) if err != nil { metrics.FSMMicroBlockDeclined("ng", a.microBlockWaitingForSnapshot, err) - return a, nil, a.Errorf(err) + return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, a.Errorf(err) } - defer a.cleanupBeforeTransition() zap.S().Named(logging.FSMNamespace).Debugf( "[%s] Received snapshot for microblock '%s' successfully applied to state", a, block.BlockID(), diff --git a/pkg/node/fsm/wait_snapshot_state.go b/pkg/node/fsm/wait_snapshot_state.go index d79108a10..3d62e09a8 100644 --- a/pkg/node/fsm/wait_snapshot_state.go +++ b/pkg/node/fsm/wait_snapshot_state.go @@ -77,7 +77,7 @@ func (a *WaitSnapshotState) Task(task tasks.AsyncTask) (State, Async, error) { } func (a *WaitSnapshotState) BlockSnapshot( - peer peer.Peer, + _ peer.Peer, blockID proto.BlockID, snapshot proto.BlockSnapshot, ) (State, Async, error) { @@ -86,6 +86,7 @@ func (a *WaitSnapshotState) BlockSnapshot( errors.Errorf("new snapshot doesn't match with block %s", a.blockWaitingForSnapshot.BlockID())) } + defer a.cleanupBeforeTransition() _, err := a.baseInfo.blocksApplier.ApplyWithSnapshots( a.baseInfo.storage, []*proto.Block{a.blockWaitingForSnapshot}, @@ -93,9 +94,9 @@ func (a *WaitSnapshotState) BlockSnapshot( ) if err != nil { // metrics.FSMKeyBlockDeclined("ng", block, err) - return a, nil, a.Errorf(errors.Wrapf(err, "peer '%s'", peer.ID())) + return newNGStateWithCache(a.baseInfo, a.blocksCache), + nil, a.Errorf(errors.Wrapf(err, "failed to apply block %s", a.blockWaitingForSnapshot.BlockID())) } - defer a.cleanupBeforeTransition() metrics.FSMKeyBlockApplied("ng", a.blockWaitingForSnapshot) zap.S().Named(logging.FSMNamespace).Debugf("[%s] Handle received key block message: block '%s' applied to state", From 34c943d6a3414b0a14faf35c1a0a6f02047f162a Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Tue, 12 Mar 2024 12:24:40 +0300 Subject: [PATCH 121/139] add Score in WaitSnapshots States --- pkg/node/fsm/fsm_common.go | 22 +++++++++++++++++ pkg/node/fsm/wait_micro_snapshot.go | 33 ++++++++++++++++++------- pkg/node/fsm/wait_snapshot_state.go | 37 ++++++++++++++++++++++------- 3 files changed, 76 insertions(+), 16 deletions(-) diff --git a/pkg/node/fsm/fsm_common.go b/pkg/node/fsm/fsm_common.go index b75e92153..7137f6775 100644 --- a/pkg/node/fsm/fsm_common.go +++ b/pkg/node/fsm/fsm_common.go @@ -230,3 +230,25 @@ func broadcastMicroBlockInv(info BaseInfo, inv *proto.MicroBlockInv) error { ) return nil } + +func processScoreAfterApplyingOrReturnToNG( + state State, + baseInfo BaseInfo, + scores []ReceivedScore, + cache blockStatesCache, +) (State, Async, error) { + for _, s := range scores { + if err := baseInfo.peers.UpdateScore(s.Peer, s.Score); err != nil { + return state, nil, state.Errorf(proto.NewInfoMsg(err)) + } + nodeScore, err := baseInfo.storage.CurrentScore() + if err != nil { + return state, nil, state.Errorf(err) + } + if s.Score.Cmp(nodeScore) == 1 { + // received score is larger than local score + return syncWithNewPeer(state, baseInfo, s.Peer) + } + } + return newNGStateWithCache(baseInfo, cache), nil, nil +} diff --git a/pkg/node/fsm/wait_micro_snapshot.go b/pkg/node/fsm/wait_micro_snapshot.go index ca9c7c2eb..1f909d91f 100644 --- a/pkg/node/fsm/wait_micro_snapshot.go +++ b/pkg/node/fsm/wait_micro_snapshot.go @@ -21,6 +21,8 @@ type WaitMicroSnapshotState struct { blocksCache blockStatesCache timeoutTaskOutdated chan<- struct{} microBlockWaitingForSnapshot *proto.MicroBlock + + receivedScores []ReceivedScore } func newWaitMicroSnapshotState(baseInfo BaseInfo, micro *proto.MicroBlock, cache blockStatesCache) (State, tasks.Task) { @@ -65,8 +67,9 @@ func (a *WaitMicroSnapshotState) Task(task tasks.AsyncTask) (State, Async, error return a, nil, nil case tasks.MicroBlockSnapshot: defer a.cleanupBeforeTransition() - return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, a.Errorf(errors.Errorf( - "failed to get snapshot for microBlock '%s' - timeout", t.BlockID)) + zap.S().Errorf("%v", a.Errorf(errors.Errorf( + "failed to get snapshot for microBlock '%s' - timeout", t.BlockID))) + return processScoreAfterApplyingOrReturnToNG(a, a.baseInfo, a.receivedScores, a.blocksCache) default: return a, nil, a.Errorf(errors.New("undefined Snapshot Task type")) } @@ -77,6 +80,12 @@ func (a *WaitMicroSnapshotState) Task(task tasks.AsyncTask) (State, Async, error } } +func (a *WaitMicroSnapshotState) Score(p peer.Peer, score *proto.Score) (State, Async, error) { + metrics.FSMScore("ng", score, p.Handshake().NodeName) + a.receivedScores = append(a.receivedScores, ReceivedScore{Peer: p, Score: score}) + return a, nil, nil +} + func (a *WaitMicroSnapshotState) MicroBlockSnapshot( _ peer.Peer, blockID proto.BlockID, @@ -91,7 +100,8 @@ func (a *WaitMicroSnapshotState) MicroBlockSnapshot( block, err := a.checkAndAppendMicroBlock(a.microBlockWaitingForSnapshot, &snapshot) if err != nil { metrics.FSMMicroBlockDeclined("ng", a.microBlockWaitingForSnapshot, err) - return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, a.Errorf(err) + zap.S().Errorf("%v", a.Errorf(err)) + return processScoreAfterApplyingOrReturnToNG(a, a.baseInfo, a.receivedScores, a.blocksCache) } zap.S().Named(logging.FSMNamespace).Debugf( @@ -105,11 +115,11 @@ func (a *WaitMicroSnapshotState) MicroBlockSnapshot( if inv, ok := a.baseInfo.MicroBlockInvCache.Get(block.BlockID()); ok { //TODO: We have to exclude from recipients peers that already have this microblock if err = broadcastMicroBlockInv(a.baseInfo, inv); err != nil { - return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, - a.Errorf(errors.Wrap(err, "failed to handle microblock message")) + zap.S().Errorf("%v", a.Errorf(errors.Wrap(err, "failed to handle micro block message"))) + return processScoreAfterApplyingOrReturnToNG(a, a.baseInfo, a.receivedScores, a.blocksCache) } } - return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, nil + return processScoreAfterApplyingOrReturnToNG(a, a.baseInfo, a.receivedScores, a.blocksCache) } func (a *WaitMicroSnapshotState) cleanupBeforeTransition() { @@ -193,7 +203,6 @@ func initWaitMicroSnapshotStateInFSM(state *StateData, fsm *stateless.StateMachi proto.ContentIDSignatures, proto.ContentIDGetBlock, proto.ContentIDBlock, - proto.ContentIDScore, proto.ContentIDTransaction, proto.ContentIDInvMicroblock, proto.ContentIDCheckpoint, @@ -210,7 +219,6 @@ func initWaitMicroSnapshotStateInFSM(state *StateData, fsm *stateless.StateMachi info.skipMessageList.SetList(waitSnapshotSkipMessageList) return nil }). - Ignore(ScoreEvent). Ignore(BlockEvent). Ignore(MinedBlockEvent). Ignore(BlockIDsEvent). @@ -244,5 +252,14 @@ func initWaitMicroSnapshotStateInFSM(state *StateData, fsm *stateless.StateMachi args[1].(proto.BlockID), args[2].(proto.BlockSnapshot), ) + })). + PermitDynamic(ScoreEvent, + createPermitDynamicCallback(ScoreEvent, state, func(args ...interface{}) (State, Async, error) { + a, ok := state.State.(*WaitMicroSnapshotState) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type '%T' expected '*WaitMicroSnapshotState'", state.State)) + } + return a.Score(convertToInterface[peer.Peer](args[0]), args[1].(*proto.Score)) })) } diff --git a/pkg/node/fsm/wait_snapshot_state.go b/pkg/node/fsm/wait_snapshot_state.go index 3d62e09a8..2fb1f16ce 100644 --- a/pkg/node/fsm/wait_snapshot_state.go +++ b/pkg/node/fsm/wait_snapshot_state.go @@ -20,6 +20,13 @@ type WaitSnapshotState struct { blocksCache blockStatesCache timeoutTaskOutdated chan<- struct{} blockWaitingForSnapshot *proto.Block + + receivedScores []ReceivedScore +} + +type ReceivedScore struct { + Peer peer.Peer + Score *proto.Score } func newWaitSnapshotState(baseInfo BaseInfo, block *proto.Block, cache blockStatesCache) (State, tasks.Task) { @@ -30,6 +37,7 @@ func newWaitSnapshotState(baseInfo BaseInfo, block *proto.Block, cache blockStat blocksCache: cache, timeoutTaskOutdated: timeoutTaskOutdated, blockWaitingForSnapshot: block, + receivedScores: nil, } task := tasks.NewBlockSnapshotTimeoutTask(time.Minute, block.BlockID(), timeoutTaskOutdated) return st, task @@ -62,8 +70,9 @@ func (a *WaitSnapshotState) Task(task tasks.AsyncTask) (State, Async, error) { switch t.SnapshotTaskType { case tasks.BlockSnapshot: defer a.cleanupBeforeTransition() - return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, a.Errorf(errors.Errorf( - "failed to get snapshot for block '%s' - timeout", t.BlockID)) + zap.S().Errorf("%v", a.Errorf(errors.Errorf( + "failed to get snapshot for block '%s' - timeout", t.BlockID))) + return processScoreAfterApplyingOrReturnToNG(a, a.baseInfo, a.receivedScores, a.blocksCache) case tasks.MicroBlockSnapshot: return a, nil, nil default: @@ -76,6 +85,12 @@ func (a *WaitSnapshotState) Task(task tasks.AsyncTask) (State, Async, error) { } } +func (a *WaitSnapshotState) Score(p peer.Peer, score *proto.Score) (State, Async, error) { + metrics.FSMScore("ng", score, p.Handshake().NodeName) + a.receivedScores = append(a.receivedScores, ReceivedScore{Peer: p, Score: score}) + return a, nil, nil +} + func (a *WaitSnapshotState) BlockSnapshot( _ peer.Peer, blockID proto.BlockID, @@ -93,9 +108,8 @@ func (a *WaitSnapshotState) BlockSnapshot( []*proto.BlockSnapshot{&snapshot}, ) if err != nil { - // metrics.FSMKeyBlockDeclined("ng", block, err) - return newNGStateWithCache(a.baseInfo, a.blocksCache), - nil, a.Errorf(errors.Wrapf(err, "failed to apply block %s", a.blockWaitingForSnapshot.BlockID())) + zap.S().Errorf("%v", a.Errorf(errors.Wrapf(err, "failed to apply block %s", a.blockWaitingForSnapshot.BlockID()))) + return processScoreAfterApplyingOrReturnToNG(a, a.baseInfo, a.receivedScores, a.blocksCache) } metrics.FSMKeyBlockApplied("ng", a.blockWaitingForSnapshot) @@ -108,7 +122,7 @@ func (a *WaitSnapshotState) BlockSnapshot( a.baseInfo.scheduler.Reschedule() a.baseInfo.actions.SendScore(a.baseInfo.storage) a.baseInfo.CleanUtx() - return newNGStateWithCache(a.baseInfo, a.blocksCache), nil, nil + return processScoreAfterApplyingOrReturnToNG(a, a.baseInfo, a.receivedScores, a.blocksCache) } func (a *WaitSnapshotState) cleanupBeforeTransition() { @@ -127,7 +141,6 @@ func initWaitSnapshotStateInFSM(state *StateData, fsm *stateless.StateMachine, i proto.ContentIDSignatures, proto.ContentIDGetBlock, proto.ContentIDBlock, - proto.ContentIDScore, proto.ContentIDTransaction, proto.ContentIDInvMicroblock, proto.ContentIDCheckpoint, @@ -143,7 +156,6 @@ func initWaitSnapshotStateInFSM(state *StateData, fsm *stateless.StateMachine, i info.skipMessageList.SetList(waitSnapshotSkipMessageList) return nil }). - Ignore(ScoreEvent). Ignore(BlockEvent). Ignore(MinedBlockEvent). Ignore(BlockIDsEvent). @@ -177,5 +189,14 @@ func initWaitSnapshotStateInFSM(state *StateData, fsm *stateless.StateMachine, i args[1].(proto.BlockID), args[2].(proto.BlockSnapshot), ) + })). + PermitDynamic(ScoreEvent, + createPermitDynamicCallback(ScoreEvent, state, func(args ...interface{}) (State, Async, error) { + a, ok := state.State.(*WaitSnapshotState) + if !ok { + return a, nil, a.Errorf(errors.Errorf( + "unexpected type '%T' expected '*WaitSnapshotState'", state.State)) + } + return a.Score(convertToInterface[peer.Peer](args[0]), args[1].(*proto.Score)) })) } From a24039e2147ffe2401b1871d9c951d3e709f646b Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Fri, 15 Mar 2024 12:12:28 +0300 Subject: [PATCH 122/139] fix Score check func and reduce timeouts --- pkg/node/fsm/fsm_common.go | 13 ++++++++++--- pkg/node/fsm/wait_micro_snapshot.go | 8 +++++++- pkg/node/fsm/wait_snapshot_state.go | 7 ++++++- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/pkg/node/fsm/fsm_common.go b/pkg/node/fsm/fsm_common.go index 7137f6775..dbe22144f 100644 --- a/pkg/node/fsm/fsm_common.go +++ b/pkg/node/fsm/fsm_common.go @@ -239,15 +239,22 @@ func processScoreAfterApplyingOrReturnToNG( ) (State, Async, error) { for _, s := range scores { if err := baseInfo.peers.UpdateScore(s.Peer, s.Score); err != nil { - return state, nil, state.Errorf(proto.NewInfoMsg(err)) + zap.S().Named(logging.FSMNamespace).Debugf("Error: %v", proto.NewInfoMsg(err)) + continue } nodeScore, err := baseInfo.storage.CurrentScore() if err != nil { - return state, nil, state.Errorf(err) + zap.S().Named(logging.FSMNamespace).Debugf("Error: %v", proto.NewInfoMsg(err)) + continue } if s.Score.Cmp(nodeScore) == 1 { // received score is larger than local score - return syncWithNewPeer(state, baseInfo, s.Peer) + newS, task, errS := syncWithNewPeer(state, baseInfo, s.Peer) + if newS.String() != SyncStateName { + zap.S().Errorf("%v", state.Errorf(errS)) + continue + } + return newS, task, errS } } return newNGStateWithCache(baseInfo, cache), nil, nil diff --git a/pkg/node/fsm/wait_micro_snapshot.go b/pkg/node/fsm/wait_micro_snapshot.go index 1f909d91f..ee0b48bc3 100644 --- a/pkg/node/fsm/wait_micro_snapshot.go +++ b/pkg/node/fsm/wait_micro_snapshot.go @@ -16,6 +16,10 @@ import ( "github.com/wavesplatform/gowaves/pkg/state" ) +const ( + microSnapshotTimeout = 15 +) + type WaitMicroSnapshotState struct { baseInfo BaseInfo blocksCache blockStatesCache @@ -34,7 +38,8 @@ func newWaitMicroSnapshotState(baseInfo BaseInfo, micro *proto.MicroBlock, cache timeoutTaskOutdated: timeoutTaskOutdated, microBlockWaitingForSnapshot: micro, } - task := tasks.NewMicroBlockSnapshotTimeoutTask(time.Minute, micro.TotalBlockID, timeoutTaskOutdated) + task := tasks.NewMicroBlockSnapshotTimeoutTask(time.Second*microSnapshotTimeout, + micro.TotalBlockID, timeoutTaskOutdated) return st, task } @@ -128,6 +133,7 @@ func (a *WaitMicroSnapshotState) cleanupBeforeTransition() { close(a.timeoutTaskOutdated) a.timeoutTaskOutdated = nil } + a.receivedScores = nil } func (a *WaitMicroSnapshotState) checkAndAppendMicroBlock( diff --git a/pkg/node/fsm/wait_snapshot_state.go b/pkg/node/fsm/wait_snapshot_state.go index 2fb1f16ce..2454227ec 100644 --- a/pkg/node/fsm/wait_snapshot_state.go +++ b/pkg/node/fsm/wait_snapshot_state.go @@ -15,6 +15,10 @@ import ( "github.com/wavesplatform/gowaves/pkg/proto" ) +const ( + snapshotTimeout = 30 +) + type WaitSnapshotState struct { baseInfo BaseInfo blocksCache blockStatesCache @@ -39,7 +43,7 @@ func newWaitSnapshotState(baseInfo BaseInfo, block *proto.Block, cache blockStat blockWaitingForSnapshot: block, receivedScores: nil, } - task := tasks.NewBlockSnapshotTimeoutTask(time.Minute, block.BlockID(), timeoutTaskOutdated) + task := tasks.NewBlockSnapshotTimeoutTask(time.Second*snapshotTimeout, block.BlockID(), timeoutTaskOutdated) return st, task } @@ -131,6 +135,7 @@ func (a *WaitSnapshotState) cleanupBeforeTransition() { close(a.timeoutTaskOutdated) a.timeoutTaskOutdated = nil } + a.receivedScores = nil } func initWaitSnapshotStateInFSM(state *StateData, fsm *stateless.StateMachine, info BaseInfo) { From 8ac321f4b55a64ec5e76e1eb4f48b8fb215e3c23 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Tue, 19 Mar 2024 08:02:46 +0300 Subject: [PATCH 123/139] increse message max lenght and allow negative in/out in lease balance snapshot --- pkg/p2p/conn/conn.go | 2 +- pkg/proto/snapshot_types.go | 11 ++--------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/pkg/p2p/conn/conn.go b/pkg/p2p/conn/conn.go index 566d31565..762280964 100644 --- a/pkg/p2p/conn/conn.go +++ b/pkg/p2p/conn/conn.go @@ -17,7 +17,7 @@ import ( ) const ( - maxMessageSize = 2 << (10 * 2) + maxMessageSize = 100 << (10 * 2) maxConnIODurationPerMessage = 15 * time.Second MaxConnIdleIODuration = 5 * time.Minute ) diff --git a/pkg/proto/snapshot_types.go b/pkg/proto/snapshot_types.go index 47644b8b8..2d94266cc 100644 --- a/pkg/proto/snapshot_types.go +++ b/pkg/proto/snapshot_types.go @@ -280,15 +280,8 @@ func (s *LeaseBalanceSnapshot) FromProtobuf(scheme Scheme, p *g.TransactionState if err != nil { return err } - var c ProtobufConverter - in := c.uint64(p.In) - if c.err != nil { - return c.err - } - out := c.uint64(p.Out) - if c.err != nil { - return c.err - } + in := uint64(p.In) + out := uint64(p.Out) s.Address = addr s.LeaseIn = in s.LeaseOut = out From 65cffd46f9583eb5bbadc2c6e734707dfadda584 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Wed, 3 Apr 2024 12:22:39 +0300 Subject: [PATCH 124/139] fix asset volume decode/encode --- pkg/proto/snapshot_types.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/proto/snapshot_types.go b/pkg/proto/snapshot_types.go index 2d94266cc..b7463a30c 100644 --- a/pkg/proto/snapshot_types.go +++ b/pkg/proto/snapshot_types.go @@ -2,6 +2,7 @@ package proto import ( "encoding/json" + "github.com/wavesplatform/gowaves/pkg/util/common" "math/big" "github.com/pkg/errors" @@ -567,7 +568,7 @@ func (s AssetVolumeSnapshot) ToProtobuf() (*g.TransactionStateSnapshot_AssetVolu return &g.TransactionStateSnapshot_AssetVolume{ AssetId: s.AssetID.Bytes(), Reissuable: s.IsReissuable, - Volume: s.TotalQuantity.Bytes(), + Volume: common.Encode2CBigInt(&s.TotalQuantity), }, nil } @@ -588,7 +589,7 @@ func (s *AssetVolumeSnapshot) FromProtobuf(p *g.TransactionStateSnapshot_AssetVo } s.AssetID = assetID - s.TotalQuantity.SetBytes(p.Volume) + s.TotalQuantity = *common.Decode2CBigInt(p.Volume) s.IsReissuable = p.Reissuable return nil } From 45b1c2b234d79d668159c7aac0545bd9ca1f145e Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Thu, 4 Apr 2024 12:06:18 +0300 Subject: [PATCH 125/139] fix linters --- pkg/p2p/conn/conn.go | 4 +++- pkg/proto/snapshot_types.go | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/p2p/conn/conn.go b/pkg/p2p/conn/conn.go index 762280964..b477bbe55 100644 --- a/pkg/p2p/conn/conn.go +++ b/pkg/p2p/conn/conn.go @@ -17,7 +17,9 @@ import ( ) const ( - maxMessageSize = 100 << (10 * 2) + KiB = 1024 + MiB = KiB * KiB + maxMessageSize = 100 * MiB maxConnIODurationPerMessage = 15 * time.Second MaxConnIdleIODuration = 5 * time.Minute ) diff --git a/pkg/proto/snapshot_types.go b/pkg/proto/snapshot_types.go index b7463a30c..238872d19 100644 --- a/pkg/proto/snapshot_types.go +++ b/pkg/proto/snapshot_types.go @@ -2,13 +2,13 @@ package proto import ( "encoding/json" - "github.com/wavesplatform/gowaves/pkg/util/common" "math/big" "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/crypto" g "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" + "github.com/wavesplatform/gowaves/pkg/util/common" ) type AtomicSnapshot interface { From 2f5445a45f954e7cac39c939af297618e51a846c Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Fri, 12 Apr 2024 15:05:02 +0300 Subject: [PATCH 126/139] move ask blockIDs --- pkg/node/fsm/sync_internal/internal.go | 5 ++++- pkg/node/fsm/sync_state.go | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/node/fsm/sync_internal/internal.go b/pkg/node/fsm/sync_internal/internal.go index 673aae87d..3223cf254 100644 --- a/pkg/node/fsm/sync_internal/internal.go +++ b/pkg/node/fsm/sync_internal/internal.go @@ -109,11 +109,14 @@ func (a Internal) Blocks(p peerExtension) (Internal, Blocks, Snapshots, Eof) { bs, ss := a.orderedBlocks.PopAll(a.isLightNode) return NewInternal(a.orderedBlocks, a.respondedSignatures, false, a.isLightNode), bs, ss, true } - p.AskBlocksIDs(a.respondedSignatures.BlockIDS()) bs, ss := a.orderedBlocks.PopAll(a.isLightNode) return NewInternal(a.orderedBlocks, a.respondedSignatures, true, a.isLightNode), bs, ss, false } +func (a Internal) AskBlocksIDs(p peerExtension) { + p.AskBlocksIDs(a.respondedSignatures.BlockIDS()) +} + func (a Internal) AvailableCount() int { return a.orderedBlocks.ReceivedCount(a.isLightNode) } diff --git a/pkg/node/fsm/sync_state.go b/pkg/node/fsm/sync_state.go index 456a4b90b..8da6d3380 100644 --- a/pkg/node/fsm/sync_state.go +++ b/pkg/node/fsm/sync_state.go @@ -304,6 +304,7 @@ func (a *SyncState) applyBlocksWithSnapshots( } return newNGState(a.baseInfo), nil, nil } + a.internal.AskBlocksIDs(extension.NewPeerExtension(a.conf.peerSyncWith, a.baseInfo.scheme)) return newSyncState(baseInfo, conf, internal), nil, nil } From 09a69f8f4d7d1dd9279085ac61b779403e6be8f5 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Fri, 12 Apr 2024 16:19:06 +0300 Subject: [PATCH 127/139] fix linters --- cmd/importer/importer.go | 20 ++++++++++++-------- pkg/node/fsm/sync_internal/internal.go | 2 +- pkg/node/fsm/sync_internal/internal_test.go | 4 ++-- pkg/node/fsm/sync_state.go | 12 ++---------- 4 files changed, 17 insertions(+), 21 deletions(-) diff --git a/cmd/importer/importer.go b/cmd/importer/importer.go index 0e360589c..4e4a9ee62 100644 --- a/cmd/importer/importer.go +++ b/cmd/importer/importer.go @@ -211,14 +211,7 @@ func run() error { if hErr != nil { zap.S().Fatalf("Failed to get current height: %v", hErr) } - switch { - case errors.Is(impErr, context.Canceled): - zap.S().Infof("Interrupted by user, height %d", currentHeight) - case errors.Is(impErr, io.EOF): - zap.S().Info("End of blockchain file reached, height %d", currentHeight) - default: - zap.S().Fatalf("Failed to apply blocks after height %d: %v", currentHeight, impErr) - } + handleError(impErr, currentHeight) } elapsed := time.Since(start) zap.S().Infof("Import took %s", elapsed) @@ -237,6 +230,17 @@ func run() error { return nil } +func handleError(err error, height uint64) { + switch { + case errors.Is(err, context.Canceled): + zap.S().Infof("Interrupted by user, height %d", height) + case errors.Is(err, io.EOF): + zap.S().Info("End of blockchain file reached, height %d", height) + default: + zap.S().Fatalf("Failed to apply blocks after height %d: %v", height, err) + } +} + func selectImporter(c cfg, ss *settings.BlockchainSettings, st importer.State) (importer.Importer, func(), error) { if c.lightNodeMode { imp, err := importer.NewSnapshotsImporter(ss.AddressSchemeCharacter, st, c.blockchainPath, c.snapshotsPath) diff --git a/pkg/node/fsm/sync_internal/internal.go b/pkg/node/fsm/sync_internal/internal.go index 3223cf254..79c09a3a0 100644 --- a/pkg/node/fsm/sync_internal/internal.go +++ b/pkg/node/fsm/sync_internal/internal.go @@ -98,7 +98,7 @@ type peerExtension interface { AskBlocksIDs(id []proto.BlockID) } -func (a Internal) Blocks(p peerExtension) (Internal, Blocks, Snapshots, Eof) { +func (a Internal) Blocks() (Internal, Blocks, Snapshots, Eof) { if a.waitingForSignatures { return NewInternal(a.orderedBlocks, a.respondedSignatures, a.waitingForSignatures, a.isLightNode), nil, nil, false } diff --git a/pkg/node/fsm/sync_internal/internal_test.go b/pkg/node/fsm/sync_internal/internal_test.go index a330f27eb..3c9546017 100644 --- a/pkg/node/fsm/sync_internal/internal_test.go +++ b/pkg/node/fsm/sync_internal/internal_test.go @@ -75,13 +75,13 @@ func TestSigFSM_Block(t *testing.T) { require.Equal(t, 2, fsm.AvailableCount()) // no panic, cause `nearEnd` is True - _, blocks, _, _ := fsm.Blocks(nil) + _, blocks, _, _ := fsm.Blocks() require.Equal(t, 2, len(blocks)) } func TestSigFSM_BlockGetSignatures(t *testing.T) { or := ordered_blocks.NewOrderedBlocks() sigs := signatures.NewSignatures() - _, bs, _, _ := NewInternal(or, sigs, false, false).Blocks(nil) + _, bs, _, _ := NewInternal(or, sigs, false, false).Blocks() require.Nil(t, bs) } diff --git a/pkg/node/fsm/sync_state.go b/pkg/node/fsm/sync_state.go index 8da6d3380..4643c8e71 100644 --- a/pkg/node/fsm/sync_state.go +++ b/pkg/node/fsm/sync_state.go @@ -38,14 +38,6 @@ func (c conf) Now(tm types.Time) conf { } } -type noopWrapper struct{} - -func (noopWrapper) AskBlocksIDs([]proto.BlockID) {} - -func (noopWrapper) AskBlock(proto.BlockID) {} - -func (noopWrapper) AskBlockSnapshot(proto.BlockID) {} - type SyncState struct { baseInfo BaseInfo conf conf @@ -73,7 +65,7 @@ func (a *SyncState) Transaction(p peer.Peer, t proto.Transaction) (State, Async, } func (a *SyncState) StopSync() (State, Async, error) { - _, blocks, snapshots, _ := a.internal.Blocks(noopWrapper{}) + _, blocks, snapshots, _ := a.internal.Blocks() if len(blocks) > 0 { var err error if a.baseInfo.enableLightMode { @@ -250,7 +242,7 @@ func (a *SyncState) changePeerIfRequired() (peer.Peer, bool) { func (a *SyncState) applyBlocksWithSnapshots( baseInfo BaseInfo, conf conf, internal sync_internal.Internal, ) (State, Async, error) { - internal, blocks, snapshots, eof := internal.Blocks(extension.NewPeerExtension(a.conf.peerSyncWith, a.baseInfo.scheme)) + internal, blocks, snapshots, eof := internal.Blocks() if len(blocks) == 0 { zap.S().Named(logging.FSMNamespace).Debug("[Sync] No blocks to apply") return newSyncState(baseInfo, conf, internal), nil, nil From 8dbe7ecabd72e5fd01d9e8c46e0709cc0886f3e3 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Sat, 13 Apr 2024 19:41:13 +0300 Subject: [PATCH 128/139] Fix log records. --- cmd/chaincmp/chaincmp.go | 2 +- cmd/convert/main.go | 5 +++-- cmd/importer/importer.go | 2 +- cmd/node/node.go | 2 +- pkg/metrics/metrics.go | 9 +++++---- pkg/node/peers/peer_manager.go | 2 +- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/cmd/chaincmp/chaincmp.go b/cmd/chaincmp/chaincmp.go index f25d0a8e8..06b748417 100644 --- a/cmd/chaincmp/chaincmp.go +++ b/cmd/chaincmp/chaincmp.go @@ -96,7 +96,7 @@ func run() error { for i, u := range other { u, err = checkAndUpdateURL(u) if err != nil { - zap.S().Error("Incorrect reference's URL: %s", err.Error()) + zap.S().Errorf("Incorrect reference's URL: %s", err.Error()) return errInvalidParameters } other[i] = u diff --git a/cmd/convert/main.go b/cmd/convert/main.go index 98473ddd8..d575998f9 100644 --- a/cmd/convert/main.go +++ b/cmd/convert/main.go @@ -5,8 +5,9 @@ import ( "flag" "os" - "github.com/wavesplatform/gowaves/pkg/proto" "go.uber.org/zap" + + "github.com/wavesplatform/gowaves/pkg/proto" ) var ( @@ -28,7 +29,7 @@ func main() { zap.S().Fatal("please, provide scheme-byte argument") } if len(*schemeByte) != 1 { - zap.S().Fatal("invalid scheme-byte argument %q", *schemeByte) + zap.S().Fatalf("invalid scheme-byte argument %q", *schemeByte) } scheme := []byte(*schemeByte)[0] switch *command { diff --git a/cmd/importer/importer.go b/cmd/importer/importer.go index 4e4a9ee62..08837ee80 100644 --- a/cmd/importer/importer.go +++ b/cmd/importer/importer.go @@ -235,7 +235,7 @@ func handleError(err error, height uint64) { case errors.Is(err, context.Canceled): zap.S().Infof("Interrupted by user, height %d", height) case errors.Is(err, io.EOF): - zap.S().Info("End of blockchain file reached, height %d", height) + zap.S().Infof("End of blockchain file reached, height %d", height) default: zap.S().Fatalf("Failed to apply blocks after height %d: %v", height, err) } diff --git a/cmd/node/node.go b/cmd/node/node.go index ec90a0af5..68a693e31 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -387,7 +387,7 @@ func main() { st, err := state.NewState(path, true, params, cfg, nc.enableLightMode) if err != nil { - zap.S().Error("Failed to initialize node's state: %v", err) + zap.S().Errorf("Failed to initialize node's state: %v", err) return } diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index e2393ba66..e89fdf866 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -11,9 +11,10 @@ import ( influx "github.com/influxdata/influxdb1-client/v2" "github.com/pkg/errors" + "go.uber.org/zap" + "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/proto" - "go.uber.org/zap" ) const ( @@ -475,7 +476,7 @@ func (r *reporter) run(ctx context.Context) { rep = nil err := r.c.Close() if err != nil { - zap.S().Warn("Failed to close connection to InfluxDB: %v", err) + zap.S().Warnf("Failed to close connection to InfluxDB: %v", err) } return case <-ticker.C: @@ -537,7 +538,7 @@ func parseURL(s string) (influx.HTTPConfig, string, error) { func reportBlock(t tags, f fields) { p, err := influx.NewPoint("block", t, f, time.Now()) if err != nil { - zap.S().Warn("Failed to create metrics point 'block': %v", err) + zap.S().Warnf("Failed to create metrics point 'block': %v", err) return } rep.in <- p @@ -546,7 +547,7 @@ func reportBlock(t tags, f fields) { func reportFSM(t tags, f fields) { p, err := influx.NewPoint("fsm", t, f, time.Now()) if err != nil { - zap.S().Warn("Failed to create metrics point 'fsm': %v", err) + zap.S().Warnf("Failed to create metrics point 'fsm': %v", err) return } rep.in <- p diff --git a/pkg/node/peers/peer_manager.go b/pkg/node/peers/peer_manager.go index 96752caad..b0942c6cf 100644 --- a/pkg/node/peers/peer_manager.go +++ b/pkg/node/peers/peer_manager.go @@ -430,7 +430,7 @@ func (a *PeerManagerImpl) AddAddress(ctx context.Context, addr proto.TCPAddr) er if removeErr := a.peerStorage.DeleteKnown([]storage.KnownPeer{known}); removeErr != nil { zap.S().Errorf("Failed to remove peer %q from known peers storage", known.String()) } - zap.S().Named(logging.NetworkNamespace).Debug("Error: %v", err) + zap.S().Named(logging.NetworkNamespace).Debugf("Error: %v", err) } }() return nil From 95cae23c4c33f6190c96779a498454f7e936fff5 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Sat, 13 Apr 2024 23:55:35 +0300 Subject: [PATCH 129/139] Fix 'TestTxSnapshotHasher'. --- pkg/state/snapshot_hasher_internal_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/state/snapshot_hasher_internal_test.go b/pkg/state/snapshot_hasher_internal_test.go index 71b18c6d9..937af4983 100644 --- a/pkg/state/snapshot_hasher_internal_test.go +++ b/pkg/state/snapshot_hasher_internal_test.go @@ -139,7 +139,7 @@ func TestTxSnapshotHasher(t *testing.T) { }, { testCaseName: "asset_volume_two's_complement", - pbInBase64: "MicKIOfYm9p3M/NiYXCvwCU3ho5eVFpwE5iekWev4QXhZMvuEAEaAcg=", + pbInBase64: "MigKIOfYm9p3M/NiYXCvwCU3ho5eVFpwE5iekWev4QXhZMvuEAEaAgDI", prevStateHashHex: "6502773294f32cc1702d374ffc1e67ee278cd63c5f00432f80f64a689fcb17f9", expectedStateHashHex: "b5f7e36556cb0d9a72bc9612be017a3cf174cfcb059d86c91621bfe7e8b74ff1", transactionIDBase58: "Gc2kPdPb1qrCPMy1Ga6SD5PDs2Equa6aazxhKjtDzrv1", // valid txID from testnet From 429030e6673c805f44bb1b3279cdab89c06779bd Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Sat, 13 Apr 2024 23:55:52 +0300 Subject: [PATCH 130/139] Add new testcase for 'TestTxSnapshotMarshalToPBAndUnmarshalFromPB'. --- pkg/proto/snapshot_types_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/proto/snapshot_types_test.go b/pkg/proto/snapshot_types_test.go index cc240a6cf..d55f3fe62 100644 --- a/pkg/proto/snapshot_types_test.go +++ b/pkg/proto/snapshot_types_test.go @@ -81,6 +81,10 @@ func TestTxSnapshotMarshalToPBAndUnmarshalFromPB(t *testing.T) { testCaseName: "all_together", pbInBase64: "CkMKGgFUYP1Q7yDeRXEgffuciL58HC+KIscK2I+1EiUKIF5mn4IKZ9CIbYdHjPBDoqx4XMevVdwxzhB1OUvTUKJbEJBOCkQKGgFUQsXJY3P1D9gTUGBPHBTypsklatr9GbAqEiYKIHidwBEj1TYPcIKv1LRquL/otRYLv7UmwEPl/Hg6T4lOEKCcAQokChoBVGD9UO8g3kVxIH37nIi+fBwviiLHCtiPtRIGEICU69wDCiQKGgFUQsXJY3P1D9gTUGBPHBTypsklatr9GbAqEgYQgKjWuQcSIgoaAVRg/VDvIN5FcSB9+5yIvnwcL4oixwrYj7UYgJri4RASIgoaAVRCxcljc/UP2BNQYE8cFPKmySVq2v0ZsCoQgK7NvhQSIgoaAVQwI8uotbzVfYC2BqPYrAX1CRomrjsJ6/0YgKjWuQcSHAoaAVRhIl3y/Mj2ursZ0i4PLrkkxzzOLj3sT3waZgoguIIzLIWCBbxl3Ysa38C0yvtZan6R9ZvOU33eldmrOo0SIFDHWa9Cd6VU8M20LLFHzbBTveERf1sEOw19SUS40GBoGhoBVELFyWNz9Q/YE1BgTxwU8qbJJWra/RmwKiCA8ouoCSIiCiC4gjMshYIFvGXdixrfwLTK+1lqfpH1m85Tfd6V2as6jSpGCiBeZp+CCmfQiG2HR4zwQ6KseFzHr1XcMc4QdTlL01CiWxIg3GBhamPTKLR06Q6bJKMnDfzLetm2Xz8SAuH6VNGUwZ4gASpGCiB4ncARI9U2D3CCr9S0ari/6LUWC7+1JsBD5fx4Ok+JThIg3GBhamPTKLR06Q6bJKMnDfzLetm2Xz8SAuH6VNGUwZ4YCDIvCiB4ncARI9U2D3CCr9S0ari/6LUWC7+1JsBD5fx4Ok+JThABGgkE//////////YyJQogXmafggpn0Ihth0eM8EOirHhcx69V3DHOEHU5S9NQolsaAQEyKAogOG+NPdNOUn6/g2LbTm9xhzWb1ZaCdA8Wi+OYkjUfrbIaBDuaygA6QwogeJ3AESPVNg9wgq/UtGq4v+i1Fgu/tSbAQ+X8eDpPiU4SB25ld25hbWUaFnNvbWUgZmFuY3kgZGVzY3JpcHRpb25KJgoaAVRCxcljc/UP2BNQYE8cFPKmySVq2v0ZsCoSCHdhdmVzZXZvUisKIMkknO8yHpMUT/XKkkdlrbYCG0Dt+qvVgphfgtRbyRDMEICU69wDGNAPUisKIJZ9YwvJObbWItHAD2zhbaFOTFx2zQ4p0Xbo81GXHKeEEICU69wDGNAPWi4KIFDHWa9Cd6VU8M20LLFHzbBTveERf1sEOw19SUS40GBoEgcGAQaw0U/PGPoBYloKGgFUYP1Q7yDeRXEgffuciL58HC+KIscK2I+1EgUKA2ZvbxISCgNiYXJqC1N0cmluZ1ZhbHVlEiEKA2JhemIaAVRg/VDvIN5FcSB9+5yIvnwcL4oixwrYj7ViLwoaAVRCxcljc/UP2BNQYE8cFPKmySVq2v0ZsCoSCAoDZm9vULAJEgcKA2JhclgBaiUKIHidwBEj1TYPcIKv1LRquL/otRYLv7UmwEPl/Hg6T4lOEPwqcAE=", //nolint:lll }, + { + testCaseName: "asset_volume_two's_complement", + pbInBase64: "MigKIOfYm9p3M/NiYXCvwCU3ho5eVFpwE5iekWev4QXhZMvuEAEaAgDI", + }, } for _, testCase := range testCases { t.Run(testCase.testCaseName, func(t *testing.T) { From ce73b95b1cc6f99d2371ed6d640fafab9e77ca23 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Tue, 16 Apr 2024 01:26:44 +0300 Subject: [PATCH 131/139] Remove unnecessary closure from 'selectImporter' im 'cmd/importer/importer.go'. --- cmd/importer/importer.go | 51 +++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/cmd/importer/importer.go b/cmd/importer/importer.go index 08837ee80..179b73f20 100644 --- a/cmd/importer/importer.go +++ b/cmd/importer/importer.go @@ -185,24 +185,21 @@ func run() error { } }() - imp, impClose, err := selectImporter(c, ss, st) + imp, err := selectImporter(c, ss, st) if err != nil { return fmt.Errorf("failed to create importer: %w", err) } - defer impClose() + defer func() { + if clErr := imp.Close(); clErr != nil { + zap.S().Errorf("Failed to close (%T) importer: %v", imp, clErr) + } + }() ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt) defer cancel() - height, err := st.Height() - if err != nil { - return fmt.Errorf("failed to get current height: %w", err) - } - if height > 1 { - zap.S().Infof("Skipping to height %d", height) - if skErr := imp.SkipToHeight(ctx, height); skErr != nil { - return fmt.Errorf("failed to skip to state height: %w", skErr) - } + if skipErr := skipToCurrentBlockchainHeight(ctx, st, imp); skipErr != nil { + return skipErr } start := time.Now() @@ -230,6 +227,20 @@ func run() error { return nil } +func skipToCurrentBlockchainHeight(ctx context.Context, st state.State, imp importer.Importer) error { + height, err := st.Height() + if err != nil { + return fmt.Errorf("failed to get current height: %w", err) + } + if height > 1 { + zap.S().Infof("Skipping to height %d", height) + if skErr := imp.SkipToHeight(ctx, height); skErr != nil { + return fmt.Errorf("failed to skip to state height: %w", skErr) + } + } + return nil +} + func handleError(err error, height uint64) { switch { case errors.Is(err, context.Canceled): @@ -241,27 +252,19 @@ func handleError(err error, height uint64) { } } -func selectImporter(c cfg, ss *settings.BlockchainSettings, st importer.State) (importer.Importer, func(), error) { +func selectImporter(c cfg, ss *settings.BlockchainSettings, st importer.State) (importer.Importer, error) { if c.lightNodeMode { imp, err := importer.NewSnapshotsImporter(ss.AddressSchemeCharacter, st, c.blockchainPath, c.snapshotsPath) if err != nil { - return nil, nil, fmt.Errorf("failed to create snapshots importer: %w", err) + return nil, fmt.Errorf("failed to create snapshots importer: %w", err) } - return imp, func() { - if clErr := imp.Close(); clErr != nil { - zap.S().Errorf("Failed to close snapshots importer: %v", clErr) - } - }, nil + return imp, nil } imp, err := importer.NewBlocksImporter(ss.AddressSchemeCharacter, st, c.blockchainPath) if err != nil { - return nil, nil, fmt.Errorf("failed to create blocks importer: %w", err) + return nil, fmt.Errorf("failed to create blocks importer: %w", err) } - return imp, func() { - if clErr := imp.Close(); clErr != nil { - zap.S().Errorf("Failed to close blocks importer: %v", clErr) - } - }, nil + return imp, nil } func configureMemProfile(memProfilePath string) error { From 875ebd8755d89498dac075b7af6cf69e5aa213b8 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Tue, 16 Apr 2024 02:39:48 +0300 Subject: [PATCH 132/139] Optimized a bit 'BlockSnapshot.ToProtobuf'. --- pkg/proto/block_snapshot.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pkg/proto/block_snapshot.go b/pkg/proto/block_snapshot.go index 99eb1bfa4..1dbe8c1e9 100644 --- a/pkg/proto/block_snapshot.go +++ b/pkg/proto/block_snapshot.go @@ -69,15 +69,16 @@ func (bs *BlockSnapshot) UnmarshalBinary(data []byte, scheme Scheme) error { } func (bs BlockSnapshot) ToProtobuf() ([]*g.TransactionStateSnapshot, error) { - res := make([]*g.TransactionStateSnapshot, 0, len(bs.TxSnapshots)) - for _, ts := range bs.TxSnapshots { - var tsProto g.TransactionStateSnapshot + data := make([]g.TransactionStateSnapshot, len(bs.TxSnapshots)) + res := make([]*g.TransactionStateSnapshot, len(bs.TxSnapshots)) + for i, ts := range bs.TxSnapshots { + tsProto := &data[i] for _, atomicSnapshot := range ts { - if err := atomicSnapshot.AppendToProtobuf(&tsProto); err != nil { + if err := atomicSnapshot.AppendToProtobuf(tsProto); err != nil { return nil, errors.Wrap(err, "failed to marshall TransactionSnapshot to proto") } } - res = append(res, &tsProto) + res[i] = tsProto } return res, nil } From 1f9adbd8a529788e8fd16e2f6b2f067347ecce6c Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Tue, 16 Apr 2024 04:29:07 +0300 Subject: [PATCH 133/139] Optimized a bit 'NGState.checkAndAppendMicroBlock'. --- pkg/node/fsm/ng_state.go | 6 +++--- pkg/proto/block_snapshot.go | 4 ++++ pkg/proto/protobuf_converters.go | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pkg/node/fsm/ng_state.go b/pkg/node/fsm/ng_state.go index 73caf45a0..319def2a8 100644 --- a/pkg/node/fsm/ng_state.go +++ b/pkg/node/fsm/ng_state.go @@ -342,9 +342,9 @@ func (a *NGState) checkAndAppendMicroBlock( if errSAtH != nil { return nil, errSAtH } - for _, sn := range snapshot.TxSnapshots { - topBlockSnapshots.AppendTxSnapshot(sn) - } + + topBlockSnapshots.AppendTxSnapshots(snapshot.TxSnapshots) + snapshotsToApply = &topBlockSnapshots err = a.baseInfo.storage.Map(func(state state.State) error { _, er := a.baseInfo.blocksApplier.ApplyMicroWithSnapshots(state, newBlock, snapshotsToApply) diff --git a/pkg/proto/block_snapshot.go b/pkg/proto/block_snapshot.go index 1dbe8c1e9..0f6edcf72 100644 --- a/pkg/proto/block_snapshot.go +++ b/pkg/proto/block_snapshot.go @@ -17,6 +17,10 @@ func (bs *BlockSnapshot) AppendTxSnapshot(txSnapshot []AtomicSnapshot) { bs.TxSnapshots = append(bs.TxSnapshots, txSnapshot) } +func (bs *BlockSnapshot) AppendTxSnapshots(txSnapshots [][]AtomicSnapshot) { + bs.TxSnapshots = append(bs.TxSnapshots, txSnapshots...) +} + func (bs BlockSnapshot) MarshallBinary() ([]byte, error) { result := binary.BigEndian.AppendUint32([]byte{}, uint32(len(bs.TxSnapshots))) for _, ts := range bs.TxSnapshots { diff --git a/pkg/proto/protobuf_converters.go b/pkg/proto/protobuf_converters.go index 2122529cf..d00f7ae8a 100644 --- a/pkg/proto/protobuf_converters.go +++ b/pkg/proto/protobuf_converters.go @@ -405,7 +405,7 @@ func BlockSnapshotFromProtobuf(scheme Scheme, blockSnapshot []*g.TransactionStat if err != nil { return BlockSnapshot{}, err } - res.TxSnapshots = append(res.TxSnapshots, txSnapshots) + res.AppendTxSnapshot(txSnapshots) } return res, nil } From 5364dde382552f9261aaddf730ce8fa6f85eac22 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Tue, 16 Apr 2024 04:44:05 +0300 Subject: [PATCH 134/139] Optimized a bit 'WaitMicroSnapshotState.checkAndAppendMicroBlock'. --- pkg/node/fsm/wait_micro_snapshot.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/node/fsm/wait_micro_snapshot.go b/pkg/node/fsm/wait_micro_snapshot.go index ee0b48bc3..dc0898d41 100644 --- a/pkg/node/fsm/wait_micro_snapshot.go +++ b/pkg/node/fsm/wait_micro_snapshot.go @@ -184,9 +184,9 @@ func (a *WaitMicroSnapshotState) checkAndAppendMicroBlock( if errSAtH != nil { return nil, errSAtH } - for _, sn := range snapshot.TxSnapshots { - topBlockSnapshots.AppendTxSnapshot(sn) - } + + topBlockSnapshots.AppendTxSnapshots(snapshot.TxSnapshots) + snapshotsToApply = &topBlockSnapshots err = a.baseInfo.storage.Map(func(state state.State) error { _, er := a.baseInfo.blocksApplier.ApplyMicroWithSnapshots(state, newBlock, snapshotsToApply) From 0ad28e32108a4ea33b17514232c121bab1bb25e4 Mon Sep 17 00:00:00 2001 From: Anton Ilin Date: Fri, 19 Apr 2024 10:39:11 +0300 Subject: [PATCH 135/139] rewrite ApplyFromFile in importer and fix some issues --- cmd/importer/importer.go | 48 ++++----------------- cmd/node/node.go | 4 +- itests/net/connection.go | 4 +- pkg/importer/importer.go | 37 +++++++++++----- pkg/importer/snapshots_importer.go | 3 +- pkg/node/blocks_applier/blocks_applier.go | 14 +++++-- pkg/node/fsm/fsm_common.go | 2 +- pkg/node/fsm/ng_state.go | 44 ++++++++++--------- pkg/node/fsm/wait_micro_snapshot.go | 18 ++++---- pkg/node/fsm/wait_snapshot_state.go | 14 ++++--- pkg/proto/proto.go | 5 ++- pkg/state/api.go | 2 - pkg/state/state_test.go | 51 +++++++++++++++++------ 13 files changed, 135 insertions(+), 111 deletions(-) diff --git a/cmd/importer/importer.go b/cmd/importer/importer.go index 179b73f20..9255bc53e 100644 --- a/cmd/importer/importer.go +++ b/cmd/importer/importer.go @@ -112,7 +112,6 @@ func (c *cfg) params(maxFDs int) state.StateParams { params.StoreExtendedApiData = c.buildDataForExtendedAPI params.BuildStateHashes = c.buildStateHashes params.ProvideExtendedApi = false // We do not need to provide any APIs during import. - params.LightNodeMode = c.lightNodeMode return params } @@ -185,25 +184,23 @@ func run() error { } }() - imp, err := selectImporter(c, ss, st) + height, err := st.Height() if err != nil { - return fmt.Errorf("failed to create importer: %w", err) + return fmt.Errorf("failed to get current height: %w", err) } - defer func() { - if clErr := imp.Close(); clErr != nil { - zap.S().Errorf("Failed to close (%T) importer: %v", imp, clErr) - } - }() ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt) defer cancel() - if skipErr := skipToCurrentBlockchainHeight(ctx, st, imp); skipErr != nil { - return skipErr + params := importer.ImportParams{ + Schema: ss.AddressSchemeCharacter, + BlockchainPath: c.blockchainPath, + SnapshotsPath: c.snapshotsPath, + LightNodeMode: c.lightNodeMode, } start := time.Now() - if impErr := imp.Import(ctx, uint64(c.nBlocks)); impErr != nil { + if impErr := importer.ApplyFromFile(ctx, params, st, uint64(c.nBlocks), height); impErr != nil { currentHeight, hErr := st.Height() if hErr != nil { zap.S().Fatalf("Failed to get current height: %v", hErr) @@ -227,20 +224,6 @@ func run() error { return nil } -func skipToCurrentBlockchainHeight(ctx context.Context, st state.State, imp importer.Importer) error { - height, err := st.Height() - if err != nil { - return fmt.Errorf("failed to get current height: %w", err) - } - if height > 1 { - zap.S().Infof("Skipping to height %d", height) - if skErr := imp.SkipToHeight(ctx, height); skErr != nil { - return fmt.Errorf("failed to skip to state height: %w", skErr) - } - } - return nil -} - func handleError(err error, height uint64) { switch { case errors.Is(err, context.Canceled): @@ -252,21 +235,6 @@ func handleError(err error, height uint64) { } } -func selectImporter(c cfg, ss *settings.BlockchainSettings, st importer.State) (importer.Importer, error) { - if c.lightNodeMode { - imp, err := importer.NewSnapshotsImporter(ss.AddressSchemeCharacter, st, c.blockchainPath, c.snapshotsPath) - if err != nil { - return nil, fmt.Errorf("failed to create snapshots importer: %w", err) - } - return imp, nil - } - imp, err := importer.NewBlocksImporter(ss.AddressSchemeCharacter, st, c.blockchainPath) - if err != nil { - return nil, fmt.Errorf("failed to create blocks importer: %w", err) - } - return imp, nil -} - func configureMemProfile(memProfilePath string) error { if memProfilePath == "" { return nil diff --git a/cmd/node/node.go b/cmd/node/node.go index 68a693e31..1ab5d4789 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -429,7 +429,7 @@ func main() { return } peerSpawnerImpl := peers.NewPeerSpawner(parent, conf.WavesNetwork, declAddr, nc.nodeName, - nodeNonce.Uint64(), proto.ProtocolVersion) + nodeNonce.Uint64(), proto.ProtocolVersion()) peerStorage, err := peersPersistentStorage.NewCBORStorage(nc.statePath, time.Now()) if err != nil { zap.S().Errorf("Failed to open or create peers storage: %v", err) @@ -447,7 +447,7 @@ func main() { peerSpawnerImpl, peerStorage, int(nc.limitAllConnections/2), - proto.ProtocolVersion, + proto.ProtocolVersion(), conf.WavesNetwork, !nc.disableOutgoingConnections, nc.newConnectionsLimit, diff --git a/itests/net/connection.go b/itests/net/connection.go index 2411ad5f7..f4e19082c 100644 --- a/itests/net/connection.go +++ b/itests/net/connection.go @@ -84,11 +84,11 @@ func NewNodeConnections(p *d.Ports) (NodeConnections, error) { } func establishConnections(p *d.Ports) (NodeConnections, error) { - goCon, err := NewConnection(proto.TCPAddr{}, d.Localhost+":"+p.Go.BindPort, proto.ProtocolVersion, "wavesL") + goCon, err := NewConnection(proto.TCPAddr{}, d.Localhost+":"+p.Go.BindPort, proto.ProtocolVersion(), "wavesL") if err != nil { return NodeConnections{}, errors.Wrap(err, "failed to create connection to go node") } - scalaCon, err := NewConnection(proto.TCPAddr{}, d.Localhost+":"+p.Scala.BindPort, proto.ProtocolVersion, "wavesL") + scalaCon, err := NewConnection(proto.TCPAddr{}, d.Localhost+":"+p.Scala.BindPort, proto.ProtocolVersion(), "wavesL") if err != nil { if closeErr := goCon.Close(); closeErr != nil { err = errors.Wrap(err, closeErr.Error()) diff --git a/pkg/importer/importer.go b/pkg/importer/importer.go index 76e37969c..217800433 100644 --- a/pkg/importer/importer.go +++ b/pkg/importer/importer.go @@ -25,8 +25,6 @@ const ( MaxBlockSize = 2 * MiB ) -var errNoop = errors.New("noop") - type State interface { AddBlocks(blocks [][]byte) error AddBlocksWithSnapshots(blocks [][]byte, snapshots []*proto.BlockSnapshot) error @@ -55,35 +53,54 @@ func maybePersistTxs(st State) error { return nil } +type ImportParams struct { + Schema proto.Scheme + BlockchainPath, SnapshotsPath string + LightNodeMode bool +} + // ApplyFromFile reads blocks from blockchainPath, applying them from height startHeight and until nBlocks+1. // Setting optimize to true speeds up the import, but it is only safe when importing blockchain from scratch // when no rollbacks are possible at all. func ApplyFromFile( ctx context.Context, - scheme proto.Scheme, - st State, - blockchainPath string, + params ImportParams, + state State, nBlocks, startHeight uint64, ) error { if ctx == nil { ctx = context.Background() } - imp, err := NewBlocksImporter(scheme, st, blockchainPath) + imp, err := selectImporter(params, state) if err != nil { - return err + return errors.Wrap(err, "failed to create importer") } defer func() { if clErr := imp.Close(); clErr != nil { zap.S().Fatalf("Failed to close importer: %v", clErr) } }() - err = imp.SkipToHeight(ctx, startHeight) - if err != nil { - return err + if err = imp.SkipToHeight(ctx, startHeight); err != nil { + return errors.Wrap(err, "failed to skip to state height") } return imp.Import(ctx, nBlocks) } +func selectImporter(params ImportParams, state State) (Importer, error) { + if params.LightNodeMode { + imp, err := NewSnapshotsImporter(params.Schema, state, params.BlockchainPath, params.SnapshotsPath) + if err != nil { + return nil, errors.Wrap(err, "failed to create snapshots importer") + } + return imp, nil + } + imp, err := NewBlocksImporter(params.Schema, state, params.BlockchainPath) + if err != nil { + return nil, errors.Wrap(err, "failed to create blocks importer") + } + return imp, nil +} + func CheckBalances(st State, balancesPath string) error { balances, err := os.Open(filepath.Clean(balancesPath)) if err != nil { diff --git a/pkg/importer/snapshots_importer.go b/pkg/importer/snapshots_importer.go index 42ae1e5cb..527cd6448 100644 --- a/pkg/importer/snapshots_importer.go +++ b/pkg/importer/snapshots_importer.go @@ -2,7 +2,6 @@ package importer import ( "context" - "errors" "fmt" "time" @@ -69,7 +68,7 @@ func (imp *SnapshotsImporter) Import(ctx context.Context, number uint64) error { } // reading snapshots snapshot, err := imp.sr.readSnapshot() - if err != nil && !errors.Is(err, errNoop) { + if err != nil { return err } snapshots[index] = snapshot diff --git a/pkg/node/blocks_applier/blocks_applier.go b/pkg/node/blocks_applier/blocks_applier.go index 7d8af569a..38d4853f4 100644 --- a/pkg/node/blocks_applier/blocks_applier.go +++ b/pkg/node/blocks_applier/blocks_applier.go @@ -1,6 +1,7 @@ package blocks_applier import ( + stderrors "errors" "math/big" "github.com/pkg/errors" @@ -83,7 +84,9 @@ func (a *innerBlocksApplier) apply( if err2 != nil { return 0, errors.Wrap(err2, "failed rollback deserialized blocks") } - return 0, errors.Wrapf(err, "failed add deserialized blocks, first block id %s", blocks[0].BlockID().String()) + + return 0, errors.Wrapf(stderrors.Join(err, err2), + "failed add deserialized blocks, first block id %s", blocks[0].BlockID().String()) } return parentHeight + proto.Height(len(blocks)), nil } @@ -183,7 +186,8 @@ func (a *innerBlocksApplier) applyWithSnapshots( if errDeserialized != nil { return 0, errors.Wrap(errDeserialized, "failed rollback deserialized blocks") } - return 0, errors.Wrapf(err, "failed add deserialized blocks, first block id %s", blocks[0].BlockID().String()) + return 0, errors.Wrapf(stderrors.Join(err, errDeserialized), + "failed add deserialized blocks, first block id %s", blocks[0].BlockID().String()) } return parentHeight + proto.Height(len(blocks)), nil } @@ -270,7 +274,8 @@ func (a *innerBlocksApplier) applyMicro( if errAdd != nil { return 0, errors.Wrap(errAdd, "failed rollback block") } - return 0, errors.Wrapf(err, "failed apply new block '%s'", block.BlockID().String()) + return 0, errors.Wrapf(stderrors.Join(err, errAdd), + "failed apply new block '%s'", block.BlockID().String()) } return currentHeight, nil } @@ -327,7 +332,8 @@ func (a *innerBlocksApplier) applyMicroWithSnapshot( if errAdd != nil { return 0, errors.Wrap(errAdd, "failed rollback block") } - return 0, errors.Wrapf(err, "failed apply new block '%s'", block.BlockID().String()) + return 0, errors.Wrapf(stderrors.Join(err, errAdd), + "failed apply new block '%s'", block.BlockID().String()) } return currentHeight, nil } diff --git a/pkg/node/fsm/fsm_common.go b/pkg/node/fsm/fsm_common.go index a372d87ba..044a49dd3 100644 --- a/pkg/node/fsm/fsm_common.go +++ b/pkg/node/fsm/fsm_common.go @@ -256,7 +256,7 @@ func processScoreAfterApplyingOrReturnToNG( if s.Score.Cmp(nodeScore) == 1 { // received score is larger than local score newS, task, errS := syncWithNewPeer(state, baseInfo, s.Peer) - if newS.String() != SyncStateName { + if newS == nil || newS.String() != SyncStateName { zap.S().Errorf("%v", state.Errorf(errS)) continue } diff --git a/pkg/node/fsm/ng_state.go b/pkg/node/fsm/ng_state.go index 319def2a8..610866af2 100644 --- a/pkg/node/fsm/ng_state.go +++ b/pkg/node/fsm/ng_state.go @@ -114,23 +114,31 @@ func (a *NGState) rollbackToStateFromCache(blockFromCache *proto.Block) error { func (a *NGState) rollbackToStateFromCacheInLightNode(parentID proto.BlockID) error { blockFromCache, okB := a.blocksCache.Get(parentID) snapshotFromCache, okS := a.blocksCache.GetSnapshot(parentID) - if okB && okS { - zap.S().Named(logging.FSMNamespace).Debugf("[%s] Re-applying block '%s' from cache", - a, blockFromCache.ID.String()) - previousBlockID := blockFromCache.Parent - err := a.baseInfo.storage.RollbackTo(previousBlockID) - if err != nil { - return errors.Wrapf(err, "failed to rollback to parent block '%s' of cached block '%s'", - previousBlockID.String(), blockFromCache.ID.String()) - } - _, err = a.baseInfo.blocksApplier.ApplyWithSnapshots( - a.baseInfo.storage, - []*proto.Block{blockFromCache}, - []*proto.BlockSnapshot{snapshotFromCache}, - ) - if err != nil { - return errors.Wrapf(err, "failed to apply cached block %q", blockFromCache.ID.String()) + if !okB && !okS { + // no blocks in cache + return nil + } + if !okS || !okB { + if !okS { + return a.Errorf(errors.Errorf("snapshot for block %s doesn't exist in cache", parentID.String())) } + return a.Errorf(errors.Errorf("block %s doesn't existin cache", parentID.String())) + } + zap.S().Named(logging.FSMNamespace).Debugf("[%s] Re-applying block '%s' from cache", + a, blockFromCache.ID.String()) + previousBlockID := blockFromCache.Parent + err := a.baseInfo.storage.RollbackTo(previousBlockID) + if err != nil { + return errors.Wrapf(err, "failed to rollback to parent block '%s' of cached block '%s'", + previousBlockID.String(), blockFromCache.ID.String()) + } + _, err = a.baseInfo.blocksApplier.ApplyWithSnapshots( + a.baseInfo.storage, + []*proto.Block{blockFromCache}, + []*proto.BlockSnapshot{snapshotFromCache}, + ) + if err != nil { + return errors.Wrapf(err, "failed to apply cached block %q", blockFromCache.ID.String()) } return nil } @@ -157,8 +165,7 @@ func (a *NGState) Block(peer peer.Peer, block *proto.Block) (State, Async, error return a, nil, a.Errorf(err) } } else { - var blockFromCache *proto.Block - if blockFromCache, ok = a.blocksCache.Get(block.Parent); ok { + if blockFromCache, okGet := a.blocksCache.Get(block.Parent); okGet { zap.S().Named(logging.FSMNamespace).Debugf("[%s] Re-applying block '%s' from cache", a, blockFromCache.ID.String()) if err = a.rollbackToStateFromCache(blockFromCache); err != nil { @@ -367,7 +374,6 @@ func (a *NGState) checkAndAppendMicroBlock( func (a *NGState) MicroBlockInv(p peer.Peer, inv *proto.MicroBlockInv) (State, Async, error) { metrics.MicroBlockInv(inv, p.Handshake().NodeName) - // TODO: add logs about microblock request existed := a.baseInfo.invRequester.Request(p, inv.TotalBlockID.Bytes()) if existed { zap.S().Named(logging.FSMNamespace).Debugf("[%s] Microblock inv received: block '%s' already in cache", diff --git a/pkg/node/fsm/wait_micro_snapshot.go b/pkg/node/fsm/wait_micro_snapshot.go index dc0898d41..5b38b9ccb 100644 --- a/pkg/node/fsm/wait_micro_snapshot.go +++ b/pkg/node/fsm/wait_micro_snapshot.go @@ -17,7 +17,8 @@ import ( ) const ( - microSnapshotTimeout = 15 + microSnapshotTimeout = 15 * time.Second + scoresSliceMaxSize = 10000 ) type WaitMicroSnapshotState struct { @@ -38,8 +39,7 @@ func newWaitMicroSnapshotState(baseInfo BaseInfo, micro *proto.MicroBlock, cache timeoutTaskOutdated: timeoutTaskOutdated, microBlockWaitingForSnapshot: micro, } - task := tasks.NewMicroBlockSnapshotTimeoutTask(time.Second*microSnapshotTimeout, - micro.TotalBlockID, timeoutTaskOutdated) + task := tasks.NewMicroBlockSnapshotTimeoutTask(microSnapshotTimeout, micro.TotalBlockID, timeoutTaskOutdated) return st, task } @@ -56,7 +56,7 @@ func (a *WaitMicroSnapshotState) Task(task tasks.AsyncTask) (State, Async, error case tasks.Ping: return a, nil, nil case tasks.AskPeers: - zap.S().Named(logging.FSMNamespace).Debug("[WaitMicroSnapshot] Requesting peers") + zap.S().Named(logging.FSMNamespace).Debugf("[%s] Requesting peers", a) a.baseInfo.peers.AskPeers() return a, nil, nil case tasks.MineMicro: @@ -72,8 +72,8 @@ func (a *WaitMicroSnapshotState) Task(task tasks.AsyncTask) (State, Async, error return a, nil, nil case tasks.MicroBlockSnapshot: defer a.cleanupBeforeTransition() - zap.S().Errorf("%v", a.Errorf(errors.Errorf( - "failed to get snapshot for microBlock '%s' - timeout", t.BlockID))) + zap.S().Named(logging.FSMNamespace).Errorf("%v", a.Errorf(errors.Errorf( + "Failed to get snapshot for microBlock '%s' - timeout", t.BlockID))) return processScoreAfterApplyingOrReturnToNG(a, a.baseInfo, a.receivedScores, a.blocksCache) default: return a, nil, a.Errorf(errors.New("undefined Snapshot Task type")) @@ -87,7 +87,9 @@ func (a *WaitMicroSnapshotState) Task(task tasks.AsyncTask) (State, Async, error func (a *WaitMicroSnapshotState) Score(p peer.Peer, score *proto.Score) (State, Async, error) { metrics.FSMScore("ng", score, p.Handshake().NodeName) - a.receivedScores = append(a.receivedScores, ReceivedScore{Peer: p, Score: score}) + if len(a.receivedScores) < scoresSliceMaxSize { + a.receivedScores = append(a.receivedScores, ReceivedScore{Peer: p, Score: score}) + } return a, nil, nil } @@ -120,7 +122,7 @@ func (a *WaitMicroSnapshotState) MicroBlockSnapshot( if inv, ok := a.baseInfo.MicroBlockInvCache.Get(block.BlockID()); ok { //TODO: We have to exclude from recipients peers that already have this microblock if err = broadcastMicroBlockInv(a.baseInfo, inv); err != nil { - zap.S().Errorf("%v", a.Errorf(errors.Wrap(err, "failed to handle micro block message"))) + zap.S().Errorf("%v", a.Errorf(errors.Wrap(err, "Failed to handle micro block message"))) return processScoreAfterApplyingOrReturnToNG(a, a.baseInfo, a.receivedScores, a.blocksCache) } } diff --git a/pkg/node/fsm/wait_snapshot_state.go b/pkg/node/fsm/wait_snapshot_state.go index 2454227ec..66b9568df 100644 --- a/pkg/node/fsm/wait_snapshot_state.go +++ b/pkg/node/fsm/wait_snapshot_state.go @@ -16,7 +16,7 @@ import ( ) const ( - snapshotTimeout = 30 + snapshotTimeout = 30 * time.Second ) type WaitSnapshotState struct { @@ -43,7 +43,7 @@ func newWaitSnapshotState(baseInfo BaseInfo, block *proto.Block, cache blockStat blockWaitingForSnapshot: block, receivedScores: nil, } - task := tasks.NewBlockSnapshotTimeoutTask(time.Second*snapshotTimeout, block.BlockID(), timeoutTaskOutdated) + task := tasks.NewBlockSnapshotTimeoutTask(snapshotTimeout, block.BlockID(), timeoutTaskOutdated) return st, task } @@ -60,7 +60,7 @@ func (a *WaitSnapshotState) Task(task tasks.AsyncTask) (State, Async, error) { case tasks.Ping: return a, nil, nil case tasks.AskPeers: - zap.S().Named(logging.FSMNamespace).Debug("[WaitSnapshot] Requesting peers") + zap.S().Named(logging.FSMNamespace).Debugf("[%s] Requesting peers", a) a.baseInfo.peers.AskPeers() return a, nil, nil case tasks.MineMicro: @@ -75,7 +75,7 @@ func (a *WaitSnapshotState) Task(task tasks.AsyncTask) (State, Async, error) { case tasks.BlockSnapshot: defer a.cleanupBeforeTransition() zap.S().Errorf("%v", a.Errorf(errors.Errorf( - "failed to get snapshot for block '%s' - timeout", t.BlockID))) + "Failed to get snapshot for block '%s' - timeout", t.BlockID))) return processScoreAfterApplyingOrReturnToNG(a, a.baseInfo, a.receivedScores, a.blocksCache) case tasks.MicroBlockSnapshot: return a, nil, nil @@ -91,7 +91,9 @@ func (a *WaitSnapshotState) Task(task tasks.AsyncTask) (State, Async, error) { func (a *WaitSnapshotState) Score(p peer.Peer, score *proto.Score) (State, Async, error) { metrics.FSMScore("ng", score, p.Handshake().NodeName) - a.receivedScores = append(a.receivedScores, ReceivedScore{Peer: p, Score: score}) + if len(a.receivedScores) < scoresSliceMaxSize { + a.receivedScores = append(a.receivedScores, ReceivedScore{Peer: p, Score: score}) + } return a, nil, nil } @@ -112,7 +114,7 @@ func (a *WaitSnapshotState) BlockSnapshot( []*proto.BlockSnapshot{&snapshot}, ) if err != nil { - zap.S().Errorf("%v", a.Errorf(errors.Wrapf(err, "failed to apply block %s", a.blockWaitingForSnapshot.BlockID()))) + zap.S().Errorf("%v", a.Errorf(errors.Wrapf(err, "Failed to apply block %s", a.blockWaitingForSnapshot.BlockID()))) return processScoreAfterApplyingOrReturnToNG(a, a.baseInfo, a.receivedScores, a.blocksCache) } diff --git a/pkg/proto/proto.go b/pkg/proto/proto.go index 8566172c0..fbb1e49fb 100644 --- a/pkg/proto/proto.go +++ b/pkg/proto/proto.go @@ -57,8 +57,9 @@ const ( ContentIDMicroBlockSnapshot PeerMessageID = 37 ) -// ProtocolVersion TODO: change to 1.5.0 -var ProtocolVersion = NewVersion(1, 4, 0) +func ProtocolVersion() Version { + return NewVersion(1, 5, 0) //nolint:gomnd // it's version number +} type Message interface { io.ReaderFrom diff --git a/pkg/state/api.go b/pkg/state/api.go index 8d3c7c685..4c1ac38cc 100644 --- a/pkg/state/api.go +++ b/pkg/state/api.go @@ -264,8 +264,6 @@ type StateParams struct { ProvideExtendedApi bool // BuildStateHashes enables building and storing state hashes by height. BuildStateHashes bool - - LightNodeMode bool } func DefaultStateParams() StateParams { diff --git a/pkg/state/state_test.go b/pkg/state/state_test.go index afc4ad067..946151efa 100644 --- a/pkg/state/state_test.go +++ b/pkg/state/state_test.go @@ -126,7 +126,11 @@ func TestValidationWithoutBlocks(t *testing.T) { assert.NoError(t, err, "readBlocksFromTestPath() failed") last := blocks[len(blocks)-1] txs := last.Transactions - err = importer.ApplyFromFile(context.Background(), proto.MainNetScheme, manager, blocksPath, height, 1) + err = importer.ApplyFromFile( + context.Background(), + importer.ImportParams{Schema: proto.MainNetScheme, BlockchainPath: blocksPath, LightNodeMode: false}, + manager, + height, 1) assert.NoError(t, err, "ApplyFromFile() failed") err = validateTxs(manager, last.Timestamp, txs) assert.NoError(t, err, "validateTxs() failed") @@ -190,7 +194,11 @@ func TestStateRollback(t *testing.T) { } if tc.nextHeight > height { if aErr := importer.ApplyFromFile( - context.Background(), proto.MainNetScheme, manager, blocksPath, tc.nextHeight-1, height); aErr != nil { + context.Background(), + importer.ImportParams{Schema: proto.MainNetScheme, BlockchainPath: blocksPath, LightNodeMode: false}, + manager, + tc.nextHeight-1, height, + ); aErr != nil { t.Fatalf("Failed to import: %v\n", aErr) } } else { @@ -226,15 +234,17 @@ func TestStateIntegrated(t *testing.T) { // Test what happens in case of failure: we add blocks starting from wrong height. // State should be rolled back to previous state and ready to use after. wrongStartHeight := uint64(100) - ctx := context.Background() - - if aErr := importer.ApplyFromFile(ctx, proto.MainNetScheme, manager, blocksPath, blocksToImport, - wrongStartHeight); aErr == nil { + if aErr := importer.ApplyFromFile( + context.Background(), + importer.ImportParams{Schema: proto.MainNetScheme, BlockchainPath: blocksPath, LightNodeMode: false}, + manager, blocksToImport, wrongStartHeight); aErr == nil { t.Errorf("Import starting from wrong height must fail but it doesn't.") } // Test normal import. - if aErr := importer.ApplyFromFile(ctx, proto.MainNetScheme, manager, blocksPath, blocksToImport, - 1); aErr != nil { + if aErr := importer.ApplyFromFile( + context.Background(), + importer.ImportParams{Schema: proto.MainNetScheme, BlockchainPath: blocksPath, LightNodeMode: false}, + manager, blocksToImport, 1); aErr != nil { t.Fatalf("Failed to import: %v\n", aErr) } if cErr := importer.CheckBalances(manager, balancesPath); cErr != nil { @@ -304,7 +314,10 @@ func TestPreactivatedFeatures(t *testing.T) { assert.Equal(t, true, approved) // Apply blocks. height := uint64(75) - err = importer.ApplyFromFile(context.Background(), proto.MainNetScheme, manager, blocksPath, height, 1) + err = importer.ApplyFromFile( + context.Background(), + importer.ImportParams{Schema: proto.MainNetScheme, BlockchainPath: blocksPath, LightNodeMode: false}, + manager, height, 1) assert.NoError(t, err, "ApplyFromFile() failed") // Check activation and approval heights. activationHeight, err := manager.ActivationHeight(featureID) @@ -322,7 +335,10 @@ func TestDisallowDuplicateTxIds(t *testing.T) { // Apply blocks. height := uint64(75) - err = importer.ApplyFromFile(context.Background(), proto.MainNetScheme, manager, blocksPath, height, 1) + err = importer.ApplyFromFile( + context.Background(), + importer.ImportParams{Schema: proto.MainNetScheme, BlockchainPath: blocksPath, LightNodeMode: false}, + manager, height, 1) assert.NoError(t, err, "ApplyFromFile() failed") // Now validate tx with ID which is already in the state. tx := existingGenesisTx(t) @@ -341,7 +357,10 @@ func TestTransactionByID(t *testing.T) { // Apply blocks. height := uint64(75) - err = importer.ApplyFromFile(context.Background(), proto.MainNetScheme, manager, blocksPath, height, 1) + err = importer.ApplyFromFile( + context.Background(), + importer.ImportParams{Schema: proto.MainNetScheme, BlockchainPath: blocksPath, LightNodeMode: false}, + manager, height, 1) assert.NoError(t, err, "ApplyFromFile() failed") // Retrieve existing MainNet genesis tx by its ID. @@ -370,7 +389,10 @@ func TestStateManager_TopBlock(t *testing.T) { assert.Equal(t, genesis, manager.TopBlock()) height := proto.Height(100) - err = importer.ApplyFromFile(context.Background(), proto.MainNetScheme, manager, blocksPath, height-1, 1) + err = importer.ApplyFromFile( + context.Background(), + importer.ImportParams{Schema: proto.MainNetScheme, BlockchainPath: blocksPath, LightNodeMode: false}, + manager, height-1, 1) assert.NoError(t, err, "ApplyFromFile() failed") correct, err := manager.BlockByHeight(height) @@ -416,7 +438,10 @@ func TestStateHashAtHeight(t *testing.T) { blocksPath, err := blocksPath() assert.NoError(t, err) - err = importer.ApplyFromFile(context.Background(), proto.MainNetScheme, manager, blocksPath, 9499, 1) + err = importer.ApplyFromFile( + context.Background(), + importer.ImportParams{Schema: proto.MainNetScheme, BlockchainPath: blocksPath, LightNodeMode: false}, + manager, 9499, 1) assert.NoError(t, err, "ApplyFromFile() failed") stateHash, err := manager.LegacyStateHashAtHeight(9500) assert.NoError(t, err, "LegacyStateHashAtHeight failed") From 3a1dadb73aaad3b40de2acf047e30282b674f6cc Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Fri, 19 Apr 2024 14:13:02 +0300 Subject: [PATCH 136/139] Remove 'nolint' for 'ProtocolVersion' func. --- pkg/proto/proto.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/proto/proto.go b/pkg/proto/proto.go index fbb1e49fb..8a917301f 100644 --- a/pkg/proto/proto.go +++ b/pkg/proto/proto.go @@ -58,7 +58,8 @@ const ( ) func ProtocolVersion() Version { - return NewVersion(1, 5, 0) //nolint:gomnd // it's version number + const major, minor, patch = 1, 5, 0 + return NewVersion(major, minor, patch) } type Message interface { From fb11dd3ecd9a45c522d605b86bce09e587ff1ba6 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Fri, 19 Apr 2024 14:15:09 +0300 Subject: [PATCH 137/139] Add more logs in 'ApplyFromFile' func. --- pkg/importer/importer.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/importer/importer.go b/pkg/importer/importer.go index 217800433..09361713e 100644 --- a/pkg/importer/importer.go +++ b/pkg/importer/importer.go @@ -80,9 +80,11 @@ func ApplyFromFile( zap.S().Fatalf("Failed to close importer: %v", clErr) } }() + zap.S().Infof("Skipping to height %d", startHeight) if err = imp.SkipToHeight(ctx, startHeight); err != nil { return errors.Wrap(err, "failed to skip to state height") } + zap.S().Infof("Start importing %d blocks", nBlocks) return imp.Import(ctx, nBlocks) } From 4b82cd2dff02c2b0e538a159a1bc569710ddec5e Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Fri, 19 Apr 2024 14:19:04 +0300 Subject: [PATCH 138/139] Add sanity checks for 'ImportParams'. --- pkg/importer/importer.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pkg/importer/importer.go b/pkg/importer/importer.go index 09361713e..e146a6e95 100644 --- a/pkg/importer/importer.go +++ b/pkg/importer/importer.go @@ -59,6 +59,19 @@ type ImportParams struct { LightNodeMode bool } +func (i ImportParams) validate() error { + if i.Schema == 0 { + return errors.New("scheme/chainID is empty") + } + if i.BlockchainPath == "" { + return errors.New("blockchain path is empty") + } + if i.LightNodeMode && i.SnapshotsPath == "" { + return errors.New("snapshots path is empty") + } + return nil +} + // ApplyFromFile reads blocks from blockchainPath, applying them from height startHeight and until nBlocks+1. // Setting optimize to true speeds up the import, but it is only safe when importing blockchain from scratch // when no rollbacks are possible at all. @@ -89,6 +102,9 @@ func ApplyFromFile( } func selectImporter(params ImportParams, state State) (Importer, error) { + if err := params.validate(); err != nil { // sanity check + return nil, errors.Wrap(err, "invalid import params") + } if params.LightNodeMode { imp, err := NewSnapshotsImporter(params.Schema, state, params.BlockchainPath, params.SnapshotsPath) if err != nil { From c20d60bdd949a09b673aef83a4276a603675151e Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Fri, 19 Apr 2024 14:50:54 +0300 Subject: [PATCH 139/139] Properly handle error in 'processScoreAfterApplyingOrReturnToNG'. --- pkg/node/fsm/fsm_common.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pkg/node/fsm/fsm_common.go b/pkg/node/fsm/fsm_common.go index 044a49dd3..29f9c793c 100644 --- a/pkg/node/fsm/fsm_common.go +++ b/pkg/node/fsm/fsm_common.go @@ -256,11 +256,16 @@ func processScoreAfterApplyingOrReturnToNG( if s.Score.Cmp(nodeScore) == 1 { // received score is larger than local score newS, task, errS := syncWithNewPeer(state, baseInfo, s.Peer) - if newS == nil || newS.String() != SyncStateName { + if errS != nil { zap.S().Errorf("%v", state.Errorf(errS)) continue } - return newS, task, errS + if newSName := newS.String(); newSName != SyncStateName { // sanity check + return newS, task, errors.Errorf("unexpected state %q after sync with peer, want %q", + newSName, SyncStateName, + ) + } + return newS, task, nil } } return newNGStateWithCache(baseInfo, cache), nil, nil