Skip to content

Commit 6f86472

Browse files
Rianhughes/fix sim txn (#2517)
* derive sierra version directly from sierra code, and introduce fix in binary search Co-authored-by: Daniil Ankushin <[email protected]> Signed-off-by: Rian Hughes <[email protected]> Signed-off-by: Rian Hughes <[email protected]> Co-authored-by: AnkushinDaniil <[email protected]>
1 parent 651dc34 commit 6f86472

File tree

2 files changed

+69
-8
lines changed

2 files changed

+69
-8
lines changed

vm/class.go

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ import (
44
"encoding/json"
55
"errors"
66
"fmt"
7+
"strconv"
8+
"strings"
79

810
"github.com/NethermindEth/juno/adapters/core2sn"
911
"github.com/NethermindEth/juno/core"
12+
"github.com/NethermindEth/juno/core/felt"
1013
)
1114

1215
func marshalClassInfo(class core.Class) (json.RawMessage, error) {
@@ -37,9 +40,48 @@ func marshalClassInfo(class core.Class) (json.RawMessage, error) {
3740
classInfo.Class = core2sn.AdaptCompiledClass(c.Compiled)
3841
classInfo.AbiLength = uint32(len(c.Abi))
3942
classInfo.SierraLength = uint32(len(c.Program))
40-
classInfo.SierraVersion = c.Compiled.CompilerVersion
43+
sierraVersion, err := parseSierraVersion(c.Program)
44+
if err != nil {
45+
return nil, err
46+
}
47+
classInfo.SierraVersion = sierraVersion
4148
default:
4249
return nil, fmt.Errorf("unsupported class type %T", c)
4350
}
4451
return json.Marshal(classInfo)
4552
}
53+
54+
// Parse Sierra version from the JSON representation of the program.
55+
//
56+
// Sierra programs contain the version number in two possible formats.
57+
// For pre-1.0-rc0 Cairo versions the program contains the Sierra version
58+
// "0.1.0" as a shortstring in its first Felt (0x302e312e30 = "0.1.0").
59+
// For all subsequent versions the version number is the first three felts
60+
// representing the three parts of a semantic version number.
61+
// TODO: There should be an implementation in the blockifier. If there is, move it to the rust part.
62+
func parseSierraVersion(prog []*felt.Felt) (string, error) {
63+
if len(prog) == 0 {
64+
return "", errors.New("failed to parse sierra version in classInfo")
65+
}
66+
67+
pre01, err := new(felt.Felt).SetString("0x302e312e30")
68+
if err != nil {
69+
return "", err
70+
}
71+
72+
if prog[0].Equal(pre01) {
73+
return "0.1.0", nil
74+
}
75+
76+
if len(prog) < 3 {
77+
return "", errors.New("failed to parse sierra version in classInfo")
78+
}
79+
80+
parts := []string{
81+
strconv.FormatUint(prog[0].Uint64(), 10),
82+
strconv.FormatUint(prog[1].Uint64(), 10),
83+
strconv.FormatUint(prog[2].Uint64(), 10),
84+
}
85+
86+
return strings.Join(parts, "."), nil
87+
}

vm/rust/src/execution.rs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ pub fn is_l2_gas_accounting_enabled(
5050
return Ok(false);
5151
}
5252

53+
5354
let min_sierra_version = &block_context
5455
.versioned_constants()
5556
.min_sierra_version_for_sierra_gas;
@@ -106,14 +107,24 @@ fn get_gas_vector_computation_mode<S>(
106107
where
107108
S: UpdatableState,
108109
{
109-
let original_tx = transaction.clone();
110110
let initial_gas_limit = extract_l2_gas_limit(transaction);
111+
let mut original_transaction = transaction.clone();
111112

112113
// Simulate transaction execution with maximum possible gas to get actual gas usage.
113114
set_l2_gas_limit(transaction, GasAmount::MAX);
115+
// TODO: Consider getting the upper bound from the balance and not changing the execution flags
116+
match transaction {
117+
Transaction::Account(account_transaction) => {
118+
account_transaction.execution_flags.charge_fee = false;
119+
account_transaction.execution_flags.validate = false;
120+
}
121+
_ =>{},
122+
};
114123
let (simulation_result, _) = match simulate_execution(transaction, state, block_context) {
115124
Ok(info) => info,
116-
Err(SimulationError::ExecutionError(error)) => return Err(error),
125+
Err(SimulationError::ExecutionError(error)) => {
126+
return Err(error);
127+
}
117128
Err(SimulationError::OutOfGas(gas)) => {
118129
return Err(TransactionExecutionError::FeeCheckError(
119130
FeeCheckError::MaxGasAmountExceeded {
@@ -131,7 +142,7 @@ where
131142
let l2_gas_adjusted = GasAmount(gas_used.saturating_add(gas_used / 10));
132143
set_l2_gas_limit(transaction, l2_gas_adjusted);
133144

134-
let (l2_gas_limit, mut execution_info, tx_state) =
145+
let (l2_gas_limit, _, tx_state) =
135146
match simulate_execution(transaction, state, block_context) {
136147
Ok((tx_info, tx_state)) => {
137148
// If 110% of the actual transaction gas fee is enough, we use that
@@ -179,17 +190,25 @@ where
179190
}
180191
Err(SimulationError::ExecutionError(error)) => return Err(error),
181192
};
193+
tx_state.abort();
182194

183195
// If the computed gas limit exceeds the initial limit, revert the transaction.
196+
// The L2 gas limit is set to zero to prevent the transaction execution from succeeding
197+
// in the case where the user defined gas limit is less than the required gas limit
184198
if l2_gas_limit > initial_gas_limit {
185-
return original_tx.execute(state, block_context);
199+
set_l2_gas_limit(&mut original_transaction, GasAmount(0));
200+
return original_transaction.execute(state, block_context);
186201
}
187202

203+
set_l2_gas_limit(&mut original_transaction, initial_gas_limit);
204+
let mut simulated_state = CachedState::<_>::create_transactional(state);
205+
let mut exec_info = original_transaction.execute(&mut simulated_state, block_context)?;
206+
188207
// Execute the transaction with the determined gas limit and update the estimate.
189-
tx_state.commit();
190-
execution_info.receipt.gas.l2_gas = l2_gas_limit;
208+
simulated_state.commit();
209+
exec_info.receipt.gas.l2_gas = l2_gas_limit;
191210

192-
Ok(execution_info)
211+
Ok(exec_info)
193212
}
194213

195214
fn calculate_midpoint(a: GasAmount, b: GasAmount) -> GasAmount {

0 commit comments

Comments
 (0)