Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added comparison methods #1356

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 29 additions & 13 deletions pkg/proto/block_snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,43 @@
import (
"encoding/binary"
"encoding/json"

"github.com/pkg/errors"

g "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves"
)

type BlockSnapshot struct {
TxSnapshots [][]AtomicSnapshot
TransactionsSnapshots []TxSnapshot
}

func (bs *BlockSnapshot) AppendTxSnapshot(txSnapshot []AtomicSnapshot) {
bs.TxSnapshots = append(bs.TxSnapshots, txSnapshot)
bs.TransactionsSnapshots = append(bs.TransactionsSnapshots, txSnapshot)
}

// Equal function assumes that TransactionsSnapshots are in same order in both original and other instances.
func (bs BlockSnapshot) Equal(other BlockSnapshot) (bool, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's necessary to say that this function can mutate the passed argument

if len(bs.TransactionsSnapshots) != len(other.TransactionsSnapshots) {
return false, nil
}
for i, txSnapshot := range bs.TransactionsSnapshots {
equal, err := txSnapshot.Equal(other.TransactionsSnapshots[i])
if err != nil {
return false, err
}
if !equal {
return false, nil
}
}
return true, nil
}

func (bs *BlockSnapshot) AppendTxSnapshots(txSnapshots [][]AtomicSnapshot) {
bs.TxSnapshots = append(bs.TxSnapshots, txSnapshots...)

Check failure on line 37 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / Vulnerability scanner

bs.TxSnapshots undefined (type *BlockSnapshot has no field or method TxSnapshots)

Check failure on line 37 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / Vulnerability scanner

bs.TxSnapshots undefined (type *BlockSnapshot has no field or method TxSnapshots)

Check failure on line 37 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / ubuntu

bs.TxSnapshots undefined (type *BlockSnapshot has no field or method TxSnapshots)

Check failure on line 37 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / ubuntu

bs.TxSnapshots undefined (type *BlockSnapshot has no field or method TxSnapshots)

Check failure on line 37 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / Analyze (go)

bs.TxSnapshots undefined (type *BlockSnapshot has no field or method TxSnapshots)

Check failure on line 37 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / Analyze (go)

bs.TxSnapshots undefined (type *BlockSnapshot has no field or method TxSnapshots)

Check failure on line 37 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / smoke_tests

bs.TxSnapshots undefined (type *BlockSnapshot has no field or method TxSnapshots)
}

