Skip to content

Commit

Permalink
read only execute sc
Browse files Browse the repository at this point in the history
  • Loading branch information
Thykof committed Nov 17, 2023
1 parent b7dd00f commit 358669f
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 5 deletions.
11 changes: 11 additions & 0 deletions pkg/node/sendoperation/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
)

// ReadOnlyCallParams is the struct used to send a read only callSC to the node.
type ReadOnlyCallParams struct {
MaxGas int `json:"max_gas"`
Coins int `json:"coins"`
Expand Down Expand Up @@ -139,3 +140,13 @@ type BitVecHeadInfo struct {
type DeferredCreditsInfo struct {
Credits map[string]interface{} `json:"credits"` // Empty in provided JSON, assumed to be a map
}

// ReadOnlyExecuteParams is the struct used to send a read only executeSC to the node.
type ReadOnlyExecuteParams struct {
MaxGas int `json:"max_gas"`
Coins int `json:"coins"`
Fee int `json:"fee"`
Address string `json:"address"`
Bytecode JSONableSlice `json:"bytecode"`
OperationDatastore JSONableSlice `json:"operation_datastore"`
}
85 changes: 83 additions & 2 deletions pkg/node/sendoperation/readonlycall.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func EstimateGasCostCallSC(
return 0, fmt.Errorf("loading wallet '%s': %w", nickname, err)
}

result, err := ReadOnlyCallSC(targetAddr, function, parameter, coins, fee, acc.Address, client)
result, err := ReadOnlyCallSC(targetAddr, function, parameter, coins, DefaultGasLimit, fee, acc.Address, client)
if err != nil {
return 0, fmt.Errorf("calling ReadOnlyCall: %w", err)
}
Expand All @@ -42,14 +42,15 @@ func ReadOnlyCallSC(
function string,
parameter []byte,
coins uint64,
maxGas uint64,
fee uint64,
callerAddr string,
client *node.Client,
) (*ReadOnlyCallResult, error) {
readOnlyCallParams := [][]ReadOnlyCallParams{
{
ReadOnlyCallParams{
MaxGas: DefaultGasLimit,
MaxGas: int(maxGas),
Coins: int(coins),
Fee: int(fee),
TargetAddress: targetAddr,
Expand Down Expand Up @@ -91,3 +92,83 @@ func ReadOnlyCallSC(

return &resp[0], nil
}

func EstimateGasCostExecuteSC(
nickname string,
contract []byte,
datastore []byte,
maxCoins uint64,
fee uint64,
client *node.Client,
) (uint64, error) {
acc, err := wallet.Fetch(nickname)
if err != nil {
return 0, fmt.Errorf("loading wallet '%s': %w", nickname, err)
}

result, err := ReadOnlyExecuteSC(contract, datastore, maxCoins, DefaultGasLimit, fee, acc.Address, client)
if err != nil {
logger.Warnf("ReadOnlyExecuteSC error: %s, caller address is %s", err, acc.Address)

// Do not return an error because execute_read_only_bytecode v24.1 fail with Internal error
// and on v27 fails with Invalid params
return DefaultGasLimit, nil
}

estimatedGasCost := uint64(result.GasCost)

return estimatedGasCost, nil
}

func ReadOnlyExecuteSC(
contract []byte,
datastore []byte,
maxCoins uint64,
maxGas uint64,
fee uint64,
callerAddr string,
client *node.Client,
) (*ReadOnlyCallResult, error) {
readOnlyExecuteParams := [][]ReadOnlyExecuteParams{
{
ReadOnlyExecuteParams{
Coins: int(maxCoins),
MaxGas: int(maxGas),
Fee: int(fee),
Address: callerAddr,
Bytecode: contract,
OperationDatastore: datastore,
},
},
}

rawResponse, err := client.RPCClient.Call(
context.Background(),
"execute_read_only_bytecode",
readOnlyExecuteParams,
)
if err != nil {
return nil, fmt.Errorf("calling execute_read_only_bytecode jsonrpc with '%+v': %w", readOnlyExecuteParams, err)
}

if rawResponse.Error != nil {
return nil, fmt.Errorf(
"receiving execute_read_only_bytecode with '%+v': response: %w",
readOnlyExecuteParams,
rawResponse.Error,
)
}

var resp []ReadOnlyCallResult // rename if it's the same for call sc and execute sc: ReadOnlyResult

err = rawResponse.GetObject(&resp)
if err != nil {
return nil, fmt.Errorf("parsing execute_read_only_bytecode jsonrpc response '%+v': %w", rawResponse, err)
}

if resp[0].Result.Error != "" {
return nil, fmt.Errorf("ReadOnlyExecuteSC error: %s, caller address is %s", resp[0].Result.Error, callerAddr)
}

return &resp[0], nil
}
18 changes: 15 additions & 3 deletions pkg/onchain/sc.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func CallFunction(
if maxGas == sendOperation.DefaultGasLimit || maxGas == 0 {
estimatedGasCost, err := sendOperation.EstimateGasCostCallSC(nickname, addr, function, parameter, coins, fee, client)
if err != nil {
return nil, fmt.Errorf("calling EstimateGasCost for function '%s' at '%s': %w", function, addr, err)
return nil, fmt.Errorf("estimating Call SC gas cost for function '%s' at '%s': %w", function, addr, err)
}

logger.Debugf("Estimated gas cost for %s at %s: %d", function, addr, estimatedGasCost)
Expand Down Expand Up @@ -107,7 +107,7 @@ func CallFunctionSuccess(
// The smart contract is deployed with the given account nickname.
func DeploySC(client *node.Client,
nickname string,
gasLimit uint64,
maxGas uint64,
maxCoins uint64,
fee uint64,
expiry uint64,
Expand All @@ -116,9 +116,21 @@ func DeploySC(client *node.Client,
operationBatch sendOperation.OperationBatch,
signer signer.Signer,
) (*sendOperation.OperationResponse, []node.Event, error) {
// Calibrate max_gas
if maxGas == sendOperation.DefaultGasLimit || maxGas == 0 {
estimatedGasCost, err := sendOperation.EstimateGasCostExecuteSC(nickname, contract, datastore, maxCoins, fee, client)
if err != nil {
return nil, nil, fmt.Errorf("estimating Execute SC gas cost: %w", err)
}

logger.Debugf("Estimated gas cost for execute SC: %d", estimatedGasCost)

maxGas = estimatedGasCost
}

exeSC := executesc.New(
contract,
gasLimit,
maxGas,
maxCoins,
datastore)

Expand Down

0 comments on commit 358669f

Please sign in to comment.