Skip to content

Commit

Permalink
Merge branch 'master' into fix_itests_transfer
Browse files Browse the repository at this point in the history
  • Loading branch information
nickeskov authored Oct 18, 2024
2 parents c00fb92 + 2b62d01 commit c6e443a
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 17 deletions.
12 changes: 8 additions & 4 deletions pkg/ride/diff_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func (db *diffBalance) effectiveBalance() (int64, error) {
return v2, nil
}

func (db *diffBalance) toFullWavesBalance() (*proto.FullWavesBalance, error) {
func (db *diffBalance) toFullWavesBalance(lightNodeActivated bool) (*proto.FullWavesBalance, error) {
eff, err := db.effectiveBalance()
if err != nil {
return nil, err
Expand All @@ -118,9 +118,13 @@ func (db *diffBalance) toFullWavesBalance() (*proto.FullWavesBalance, error) {
if spb < 0 {
return nil, errors.New("negative spendable balance")
}
gen := eff
if db.stateGenerating < gen {
gen = db.stateGenerating
// According to the scala node implementation:
// Before Light Node activation generating balance doesn't change during the script execution.
// Update generating balance if it's greater than effective balance, i.e. update generating balance during
// script processing.
gen := db.stateGenerating
if lightNodeActivated && eff < gen {
gen = eff
}
return &proto.FullWavesBalance{
Regular: uint64(db.balance),
Expand Down
10 changes: 6 additions & 4 deletions pkg/ride/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,22 @@ type WrappedState struct {
dataEntriesSize int
rootScriptLibVersion ast.LibraryVersion
rootActionsCountValidator proto.ActionsCountValidator
isLightNodeActivated bool
}

func newWrappedState(
env *EvaluationEnvironment,
env environment,
originalStateForWrappedState types.EnrichedSmartState,
rootScriptLibVersion ast.LibraryVersion,
) *WrappedState {
return &WrappedState{
diff: newDiffState(originalStateForWrappedState),
cle: env.th.(rideAddress),
scheme: env.sch,
cle: env.this().(rideAddress),
scheme: env.scheme(),
height: proto.Height(env.height()),
rootScriptLibVersion: rootScriptLibVersion,
rootActionsCountValidator: proto.NewScriptActionsCountValidator(),
isLightNodeActivated: env.lightNodeActivated(),
}
}

Expand Down Expand Up @@ -157,7 +159,7 @@ func (ws *WrappedState) NewestFullWavesBalance(account proto.Recipient) (*proto.
if err != nil {
return nil, err
}
return b.toFullWavesBalance()
return b.toFullWavesBalance(ws.isLightNodeActivated)
}

func (ws *WrappedState) IsStateUntouched(account proto.Recipient) (bool, error) {
Expand Down
14 changes: 5 additions & 9 deletions pkg/ride/test_helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -635,16 +635,12 @@ func (e *testEnv) withDataFromJSON(s string) *testEnv {

func (e *testEnv) withWrappedState() *testEnv {
v, err := e.me.libVersion()
if err != nil {
panic(err)
}
e.ws = &WrappedState{
diff: newDiffState(e.ms),
cle: e.me.this().(rideAddress),
scheme: e.me.scheme(),
rootScriptLibVersion: v,
rootActionsCountValidator: proto.NewScriptActionsCountValidator(),
require.NoError(e.t, err)
if e.me.heightFunc == nil { // create stub height function`
e.me.heightFunc = func() rideInt { return 0 }
defer func() { e.me.heightFunc = nil }()
}
e.ws = newWrappedState(e.me, e.ms, v)
e.me.stateFunc = func() types.SmartState {
return e.ws
}
Expand Down
78 changes: 78 additions & 0 deletions pkg/ride/tree_evaluation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6330,3 +6330,81 @@ func TestAttachedPaymentsValidation(t *testing.T) {
})
})
}

func TestUpdateGeneratingBalanceDuringScriptExecutionAfterLightNode(t *testing.T) {
sender := newTestAccount(t, "SENDER") // 3N8CkZAyS4XcDoJTJoKNuNk2xmNKmQj7myW
dApp1 := newTestAccount(t, "DAPP1") // 3MzDtgL5yw73C2xVLnLJCrT5gCL4357a4sz

const src = `
{-# STDLIB_VERSION 5 #-}
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ACCOUNT #-}

@Callable(i)
func call(to: String, value: Int) = {
let balanceBeforeTransfer = wavesBalance(this)
let balanceAfter = invoke(this, "transfer", [to, value], [])
let balanceAfterTransfer = wavesBalance(this)
let isUpdated = balanceAfter == balanceAfterTransfer.generating
if (!isUpdated && balanceBeforeTransfer.generating != balanceAfterTransfer.generating) then
throw("failure")
else
([], isUpdated)
}

@Callable(i)
func transfer(to: String, value: Int) = {
let balance = wavesBalance(this)
let toAddr = addressFromStringValue(to)
([ScriptTransfer(toAddr, value, unit)], balance.generating - value)
}`
tree, errs := ridec.CompileToTree(src)
require.Empty(t, errs)

const (
dAppInitialBalance = 10 * proto.PriceConstant
transferAmount = 5 * proto.PriceConstant
)

createEnv := func(t *testing.T, lightNodeActivated bool) *testEnv {
complexity, err := MaxChainInvokeComplexityByVersion(ast.LibV5)
require.NoError(t, err)
env := newTestEnv(t).withLibVersion(ast.LibV5).withComplexityLimit(int(complexity)).
withBlockV5Activated().withProtobufTx().
withDataEntriesSizeV2().withMessageLengthV3().withValidateInternalPayments().
withThis(dApp1).withDApp(dApp1).withSender(sender).
withInvocation("call", withTransactionID(crypto.Digest{})).withTree(dApp1, tree).
withWavesBalance(sender, 0).
withWavesBalance(dApp1, dAppInitialBalance, 0, 0, dAppInitialBalance)
if lightNodeActivated {
env = env.withLightNodeActivated()
}
return env.withWrappedState()
}
t.Run("before-light-node", func(t *testing.T) {
env := createEnv(t, false).toEnv()
fc := proto.NewFunctionCall("call", proto.Arguments{
proto.NewStringArgument(sender.address().String()),
proto.NewIntegerArgument(transferAmount),
})
res, err := CallFunction(env, tree, fc)
require.NoError(t, err)
require.Len(t, res.ScriptActions(), 1)
isBalanceUpdated, ok := res.userResult().(rideBoolean)
require.True(t, ok)
assert.False(t, bool(isBalanceUpdated))
})
t.Run("after-light-node", func(t *testing.T) {
env := createEnv(t, true).toEnv()
fc := proto.NewFunctionCall("call", proto.Arguments{
proto.NewStringArgument(sender.address().String()),
proto.NewIntegerArgument(transferAmount),
})
res, err := CallFunction(env, tree, fc)
require.NoError(t, err)
require.Len(t, res.ScriptActions(), 1)
isBalanceUpdated, ok := res.userResult().(rideBoolean)
require.True(t, ok)
assert.True(t, bool(isBalanceUpdated))
})
}

0 comments on commit c6e443a

Please sign in to comment.