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 5 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,23 +3,39 @@ package proto
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) 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 @@ -42,7 +58,7 @@ func (bs *BlockSnapshot) UnmarshalBinary(data []byte, scheme Scheme) error {
}
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 @@ -64,16 +80,16 @@ func (bs *BlockSnapshot) UnmarshalBinary(data []byte, scheme Scheme) error {
txSnapshots = append(txSnapshots, atomicTS)
data = data[tsBytesLen:]
}
bs.TxSnapshots = txSnapshots
bs.TransactionsSnapshots = txSnapshots
return nil
}

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 @@ -91,18 +107,18 @@ func (bs *BlockSnapshot) UnmarshalJSON(bytes []byte) error {
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
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