Skip to content
Open
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
13 changes: 10 additions & 3 deletions pkg/ride/diff_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"iter"

"github.com/ccoveille/go-safecast/v2"
"github.com/pkg/errors"

"github.com/wavesplatform/gowaves/pkg/crypto"
Expand Down Expand Up @@ -32,6 +33,7 @@ type diffBalance struct {
balance int64
leaseIn int64
leaseOut int64
deposit int64
stateGenerating int64
challenged bool
}
Expand Down Expand Up @@ -68,7 +70,7 @@ func (db *diffBalance) spendableBalance() (int64, error) {
if err != nil {
return 0, err
}
return b, nil
return common.SubInt(b, db.deposit)
}

func (db *diffBalance) checkedRegularBalance() (uint64, error) {
Expand All @@ -79,7 +81,7 @@ func (db *diffBalance) checkedRegularBalance() (uint64, error) {
}

func (db *diffBalance) checkedSpendableBalance() (uint64, error) {
b, err := common.SubInt(db.balance, db.leaseOut)
b, err := db.spendableBalance()
if err != nil {
return 0, err
}
Expand All @@ -101,7 +103,7 @@ func (db *diffBalance) effectiveBalance() (int64, error) {
if err != nil {
return 0, err
}
return v2, nil
return common.SubInt(v2, db.deposit)
}

func (db *diffBalance) toFullWavesBalance(lightNodeActivated bool) (*proto.FullWavesBalance, error) {
Expand Down Expand Up @@ -257,10 +259,15 @@ func (ds *diffState) loadWavesBalance(id proto.AddressID) (diffBalance, error) {
if err != nil {
return diffBalance{}, errors.Wrap(err, "failed to get full Waves balance from state")
}
deposit, err := safecast.Convert[int64](profile.Deposit)
if err != nil {
return diffBalance{}, errors.Wrap(err, "failed to convert deposit to int64")
}
diff := diffBalance{
balance: int64(profile.Balance),
leaseIn: profile.LeaseIn,
leaseOut: profile.LeaseOut,
deposit: deposit,
stateGenerating: int64(profile.Generating),
challenged: profile.Challenged,
}
Expand Down
77 changes: 77 additions & 0 deletions pkg/ride/diff_state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"

"github.com/wavesplatform/gowaves/pkg/crypto"
Expand Down Expand Up @@ -198,3 +199,79 @@ func TestErrorOnDuplicateLeasing(t *testing.T) {
assert.EqualError(t, err3,
"lease with id '8N6F4oV2SmfWZ45xVNLQr2rjHyvDWNz8R3wxJzE83ZHm' already exists in ride execution diff")
}

func TestDiffBalanceToFullWavesBalanceTakesDepositIntoAccount(t *testing.T) {
tests := []struct {
name string
lightNodeActivated bool
expectedGenerating uint64
}{
{
name: "before Light Node activation",
lightNodeActivated: false,
expectedGenerating: 900,
},
{
name: "after Light Node activation",
lightNodeActivated: true,
expectedGenerating: 800,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
balance := diffBalance{
balance: 1_000,
leaseIn: 200,
leaseOut: 100,
deposit: 300,
stateGenerating: 900,
}

actual, err := balance.toFullWavesBalance(test.lightNodeActivated)
require.NoError(t, err)
require.Equal(t, &proto.FullWavesBalance{
Regular: 1_000,
Generating: test.expectedGenerating,
Available: 600,
Effective: 800,
LeaseIn: 200,
LeaseOut: 100,
}, actual)
})
}
}

func TestDiffStateLoadsDepositFromWavesBalanceProfile(t *testing.T) {
m := types.NewMockEnrichedSmartState(t)
m.EXPECT().WavesBalanceProfile(validAddress.ID()).Return(
&types.WavesBalanceProfile{
Balance: 1_000,
Deposit: 300,
}, nil,
).Once()
diff := newDiffState(m)

actual, err := diff.loadWavesBalance(validAddress.ID())
require.NoError(t, err)
require.Equal(t, int64(300), actual.deposit)
effective, err := actual.effectiveBalance()
require.NoError(t, err)
require.Equal(t, int64(700), effective)
}

func TestValidateChangedWavesBalancesTakesDepositIntoAccount(t *testing.T) {
balances := []changedWavesBalancesProfile{
{
addrID: validAddress.ID(),
diff: diffBalance{
balance: 100,
deposit: 101,
},
},
}

err := validateChangedWavesBalancesWithOldBalancesBeforeTx(
proto.TestNetScheme, balances, balances, nil,
)
require.ErrorContains(t, err, "negative scala-like effective balance -1")
}
21 changes: 15 additions & 6 deletions pkg/ride/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -1202,7 +1202,7 @@ func validateChangedWavesBalancesWithOldBalancesBeforeTx(
}
var (
wavesAfter = changedBalance.balance // regular balance
wavesWithoutDepositAfter = wavesAfter // TODO: need to take deposit into account
wavesWithoutDepositAfter = wavesAfter - changedBalance.deposit
)
var (
currentLeaseIn = changedBalance.leaseIn
Expand All @@ -1225,17 +1225,26 @@ func validateChangedWavesBalancesWithOldBalancesBeforeTx(
scalaLikeEffectiveBalance,
addr.String(),
leaseBalanceChangedAtTheLastLayer,
formStateChangesStringPartForErr(oldBalance.balance, oldBalance.leaseOut, oldBalance.leaseIn),
formStateChangesStringPartForErr(wavesAfter, currentLeaseOut, currentLeaseIn),
formStateChangesStringPartForErr(
oldBalance.balance, oldBalance.leaseOut, oldBalance.leaseIn, oldBalance.deposit,
),
formStateChangesStringPartForErr(
wavesAfter, currentLeaseOut, currentLeaseIn, changedBalance.deposit,
),
)
}
}
return nil
}

func formStateChangesStringPartForErr(wavesRegularBalance int64, leaseOut int64, leaseIn int64) string {
return fmt.Sprintf("(spendable=%d waves=%d leaseOut=%d leaseIn=%d)", // TODO: add deposit
wavesRegularBalance-leaseOut, wavesRegularBalance, leaseOut, leaseIn,
func formStateChangesStringPartForErr(wavesRegularBalance, leaseOut, leaseIn, deposit int64) string {
if deposit == 0 {
return fmt.Sprintf("(spendable=%d waves=%d leaseOut=%d leaseIn=%d)",
wavesRegularBalance-leaseOut, wavesRegularBalance, leaseOut, leaseIn,
)
}
return fmt.Sprintf("(spendable=%d waves=%d leaseOut=%d leaseIn=%d deposit=%d)",
wavesRegularBalance-leaseOut-deposit, wavesRegularBalance, leaseOut, leaseIn, deposit,
)
}

Expand Down
17 changes: 1 addition & 16 deletions pkg/ride/test_helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,22 +285,7 @@ func newTestEnv(t *testing.T) *testEnv {
return nil, err
}
if profile, ok := r.waves[addr]; ok {
eff := int64(profile.Balance) + profile.LeaseIn - profile.LeaseOut
if eff < 0 {
return nil, errors.New("negative effective balance")
}
spb := int64(profile.Balance) - profile.LeaseOut
if spb < 0 {
return nil, errors.New("negative spendable balance")
}
return &proto.FullWavesBalance{
Regular: profile.Balance,
Generating: profile.Generating,
Available: uint64(spb),
Effective: uint64(eff),
LeaseIn: uint64(profile.LeaseIn),
LeaseOut: uint64(profile.LeaseOut),
}, nil
return profile.ToFullWavesBalance()
}
return nil, errors.Errorf("no balance profile for address '%s'", addr.String())
}).Maybe()
Expand Down
3 changes: 1 addition & 2 deletions pkg/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -1211,7 +1211,6 @@ func (s *stateManager) FullWavesBalance(account proto.Recipient) (*proto.FullWav
Effective: effective,
LeaseIn: profile.LeaseInAsUint64(),
LeaseOut: profile.LeaseOutAsUint64(),
//TODO: Add Deposit to the profile.
}, nil
}

