Skip to content

Commit

Permalink
Allow budget instruction leeway to be configured by clients
Browse files Browse the repository at this point in the history
  • Loading branch information
stellarsaur committed Dec 14, 2023
1 parent c1fef8f commit 9e216ae
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 6 deletions.
7 changes: 4 additions & 3 deletions cmd/soroban-rpc/internal/methods/simulate_transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import (
)

type SimulateTransactionRequest struct {
Transaction string `json:"transaction"`
Transaction string `json:"transaction"`
ResourceConfig *preflight.ResourceConfig `json:"resourceConfig,omitempty"`
}

type SimulateTransactionCost struct {
Expand Down Expand Up @@ -46,7 +47,7 @@ type SimulateTransactionResponse struct {
}

type PreflightGetter interface {
GetPreflight(ctx context.Context, readTx db.LedgerEntryReadTx, bucketListSize uint64, sourceAccount xdr.AccountId, opBody xdr.OperationBody, footprint xdr.LedgerFootprint) (preflight.Preflight, error)
GetPreflight(ctx context.Context, readTx db.LedgerEntryReadTx, bucketListSize uint64, sourceAccount xdr.AccountId, opBody xdr.OperationBody, footprint xdr.LedgerFootprint, resourceConfig *preflight.ResourceConfig) (preflight.Preflight, error)
}

// NewSimulateTransactionHandler returns a json rpc handler to run preflight simulations
Expand Down Expand Up @@ -113,7 +114,7 @@ func NewSimulateTransactionHandler(logger *log.Entry, ledgerEntryReader db.Ledge
}
}