func (bs BlockSnapshot) MarshallBinary() ([]byte, error) {
result := binary.BigEndian.AppendUint32([]byte{}, uint32(len(bs.TxSnapshots)))
for _, ts := range bs.TxSnapshots {
result := binary.BigEndian.AppendUint32([]byte{}, uint32(len(bs.TransactionsSnapshots)))
for _, ts := range bs.TransactionsSnapshots {
var res g.TransactionStateSnapshot
for _, atomicSnapshot := range ts {
if err := atomicSnapshot.AppendToProtobuf(&res); err != nil {
Expand All @@ -46,7 +62,7 @@
}
txSnCnt := binary.BigEndian.Uint32(data[0:uint32Size])
data = data[uint32Size:]
var txSnapshots [][]AtomicSnapshot
var txSnapshots []TxSnapshot
for i := uint32(0); i < txSnCnt; i++ {
if len(data) < uint32Size {
return errors.Errorf("BlockSnapshot UnmarshallBinary: invalid data size")
Expand All @@ -68,14 +84,14 @@
txSnapshots = append(txSnapshots, atomicTS)
data = data[tsBytesLen:]
}
bs.TxSnapshots = txSnapshots
bs.TransactionsSnapshots = txSnapshots
return nil
}

func (bs BlockSnapshot) ToProtobuf() ([]*g.TransactionStateSnapshot, error) {
data := make([]g.TransactionStateSnapshot, len(bs.TxSnapshots))

Check failure on line 92 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / Vulnerability scanner

bs.TxSnapshots undefined (type BlockSnapshot has no field or method TxSnapshots)

Check failure on line 92 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / ubuntu

bs.TxSnapshots undefined (type BlockSnapshot has no field or method TxSnapshots)

Check failure on line 92 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / ubuntu

bs.TxSnapshots undefined (type BlockSnapshot has no field or method TxSnapshots)

Check failure on line 92 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / Analyze (go)

bs.TxSnapshots undefined (type BlockSnapshot has no field or method TxSnapshots)

Check failure on line 92 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / Analyze (go)

bs.TxSnapshots undefined (type BlockSnapshot has no field or method TxSnapshots)

Check failure on line 92 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / smoke_tests

bs.TxSnapshots undefined (type BlockSnapshot has no field or method TxSnapshots)
res := make([]*g.TransactionStateSnapshot, len(bs.TxSnapshots))

Check failure on line 93 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / Vulnerability scanner

bs.TxSnapshots undefined (type BlockSnapshot has no field or method TxSnapshots)

Check failure on line 93 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / ubuntu

bs.TxSnapshots undefined (type BlockSnapshot has no field or method TxSnapshots)

Check failure on line 93 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / ubuntu

bs.TxSnapshots undefined (type BlockSnapshot has no field or method TxSnapshots)

Check failure on line 93 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / Analyze (go)

bs.TxSnapshots undefined (type BlockSnapshot has no field or method TxSnapshots)

Check failure on line 93 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / Analyze (go)

bs.TxSnapshots undefined (type BlockSnapshot has no field or method TxSnapshots)

Check failure on line 93 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / smoke_tests

bs.TxSnapshots undefined (type BlockSnapshot has no field or method TxSnapshots)
for i, ts := range bs.TxSnapshots {

Check failure on line 94 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / Vulnerability scanner

bs.TxSnapshots undefined (type BlockSnapshot has no field or method TxSnapshots)

Check failure on line 94 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / ubuntu

bs.TxSnapshots undefined (type BlockSnapshot has no field or method TxSnapshots)

Check failure on line 94 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / ubuntu

bs.TxSnapshots undefined (type BlockSnapshot has no field or method TxSnapshots)

Check failure on line 94 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / Analyze (go)

bs.TxSnapshots undefined (type BlockSnapshot has no field or method TxSnapshots)

Check failure on line 94 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / Analyze (go)

bs.TxSnapshots undefined (type BlockSnapshot has no field or method TxSnapshots)

Check failure on line 94 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / smoke_tests

bs.TxSnapshots undefined (type BlockSnapshot has no field or method TxSnapshots)
tsProto := &data[i]
for _, atomicSnapshot := range ts {
if err := atomicSnapshot.AppendToProtobuf(tsProto); err != nil {
Expand All @@ -88,11 +104,11 @@
}

func (bs BlockSnapshot) MarshalJSON() ([]byte, error) {
if len(bs.TxSnapshots) == 0 {
if len(bs.TransactionsSnapshots) == 0 {
return []byte("[]"), nil
}
res := make([]txSnapshotJSON, 0, len(bs.TxSnapshots))
for _, txSnapshot := range bs.TxSnapshots {
res := make([]txSnapshotJSON, 0, len(bs.TransactionsSnapshots))
for _, txSnapshot := range bs.TransactionsSnapshots {
var js txSnapshotJSON
for _, snapshot := range txSnapshot {
if err := snapshot.Apply(&js); err != nil {
Expand All @@ -110,18 +126,18 @@
return err
}
if len(blockSnapshotJSON) == 0 {
bs.TxSnapshots = nil
bs.TransactionsSnapshots = nil
return nil
}
res := make([][]AtomicSnapshot, 0, len(blockSnapshotJSON))
res := make([]TxSnapshot, 0, len(blockSnapshotJSON))
for _, js := range blockSnapshotJSON {
txSnapshot, err := js.toTransactionSnapshot()
if err != nil {
return err
}
res = append(res, txSnapshot)
}
bs.TxSnapshots = res
bs.TransactionsSnapshots = res
return nil
}

Expand Down Expand Up @@ -363,6 +379,6 @@
data = data[oneSnapshotSize:]
snapshotsBytesSize -= oneSnapshotSize + uint32Size
}
bs.TxSnapshots = txSnapshots

Check failure on line 382 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / Vulnerability scanner

bs.TxSnapshots undefined (type *BlockSnapshot has no field or method TxSnapshots)

Check failure on line 382 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / ubuntu

bs.TxSnapshots undefined (type *BlockSnapshot has no field or method TxSnapshots)

Check failure on line 382 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / Analyze (go)

bs.TxSnapshots undefined (type *BlockSnapshot has no field or method TxSnapshots)

Check failure on line 382 in pkg/proto/block_snapshot.go

View workflow job for this annotation

GitHub Actions / smoke_tests

bs.TxSnapshots undefined (type *BlockSnapshot has no field or method TxSnapshots)
return nil
}
183 changes: 175 additions & 8 deletions pkg/proto/block_snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ func Test_txSnapshotJSON_MarshalJSON_UnmarshalJSON(t *testing.T) {
}

// Test marshalling and unmarshalling txSnapshotJSON.
bs := proto.BlockSnapshot{TxSnapshots: [][]proto.AtomicSnapshot{
bs := proto.BlockSnapshot{TransactionsSnapshots: []proto.TxSnapshot{
succeededTxSnap,
failedTxSnap,
elidedTxSnap,
Expand All @@ -337,25 +337,192 @@ func Test_txSnapshotJSON_MarshalJSON_UnmarshalJSON(t *testing.T) {
var unmBs proto.BlockSnapshot
err = json.Unmarshal(data, &unmBs)
require.NoError(t, err)
assert.Len(t, unmBs.TxSnapshots, len(bs.TxSnapshots))
for i := range bs.TxSnapshots {
assert.ElementsMatch(t, bs.TxSnapshots[i], unmBs.TxSnapshots[i])
assert.Len(t, unmBs.TransactionsSnapshots, len(bs.TransactionsSnapshots))
for i := range bs.TransactionsSnapshots {
assert.ElementsMatch(t, bs.TransactionsSnapshots[i], unmBs.TransactionsSnapshots[i])
}

// Test empty BlockSnapshot.
data, err = json.Marshal(proto.BlockSnapshot{TxSnapshots: [][]proto.AtomicSnapshot{}})
data, err = json.Marshal(proto.BlockSnapshot{TransactionsSnapshots: []proto.TxSnapshot{}})
require.NoError(t, err)
assert.Equal(t, "[]", string(data))

// Test BlockSnapshot with nil txSnapshots.
data, err = json.Marshal(proto.BlockSnapshot{TxSnapshots: nil})
data, err = json.Marshal(proto.BlockSnapshot{TransactionsSnapshots: nil})
require.NoError(t, err)
assert.Equal(t, "[]", string(data))

// Test unmarshalling empty BlockSnapshot.
var unmEmptyBs proto.BlockSnapshot
err = json.Unmarshal(data, &unmEmptyBs)
require.NoError(t, err)
assert.Len(t, unmEmptyBs.TxSnapshots, 0)
assert.Nil(t, unmEmptyBs.TxSnapshots)
assert.Len(t, unmEmptyBs.TransactionsSnapshots, 0)
assert.Nil(t, unmEmptyBs.TransactionsSnapshots)
}

// TestBlockSnapshotEqual tests the comparison of two BlockSnapshot instances.
func TestBlockSnapshotEqual(t *testing.T) {
addr1, _ := proto.NewAddressFromString("3P9o3uwx3fWZz3b53g53ARUk9sFoPW6z7HA")
addr2, _ := proto.NewAddressFromString("3P9o3uwx3fWZz3b5aaaaaaaaaaFoPW6z7HB")
Comment on lines +365 to +366
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handle errors

assetID1 := crypto.MustDigestFromBase58("BrjV5AB5S7qN5tLQFbU5tpLj5qeozfVvPxEpDkmmhNP")
assetID2 := crypto.MustDigestFromBase58("5Zv8JLH8TTvq9iCo6HtB2K7CGpTJt6JTj5yvXaDVrxEJ")
publicKey1, _ := crypto.NewPublicKeyFromBase58("5TBjL2VdL1XmXq5dC4SYMeH5sVCGmMTeBNNYqWCuEXMn")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here

leaseID1 := crypto.MustDigestFromBase58("FjnZ7aY8iqVpZc4M4uPFuDzMB6YShYd4cNmRfQP1p4Su")

// Setup test cases
tests := []struct {
name string
blockSnapshotA proto.BlockSnapshot
blockSnapshotB proto.BlockSnapshot
wantEqual bool
}{
{
name: "equal snapshots with single transaction",
blockSnapshotA: proto.BlockSnapshot{
TransactionsSnapshots: []proto.TxSnapshot{
{&proto.WavesBalanceSnapshot{Address: addr1, Balance: 100}},
},
},
blockSnapshotB: proto.BlockSnapshot{
TransactionsSnapshots: []proto.TxSnapshot{
{&proto.WavesBalanceSnapshot{Address: addr1, Balance: 100}},
},
},
wantEqual: true,
},
{
name: "different snapshots with single transaction",
blockSnapshotA: proto.BlockSnapshot{
TransactionsSnapshots: []proto.TxSnapshot{
{&proto.WavesBalanceSnapshot{Address: addr1, Balance: 100}},
},
},
blockSnapshotB: proto.BlockSnapshot{
TransactionsSnapshots: []proto.TxSnapshot{
{&proto.WavesBalanceSnapshot{Address: addr2, Balance: 100}},
},
},
wantEqual: false,
},
{
name: "equal snapshots with multiple transactions",
blockSnapshotA: proto.BlockSnapshot{
TransactionsSnapshots: []proto.TxSnapshot{
{&proto.WavesBalanceSnapshot{Address: addr1, Balance: 100}},
{&proto.AssetBalanceSnapshot{Address: addr2, AssetID: assetID1, Balance: 200}},
},
},
blockSnapshotB: proto.BlockSnapshot{
TransactionsSnapshots: []proto.TxSnapshot{
{&proto.WavesBalanceSnapshot{Address: addr1, Balance: 100}},
{&proto.AssetBalanceSnapshot{Address: addr2, AssetID: assetID1, Balance: 200}},
},
},
wantEqual: true,
},
{
name: "snapshots with different asset balances",
blockSnapshotA: proto.BlockSnapshot{
TransactionsSnapshots: []proto.TxSnapshot{
{&proto.AssetBalanceSnapshot{Address: addr1, AssetID: assetID1, Balance: 300}},
},
},
blockSnapshotB: proto.BlockSnapshot{
TransactionsSnapshots: []proto.TxSnapshot{
{&proto.AssetBalanceSnapshot{Address: addr1, AssetID: assetID2, Balance: 300}},
},
},
wantEqual: false,
},
{
name: "snapshots with new lease and cancelled lease snapshots",
blockSnapshotA: proto.BlockSnapshot{
TransactionsSnapshots: []proto.TxSnapshot{
{&proto.NewLeaseSnapshot{LeaseID: leaseID1, Amount: 1000, SenderPK: publicKey1, RecipientAddr: addr1}},
{&proto.CancelledLeaseSnapshot{LeaseID: leaseID1}},
},
},
wantEqual: false,
},
{
name: "snapshots with equal AssetVolumeSnapshot",
blockSnapshotA: proto.BlockSnapshot{
TransactionsSnapshots: []proto.TxSnapshot{
{&proto.AssetVolumeSnapshot{AssetID: assetID1, TotalQuantity: *big.NewInt(1000), IsReissuable: true}},
},
},
blockSnapshotB: proto.BlockSnapshot{
TransactionsSnapshots: []proto.TxSnapshot{
{&proto.AssetVolumeSnapshot{AssetID: assetID1, TotalQuantity: *big.NewInt(1000), IsReissuable: true}},
},
},
wantEqual: true,
},
{
name: "snapshots with different AssetVolumeSnapshot reissuability",
blockSnapshotA: proto.BlockSnapshot{
TransactionsSnapshots: []proto.TxSnapshot{
{&proto.AssetVolumeSnapshot{AssetID: assetID1, TotalQuantity: *big.NewInt(1000), IsReissuable: true}},
},
},
blockSnapshotB: proto.BlockSnapshot{
TransactionsSnapshots: []proto.TxSnapshot{
{&proto.AssetVolumeSnapshot{AssetID: assetID1, TotalQuantity: *big.NewInt(1000), IsReissuable: false}},
},
},
wantEqual: false,
},
{
name: "snapshots with equal DataEntriesSnapshot",
blockSnapshotA: proto.BlockSnapshot{
TransactionsSnapshots: []proto.TxSnapshot{
{&proto.DataEntriesSnapshot{Address: addr1, DataEntries: proto.DataEntries{
&proto.IntegerDataEntry{Key: "key1", Value: 100},
&proto.BooleanDataEntry{Key: "key2", Value: true},
}}},
},
},
blockSnapshotB: proto.BlockSnapshot{
TransactionsSnapshots: []proto.TxSnapshot{
{&proto.DataEntriesSnapshot{Address: addr1, DataEntries: proto.DataEntries{
&proto.IntegerDataEntry{Key: "key1", Value: 100},
&proto.BooleanDataEntry{Key: "key2", Value: true},
}}},
},
},
wantEqual: true,
},
{
name: "snapshots with different DataEntriesSnapshot",
blockSnapshotA: proto.BlockSnapshot{
TransactionsSnapshots: []proto.TxSnapshot{
{&proto.DataEntriesSnapshot{Address: addr1, DataEntries: proto.DataEntries{
&proto.IntegerDataEntry{Key: "key1", Value: 100},
&proto.BooleanDataEntry{Key: "key2", Value: true},
}}},
},
},
blockSnapshotB: proto.BlockSnapshot{
TransactionsSnapshots: []proto.TxSnapshot{
{&proto.DataEntriesSnapshot{Address: addr1, DataEntries: proto.DataEntries{
&proto.IntegerDataEntry{Key: "key1", Value: 200}, // Different value
&proto.BooleanDataEntry{Key: "key2", Value: true},
}}},
},
},
wantEqual: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
equal, err := tt.blockSnapshotA.Equal(tt.blockSnapshotB)
if err != nil {
t.Errorf("Error comparing snapshots: %v", err)
}
if equal != tt.wantEqual {
t.Errorf("Expected snapshots to be equal: %v, got: %v", tt.wantEqual, equal)
}
Comment on lines +520 to +525
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use testify package.

})
}
}
Loading
Loading