Expand Down Expand Up @@ -1271,9 +1270,9 @@ func (s *stateManager) WavesBalanceProfile(id proto.AddressID) (*types.WavesBala
Balance: profile.Balance,
LeaseIn: profile.LeaseIn,
LeaseOut: profile.LeaseOut,
Deposit: profile.Deposit,
Generating: generating,
Challenged: challenged,
//TODO: Add Deposit to the profile.
}, nil
}

Expand Down
34 changes: 34 additions & 0 deletions pkg/state/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,40 @@ func TestGeneratingBalanceValuesForNewestFunctions(t *testing.T) {
})
}

func TestFullWavesBalanceFunctionsTakeDepositIntoAccount(t *testing.T) {
state, testObj := createMockStateManager(t, settings.MustMainNetSettings())
_, pk, err := crypto.GenerateKeyPair([]byte("full-waves-balance-deposit"))
require.NoError(t, err)
addr, err := proto.NewAddressFromPublicKey(state.settings.AddressSchemeCharacter, pk)
require.NoError(t, err)

testObj.addBlock(t, blockID0)
testObj.setWavesBalance(t, addr, balanceProfile{
Balance: 1_000,
LeaseIn: 200,
LeaseOut: 100,
Deposit: 300,
}, blockID0)
testObj.flush(t)

recipient := proto.NewRecipientFromAddress(addr)
committed, err := state.FullWavesBalance(recipient)
require.NoError(t, err)
newest, err := state.NewestFullWavesBalance(recipient)
require.NoError(t, err)

for _, balance := range []*proto.FullWavesBalance{committed, newest} {
require.Equal(t, uint64(1_000), balance.Regular)
require.Equal(t, uint64(600), balance.Available)
require.Equal(t, uint64(800), balance.Effective)
require.Equal(t, uint64(200), balance.LeaseIn)
require.Equal(t, uint64(100), balance.LeaseOut)
}
profile, err := state.WavesBalanceProfile(addr.ID())
require.NoError(t, err)
require.Equal(t, uint64(300), profile.Deposit)
}