result, err := getter.GetPreflight(ctx, readTx, bucketListSize, sourceAccount, op.Body, footprint)
result, err := getter.GetPreflight(ctx, readTx, bucketListSize, sourceAccount, op.Body, footprint, request.ResourceConfig)
if err != nil {
return SimulateTransactionResponse{
Error: err.Error(),
Expand Down
3 changes: 2 additions & 1 deletion cmd/soroban-rpc/internal/preflight/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ func (m *metricsLedgerEntryWrapper) GetLedgerEntries(keys ...xdr.LedgerKey) ([]d
return entries, err
}

func (pwp *PreflightWorkerPool) GetPreflight(ctx context.Context, readTx db.LedgerEntryReadTx, bucketListSize uint64, sourceAccount xdr.AccountId, opBody xdr.OperationBody, footprint xdr.LedgerFootprint) (Preflight, error) {
func (pwp *PreflightWorkerPool) GetPreflight(ctx context.Context, readTx db.LedgerEntryReadTx, bucketListSize uint64, sourceAccount xdr.AccountId, opBody xdr.OperationBody, footprint xdr.LedgerFootprint, resourceConfig *ResourceConfig) (Preflight, error) {
if pwp.isClosed.Load() {
return Preflight{}, errors.New("preflight worker pool is closed")
}
Expand All @@ -154,6 +154,7 @@ func (pwp *PreflightWorkerPool) GetPreflight(ctx context.Context, readTx db.Ledg
LedgerEntryReadTx: &wrappedTx,
BucketListSize: bucketListSize,
Footprint: footprint,
ResourceConfig: resourceConfig,
EnableDebug: pwp.enableDebug,
}
resultC := make(chan workerResult)
Expand Down
17 changes: 17 additions & 0 deletions cmd/soroban-rpc/internal/preflight/preflight.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ type snapshotSourceHandle struct {
logger *log.Entry
}

const (
defaultInstructionLeeway uint64 = 1000000
)

// SnapshotSourceGet takes a LedgerKey XDR in base64 string and returns its matching LedgerEntry XDR in base64 string
// It's used by the Rust preflight code to obtain ledger entries.
//
Expand Down Expand Up @@ -71,6 +75,10 @@ func FreeGoXDR(xdr C.xdr_t) {
C.free(unsafe.Pointer(xdr.xdr))
}

type ResourceConfig struct {
InstructionLeeway uint64 `json:"instructionLeeway"`
}

type PreflightParameters struct {
Logger *log.Entry
SourceAccount xdr.AccountId
Expand All @@ -79,6 +87,7 @@ type PreflightParameters struct {
NetworkPassphrase string
LedgerEntryReadTx db.LedgerEntryReadTx
BucketListSize uint64
ResourceConfig *ResourceConfig
EnableDebug bool
}

Expand Down Expand Up @@ -216,12 +225,20 @@ func getInvokeHostFunctionPreflight(params PreflightParameters) (Preflight, erro

handle := cgo.NewHandle(snapshotSourceHandle{params.LedgerEntryReadTx, params.Logger})
defer handle.Delete()
instructionLeeway := defaultInstructionLeeway
if params.ResourceConfig != nil {
instructionLeeway = params.ResourceConfig.InstructionLeeway
}
resourceConfig := C.resource_config_t{
instruction_leeway: C.uint64_t(instructionLeeway),
}
res := C.preflight_invoke_hf_op(
C.uintptr_t(handle),
C.uint64_t(params.BucketListSize),
invokeHostFunctionCXDR,
sourceAccountCXDR,
li,
resourceConfig,
C.bool(params.EnableDebug),
)
FreeGoXDR(invokeHostFunctionCXDR)
Expand Down
5 changes: 5 additions & 0 deletions cmd/soroban-rpc/lib/preflight.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ typedef struct xdr_vector_t {
size_t len;
} xdr_vector_t;

typedef struct resource_config_t {
uint64_t instruction_leeway; // Allow this many extra instructions when budgeting
} resource_config_t;

typedef struct preflight_result_t {
char *error; // Error string in case of error, otherwise null
xdr_vector_t auth; // array of SorobanAuthorizationEntries
Expand All @@ -43,6 +47,7 @@ preflight_result_t *preflight_invoke_hf_op(uintptr_t handle, // Go Handle to for
const xdr_t invoke_hf_op, // InvokeHostFunctionOp XDR
const xdr_t source_account, // AccountId XDR
const ledger_info_t ledger_info,
const resource_config_t resource_config,
bool enable_debug);

preflight_result_t *preflight_footprint_ttl_op(uintptr_t handle, // Go Handle to forward to SnapshotSourceGet
Expand Down
8 changes: 6 additions & 2 deletions cmd/soroban-rpc/lib/preflight/src/fees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,23 @@ use state_ttl::{get_restored_ledger_sequence, TTLLedgerEntry};
use std::cmp::max;
use std::convert::{TryFrom, TryInto};

use crate::CResourceConfig;

#[allow(clippy::too_many_arguments)]
pub(crate) fn compute_host_function_transaction_data_and_min_fee(
op: &InvokeHostFunctionOp,
pre_storage: &LedgerStorage,
post_storage: &Storage,
budget: &Budget,
resource_config: CResourceConfig,
events: &[DiagnosticEvent],
invocation_result: &ScVal,
bucket_list_size: u64,
current_ledger_seq: u32,
) -> Result<(SorobanTransactionData, i64)> {
let ledger_changes = get_ledger_changes(budget, post_storage, pre_storage, TtlEntryMap::new())?;
let soroban_resources =
calculate_host_function_soroban_resources(&ledger_changes, &post_storage.footprint, budget)
calculate_host_function_soroban_resources(&ledger_changes, &post_storage.footprint, budget, resource_config)
.context("cannot compute host function resources")?;

let contract_events_size =
Expand Down Expand Up @@ -128,6 +131,7 @@ fn calculate_host_function_soroban_resources(
ledger_changes: &[LedgerEntryChange],
footprint: &Footprint,
budget: &Budget,
resource_config: CResourceConfig
) -> Result<SorobanResources> {
let ledger_footprint = storage_footprint_to_ledger_footprint(footprint)
.context("cannot convert storage footprint to ledger footprint")?;
Expand All @@ -143,7 +147,7 @@ fn calculate_host_function_soroban_resources(
.get_cpu_insns_consumed()
.context("cannot get instructions consumed")?;
let instructions = max(
budget_instructions + 1000000,
budget_instructions + resource_config.instruction_leeway,
budget_instructions * 120 / 100,
);
Ok(SorobanResources {
Expand Down
10 changes: 10 additions & 0 deletions cmd/soroban-rpc/lib/preflight/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ fn get_default_c_xdr_vector() -> CXDRVector {
}
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct CResourceConfig {
pub instruction_leeway: u64
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct CPreflightResult {
Expand Down Expand Up @@ -133,6 +139,7 @@ pub extern "C" fn preflight_invoke_hf_op(
invoke_hf_op: CXDR, // InvokeHostFunctionOp XDR in base64
source_account: CXDR, // AccountId XDR in base64
ledger_info: CLedgerInfo,
resource_config: CResourceConfig,
enable_debug: bool,
) -> *mut CPreflightResult {
catch_preflight_panic(Box::new(move || {
Expand All @@ -142,6 +149,7 @@ pub extern "C" fn preflight_invoke_hf_op(
invoke_hf_op,
source_account,
ledger_info,
resource_config,
enable_debug,
)
}))
Expand All @@ -153,6 +161,7 @@ fn preflight_invoke_hf_op_or_maybe_panic(
invoke_hf_op: CXDR, // InvokeHostFunctionOp XDR in base64
source_account: CXDR, // AccountId XDR in base64
ledger_info: CLedgerInfo,
resource_config: CResourceConfig,
enable_debug: bool,
) -> Result<CPreflightResult> {
let invoke_hf_op =
Expand All @@ -166,6 +175,7 @@ fn preflight_invoke_hf_op_or_maybe_panic(
invoke_hf_op,
source_account,
LedgerInfo::from(ledger_info),
resource_config,
enable_debug,
)?;
Ok(result.into())
Expand Down
4 changes: 4 additions & 0 deletions cmd/soroban-rpc/lib/preflight/src/preflight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ use std::convert::{TryFrom, TryInto};
use std::iter::FromIterator;
use std::rc::Rc;

use crate::CResourceConfig;

pub(crate) struct RestorePreamble {
pub(crate) transaction_data: SorobanTransactionData,
pub(crate) min_fee: i64,
Expand All @@ -40,6 +42,7 @@ pub(crate) fn preflight_invoke_hf_op(
invoke_hf_op: InvokeHostFunctionOp,
source_account: AccountId,
ledger_info: LedgerInfo,
resource_config: CResourceConfig,
enable_debug: bool,
) -> Result<PreflightResult> {
let ledger_storage_rc = Rc::new(ledger_storage);
Expand Down Expand Up @@ -117,6 +120,7 @@ pub(crate) fn preflight_invoke_hf_op(
&ledger_storage_rc,
&storage,
&budget,
resource_config,
&diagnostic_events,
&result,
bucket_list_size,
Expand Down

0 comments on commit 9e216ae

Please sign in to comment.