Skip to content

Commit

Permalink
Compute fee_per_write_1kb using the bucket list size
Browse files Browse the repository at this point in the history
  • Loading branch information
2opremio committed Jul 24, 2023
1 parent 1b8c37f commit 293f343
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 27 deletions.
2 changes: 1 addition & 1 deletion cmd/soroban-rpc/internal/jsonrpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func NewJSONRPCHandler(cfg *config.Config, params HandlerParams) Handler {
"getLedgerEntries": methods.NewGetLedgerEntriesHandler(params.Logger, params.LedgerEntryReader),
"getTransaction": methods.NewGetTransactionHandler(params.TransactionStore),
"sendTransaction": methods.NewSendTransactionHandler(params.Daemon, params.Logger, params.TransactionStore, cfg.NetworkPassphrase),
"simulateTransaction": methods.NewSimulateTransactionHandler(params.Logger, params.LedgerEntryReader, params.PreflightGetter),
"simulateTransaction": methods.NewSimulateTransactionHandler(params.Logger, params.LedgerEntryReader, params.LedgerReader, params.PreflightGetter),
}), &bridgeOptions)

return Handler{
Expand Down
25 changes: 22 additions & 3 deletions cmd/soroban-rpc/internal/methods/simulate_transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package methods

import (
"context"
"fmt"

"github.com/creachadair/jrpc2"
"github.com/creachadair/jrpc2/handler"
Expand Down Expand Up @@ -38,11 +39,11 @@ type SimulateTransactionResponse struct {
}

type PreflightGetter interface {
GetPreflight(ctx context.Context, readTx db.LedgerEntryReadTx, 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) (preflight.Preflight, error)
}

// NewSimulateTransactionHandler returns a json rpc handler to run preflight simulations
func NewSimulateTransactionHandler(logger *log.Entry, ledgerEntryReader db.LedgerEntryReader, getter PreflightGetter) jrpc2.Handler {
func NewSimulateTransactionHandler(logger *log.Entry, ledgerEntryReader db.LedgerEntryReader, ledgerReader db.LedgerReader, getter PreflightGetter) jrpc2.Handler {

return handler.New(func(ctx context.Context, request SimulateTransactionRequest) SimulateTransactionResponse {
var txEnvelope xdr.TransactionEnvelope
Expand Down Expand Up @@ -98,8 +99,26 @@ func NewSimulateTransactionHandler(logger *log.Entry, ledgerEntryReader db.Ledge
Error: err.Error(),
}
}
// obtain bucket size
closeMeta, ok, err := ledgerReader.GetLedger(ctx, latestLedger)
if err != nil {
return SimulateTransactionResponse{
Error: err.Error(),
}
}
if !ok {
return SimulateTransactionResponse{
Error: fmt.Sprintf("missing meta for latest ledger (%d)", latestLedger),
}
}
if closeMeta.V != 2 {
return SimulateTransactionResponse{
Error: fmt.Sprintf("latest ledger (%d) meta has unexpected verion (%d)", latestLedger, closeMeta.V),
}
}
bucketListSize := uint64(closeMeta.V2.TotalByteSizeOfBucketList)

result, err := getter.GetPreflight(ctx, readTx, sourceAccount, op.Body, footprint)
result, err := getter.GetPreflight(ctx, readTx, bucketListSize, sourceAccount, op.Body, footprint)
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 @@ -135,7 +135,7 @@ func (m *metricsLedgerEntryWrapper) GetLedgerEntry(key xdr.LedgerKey, includeExp
return ok, entry, err
}

func (pwp *PreflightWorkerPool) GetPreflight(ctx context.Context, readTx db.LedgerEntryReadTx, 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) (Preflight, error) {
if pwp.isClosed.Load() {
return Preflight{}, errors.New("preflight worker pool is closed")
}
Expand All @@ -148,6 +148,7 @@ func (pwp *PreflightWorkerPool) GetPreflight(ctx context.Context, readTx db.Ledg
OpBody: opBody,
NetworkPassphrase: pwp.networkPassphrase,
LedgerEntryReadTx: &wrappedTx,
BucketListSize: bucketListSize,
Footprint: footprint,
}
resultC := make(chan workerResult)
Expand Down
5 changes: 3 additions & 2 deletions cmd/soroban-rpc/internal/preflight/preflight.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ type PreflightParameters struct {
Footprint xdr.LedgerFootprint
NetworkPassphrase string
LedgerEntryReadTx db.LedgerEntryReadTx
BucketListSize uint64
}

type Preflight struct {
Expand Down Expand Up @@ -126,8 +127,6 @@ func GoNullTerminatedStringSlice(str **C.char) []string {
}

func GetPreflight(ctx context.Context, params PreflightParameters) (Preflight, error) {
handle := cgo.NewHandle(snapshotSourceHandle{params.LedgerEntryReadTx, params.Logger})
defer handle.Delete()
switch params.OpBody.Type {
case xdr.OperationTypeInvokeHostFunction:
return getInvokeHostFunctionPreflight(params)
Expand All @@ -154,6 +153,7 @@ func getFootprintExpirationPreflight(params PreflightParameters) (Preflight, err

res := C.preflight_footprint_expiration_op(
C.uintptr_t(handle),
C.uint64_t(params.BucketListSize),
opBodyCString,
footprintCString,
)
Expand Down Expand Up @@ -215,6 +215,7 @@ func getInvokeHostFunctionPreflight(params PreflightParameters) (Preflight, erro
defer handle.Delete()
res := C.preflight_invoke_hf_op(
C.uintptr_t(handle),
C.uint64_t(params.BucketListSize),
invokeHostFunctionCString,
sourceAccountCString,
li,
Expand Down
7 changes: 4 additions & 3 deletions cmd/soroban-rpc/internal/test/get_ledger_entry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,12 @@ func TestGetLedgerEntrySucceeds(t *testing.T) {
kp := keypair.Root(StandaloneNetworkPassphrase)
account := txnbuild.NewSimpleAccount(kp.Address(), 0)

helloWorldContract := getHelloWorldContract(t)
params := preflightTransactionParams(t, client, txnbuild.TransactionParams{
SourceAccount: &account,
IncrementSequenceNum: true,
Operations: []txnbuild.Operation{
createInstallContractCodeOperation(account.AccountID, testContract),
createInstallContractCodeOperation(account.AccountID, helloWorldContract),
},
BaseFee: txnbuild.MinBaseFee,
Preconditions: txnbuild.Preconditions{
Expand All @@ -93,7 +94,7 @@ func TestGetLedgerEntrySucceeds(t *testing.T) {

sendSuccessfulTransaction(t, client, kp, tx)

contractHash := sha256.Sum256(testContract)
contractHash := sha256.Sum256(helloWorldContract)
keyB64, err := xdr.MarshalBase64(xdr.LedgerKey{
Type: xdr.LedgerEntryTypeContractCode,
ContractCode: &xdr.LedgerKeyContractCode{
Expand All @@ -112,5 +113,5 @@ func TestGetLedgerEntrySucceeds(t *testing.T) {
assert.GreaterOrEqual(t, result.LatestLedger, result.LastModifiedLedger)
var entry xdr.LedgerEntryData
assert.NoError(t, xdr.SafeUnmarshalBase64(result.XDR, &entry))
assert.Equal(t, testContract, *entry.MustContractCode().Body.Code)
assert.Equal(t, helloWorldContract, *entry.MustContractCode().Body.Code)
}
4 changes: 3 additions & 1 deletion cmd/soroban-rpc/internal/test/simulate_transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,9 @@ func preflightTransactionParams(t *testing.T, client *jrpc2.Client, params txnbu

params.Operations = []txnbuild.Operation{op}

params.BaseFee += response.MinResourceFee
// Hack until we start including rent fees
minResourceFee := response.MinResourceFee * 120 / 100
params.BaseFee += minResourceFee
return params
}

Expand Down
6 changes: 4 additions & 2 deletions cmd/soroban-rpc/lib/preflight.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ typedef struct CPreflightResult {
uint64_t memory_bytes;
} CPreflightResult;

CPreflightResult *preflight_invoke_hf_op(uintptr_t handle, // Go Handle to forward to SnapshotSourceGet and SnapshotSourceHasconst
CPreflightResult *preflight_invoke_hf_op(uintptr_t handle, // Go Handle to forward to SnapshotSourceGet and SnapshotSourceHas
uint64_t bucket_list_size, // Bucket list size of current ledger
const char *invoke_hf_op, // InvokeHostFunctionOp XDR in base64
const char *source_account, // AccountId XDR in base64
const struct CLedgerInfo ledger_info);

CPreflightResult *preflight_footprint_expiration_op(uintptr_t handle, // Go Handle to forward to SnapshotSourceGet and SnapshotSourceHasconst
CPreflightResult *preflight_footprint_expiration_op(uintptr_t handle, // Go Handle to forward to SnapshotSourceGet and SnapshotSourceHas
uint64_t bucket_list_size, // Bucket list size of current ledger
const char *op_body, // OperationBody XDR in base64
const char *footprint); // LedgerFootprint XDR in base64

Expand Down
26 changes: 20 additions & 6 deletions cmd/soroban-rpc/lib/preflight/src/fees.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use ledger_storage;
use soroban_env_host::budget::Budget;
use soroban_env_host::fees::{
compute_transaction_resource_fee, FeeConfiguration, TransactionResources,
compute_transaction_resource_fee, compute_write_fee_per_1kb, FeeConfiguration,
TransactionResources, WriteFeeConfiguration,
};
use soroban_env_host::storage::{AccessType, Footprint, Storage, StorageMap};
use soroban_env_host::xdr;
Expand All @@ -23,10 +24,11 @@ pub(crate) fn compute_host_function_transaction_data_and_min_fee(
storage: &Storage,
budget: &Budget,
events: &Vec<DiagnosticEvent>,
bucket_list_size: u64,
) -> Result<(SorobanTransactionData, i64), Box<dyn error::Error>> {
let soroban_resources =
calculate_host_function_soroban_resources(snapshot_source, storage, budget, events)?;
let fee_configuration = get_fee_configuration(snapshot_source)?;
let fee_configuration = get_fee_configuration(snapshot_source, bucket_list_size)?;

let read_write_entries = u32::try_from(soroban_resources.footprint.read_write.as_vec().len())?;

Expand Down Expand Up @@ -165,6 +167,7 @@ fn get_configuration_setting(

fn get_fee_configuration(
ledger_storage: &ledger_storage::LedgerStorage,
bucket_list_size: u64,
) -> Result<FeeConfiguration, Box<dyn error::Error>> {
// TODO: to improve the performance of this function (which is invoked every single preflight call) we can
// 1. modify ledger_storage.get() so that it can gather multiple entries at once
Expand Down Expand Up @@ -202,14 +205,23 @@ fn get_fee_configuration(
);
};

let write_fee_configuration = WriteFeeConfiguration {
bucket_list_target_size_bytes: ledger_cost.bucket_list_target_size_bytes,
write_fee_1kb_bucket_list_low: ledger_cost.write_fee1_kb_bucket_list_low,
write_fee_1kb_bucket_list_high: ledger_cost.write_fee1_kb_bucket_list_high,
bucket_list_write_fee_growth_factor: ledger_cost.bucket_list_write_fee_growth_factor,
};

// Taken from Stellar Core's InitialSorobanNetworkConfig in NetworkConfig.h
let fee_configuration = FeeConfiguration {
fee_per_instruction_increment: compute.fee_rate_per_instructions_increment,
fee_per_read_entry: ledger_cost.fee_read_ledger_entry,
fee_per_write_entry: ledger_cost.fee_write_ledger_entry,
fee_per_read_1kb: ledger_cost.fee_read1_kb,
// TODO: This fild should had been removed by the env library
fee_per_write_1kb: 0,
fee_per_write_1kb: compute_write_fee_per_1kb(
bucket_list_size as i64,
&write_fee_configuration,
),
fee_per_historical_1kb: historical_data.fee_historical1_kb,
fee_per_metadata_1kb: metadata.fee_extended_meta_data1_kb,
fee_per_propagate_1kb: bandwidth.fee_propagate_data1_kb,
Expand Down Expand Up @@ -296,6 +308,7 @@ pub(crate) fn compute_bump_footprint_exp_transaction_data_and_min_fee(
footprint: LedgerFootprint,
ledgers_to_expire: u32,
snapshot_source: &ledger_storage::LedgerStorage,
bucket_list_size: u64,
) -> Result<(SorobanTransactionData, i64), Box<dyn error::Error>> {
let read_bytes = calculate_unmodified_ledger_entry_bytes(
footprint.read_only.as_vec(),
Expand Down Expand Up @@ -324,7 +337,7 @@ pub(crate) fn compute_bump_footprint_exp_transaction_data_and_min_fee(
&soroban_resources.footprint,
)?,
};
let fee_configuration = get_fee_configuration(snapshot_source)?;
let fee_configuration = get_fee_configuration(snapshot_source, bucket_list_size)?;
let (min_fee, ref_fee) =
compute_transaction_resource_fee(&transaction_resources, &fee_configuration);
let transaction_data = SorobanTransactionData {
Expand All @@ -338,6 +351,7 @@ pub(crate) fn compute_bump_footprint_exp_transaction_data_and_min_fee(
pub(crate) fn compute_restore_footprint_transaction_data_and_min_fee(
footprint: LedgerFootprint,
snapshot_source: &ledger_storage::LedgerStorage,
bucket_list_size: u64,
) -> Result<(SorobanTransactionData, i64), Box<dyn error::Error>> {
let write_bytes = calculate_unmodified_ledger_entry_bytes(
footprint.read_write.as_vec(),
Expand Down Expand Up @@ -368,7 +382,7 @@ pub(crate) fn compute_restore_footprint_transaction_data_and_min_fee(
&soroban_resources.footprint,
)?,
};
let fee_configuration = get_fee_configuration(snapshot_source)?;
let fee_configuration = get_fee_configuration(snapshot_source, bucket_list_size)?;
let (min_fee, ref_fee) =
compute_transaction_resource_fee(&transaction_resources, &fee_configuration);
let transaction_data = SorobanTransactionData {
Expand Down
39 changes: 31 additions & 8 deletions cmd/soroban-rpc/lib/preflight/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,26 @@ fn preflight_error(str: String) -> *mut CPreflightResult {

#[no_mangle]
pub extern "C" fn preflight_invoke_hf_op(
handle: libc::uintptr_t, // Go Handle to forward to SnapshotSourceGet and SnapshotSourceHasconst
handle: libc::uintptr_t, // Go Handle to forward to SnapshotSourceGet and SnapshotSourceHas
bucket_list_size: u64, // Bucket list size for current ledger
invoke_hf_op: *const libc::c_char, // InvokeHostFunctionOp XDR in base64
source_account: *const libc::c_char, // AccountId XDR in base64
ledger_info: CLedgerInfo,
) -> *mut CPreflightResult {
catch_preflight_panic(Box::new(move || {
preflight_invoke_hf_op_or_maybe_panic(handle, invoke_hf_op, source_account, ledger_info)
preflight_invoke_hf_op_or_maybe_panic(
handle,
bucket_list_size,
invoke_hf_op,
source_account,
ledger_info,
)
}))
}

fn preflight_invoke_hf_op_or_maybe_panic(
handle: libc::uintptr_t, // Go Handle to forward to SnapshotSourceGet and SnapshotSourceHas
handle: libc::uintptr_t,
bucket_list_size: u64, // Go Handle to forward to SnapshotSourceGet and SnapshotSourceHas
invoke_hf_op: *const libc::c_char, // InvokeHostFunctionOp XDR in base64
source_account: *const libc::c_char, // AccountId XDR in base64
ledger_info: CLedgerInfo,
Expand Down Expand Up @@ -134,6 +142,7 @@ fn preflight_invoke_hf_op_or_maybe_panic(
&storage,
&budget,
&diagnostic_events,
bucket_list_size,
)?;
let transaction_data_cstr = CString::new(transaction_data.to_xdr_base64()?)?;
Ok(CPreflightResult {
Expand All @@ -150,17 +159,24 @@ fn preflight_invoke_hf_op_or_maybe_panic(

#[no_mangle]
pub extern "C" fn preflight_footprint_expiration_op(
handle: libc::uintptr_t, // Go Handle to forward to SnapshotSourceGet and SnapshotSourceHasconst
handle: libc::uintptr_t, // Go Handle to forward to SnapshotSourceGet and SnapshotSourceHas
bucket_list_size: u64, // Bucket list size for current ledger
op_body: *const libc::c_char, // OperationBody XDR in base64
footprint: *const libc::c_char, // LedgerFootprint XDR in base64
) -> *mut CPreflightResult {
catch_preflight_panic(Box::new(move || {
preflight_footprint_expiration_op_or_maybe_panic(handle, op_body, footprint)
preflight_footprint_expiration_op_or_maybe_panic(
handle,
bucket_list_size,
op_body,
footprint,
)
}))
}

fn preflight_footprint_expiration_op_or_maybe_panic(
handle: libc::uintptr_t,
bucket_list_size: u64,
op_body: *const libc::c_char,
footprint: *const libc::c_char,
) -> Result<CPreflightResult, Box<dyn error::Error>> {
Expand All @@ -176,9 +192,10 @@ fn preflight_footprint_expiration_op_or_maybe_panic(
ledger_footprint,
op.ledgers_to_expire,
snapshot_source,
bucket_list_size,
),
OperationBody::RestoreFootprint(_) => {
preflight_restore_footprint(ledger_footprint, snapshot_source)
preflight_restore_footprint(ledger_footprint, snapshot_source, bucket_list_size)
}
op => Err(format!(
"preflight_footprint_expiration_op(): unsupported operation type {}",
Expand All @@ -192,12 +209,14 @@ fn preflight_bump_footprint_expiration(
footprint: LedgerFootprint,
ledgers_to_expire: u32,
snapshot_source: &LedgerStorage,
bucket_list_size: u64,
) -> Result<CPreflightResult, Box<dyn Error>> {
let (transaction_data, min_fee) =
fees::compute_bump_footprint_exp_transaction_data_and_min_fee(
footprint,
ledgers_to_expire,
snapshot_source,
bucket_list_size,
)?;
let transaction_data_cstr = CString::new(transaction_data.to_xdr_base64()?)?;
Ok(CPreflightResult {
Expand All @@ -215,9 +234,13 @@ fn preflight_bump_footprint_expiration(
fn preflight_restore_footprint(
footprint: LedgerFootprint,
snapshot_source: &LedgerStorage,
bucket_list_size: u64,
) -> Result<CPreflightResult, Box<dyn Error>> {
let (transaction_data, min_fee) =
fees::compute_restore_footprint_transaction_data_and_min_fee(footprint, snapshot_source)?;
let (transaction_data, min_fee) = fees::compute_restore_footprint_transaction_data_and_min_fee(
footprint,
snapshot_source,
bucket_list_size,
)?;
let transaction_data_cstr = CString::new(transaction_data.to_xdr_base64()?)?;
Ok(CPreflightResult {
error: null_mut(),
Expand Down

0 comments on commit 293f343

Please sign in to comment.