type stateForEnv interface {
StateInfo
types.EnrichedSmartState
Expand Down
13 changes: 11 additions & 2 deletions pkg/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ type WavesBalanceProfile struct {
Balance uint64
LeaseIn int64
LeaseOut int64
Deposit uint64
Generating uint64
Challenged bool // if Challenged true, the account considered as challenged at the current height.
}
Expand All @@ -81,14 +82,22 @@ func (bp *WavesBalanceProfile) EffectiveBalance() (uint64, error) {
if err != nil {
return 0, err
}
return common.SubInt(val, uint64(bp.LeaseOut))
val, err = common.SubInt(val, uint64(bp.LeaseOut))
if err != nil {
return 0, err
}
return common.SubInt(val, bp.Deposit)
}

func (bp *WavesBalanceProfile) SpendableBalance() (uint64, error) {
if bp.LeaseOut < 0 {
return 0, fmt.Errorf("negative lease out balance %d", bp.LeaseOut)
}
return common.SubInt(bp.Balance, uint64(bp.LeaseOut))
val, err := common.SubInt(bp.Balance, uint64(bp.LeaseOut))
if err != nil {
return 0, err
}
return common.SubInt(val, bp.Deposit)
}

func (bp *WavesBalanceProfile) ToFullWavesBalance() (*proto.FullWavesBalance, error) {
Expand Down
55 changes: 55 additions & 0 deletions pkg/types/types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package types_test

import (
"testing"

"github.com/stretchr/testify/require"

"github.com/wavesplatform/gowaves/pkg/proto"
"github.com/wavesplatform/gowaves/pkg/types"
)

func TestWavesBalanceProfileToFullWavesBalanceTakesDepositIntoAccount(t *testing.T) {
profile := &types.WavesBalanceProfile{
Balance: 1_000,
LeaseIn: 200,
LeaseOut: 100,
Deposit: 300,
Generating: 700,
}

actual, err := profile.ToFullWavesBalance()
require.NoError(t, err)
require.Equal(t, &proto.FullWavesBalance{
Regular: 1_000,
Generating: 700,
Available: 600,
Effective: 800,
LeaseIn: 200,
LeaseOut: 100,
}, actual)
}

func TestWavesBalanceProfileDepositCanMakeBalancesNegative(t *testing.T) {
profile := &types.WavesBalanceProfile{
Balance: 100,
Deposit: 101,
}

_, err := profile.SpendableBalance()
require.Error(t, err)
_, err = profile.EffectiveBalance()
require.Error(t, err)
}

func TestWavesBalanceProfileChallengedEffectiveBalance(t *testing.T) {
profile := &types.WavesBalanceProfile{
Balance: 1_000,
Deposit: 300,
Challenged: true,
}

effective, err := profile.EffectiveBalance()
require.NoError(t, err)
require.Zero(t, effective)
}
Loading