Skip to content

Commit

Permalink
Merge branch 'develop' into feat/expr-comments
Browse files Browse the repository at this point in the history
  • Loading branch information
obycode authored Mar 7, 2023
2 parents 5a1c815 + 10256ae commit dff6c54
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 2 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE

- The transaction receipts for smart contract publish transactions now indicate
a result of `(err none)` if the top-level code of the smart contract contained
runtime error. Fixes issue #3154.
runtime error and include details about the error in the `vm_error` field of
the receipt. Fixes issues #3154, #3328.

## [2.1]

Expand Down
111 changes: 110 additions & 1 deletion src/chainstate/stacks/db/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,31 @@ impl StacksTransactionReceipt {
pub fn from_analysis_failure(
tx: StacksTransaction,
analysis_cost: ExecutionCost,
error: clarity::vm::clarity::Error,
) -> StacksTransactionReceipt {
let error_string = match error {
clarity_error::Analysis(ref check_error) => {
if let Some(span) = check_error.diagnostic.spans.first() {
format!(
":{}:{}: {}",
span.start_line, span.start_column, check_error.diagnostic.message
)
} else {
format!("{}", check_error.diagnostic.message)
}
}
clarity_error::Parse(ref parse_error) => {
if let Some(span) = parse_error.diagnostic.spans.first() {
format!(
":{}:{}: {}",
span.start_line, span.start_column, parse_error.diagnostic.message
)
} else {
format!("{}", parse_error.diagnostic.message)
}
}
_ => error.to_string(),
};
StacksTransactionReceipt {
transaction: tx.into(),
events: vec![],
Expand All @@ -194,7 +218,7 @@ impl StacksTransactionReceipt {
execution_cost: analysis_cost,
microblock_header: None,
tx_index: 0,
vm_error: None,
vm_error: Some(error_string),
}
}

Expand Down Expand Up @@ -1124,6 +1148,7 @@ impl StacksChainState {
let receipt = StacksTransactionReceipt::from_analysis_failure(
tx.clone(),
analysis_cost,
other_error,
);

// abort now -- no burns
Expand Down Expand Up @@ -2148,6 +2173,90 @@ pub mod test {
}
}

#[test]
fn process_smart_contract_transaction_syntax_error() {
let contracts = [
"(define-data-var bar int 0)) ;; oops",
";; `Int` instead of `int`
(define-data-var bar Int 0)",
];
let contract_names = ["hello-world-0", "hello-world-1"];
let expected_errors = [
"Tried to close list which isn't open.",
":2:14: invalid variable definition",
];
let expected_errors_2_1 = ["unexpected ')'", ":2:14: invalid variable definition"];

let mut chainstate = instantiate_chainstate(false, 0x80000000, function_name!());

let privk = StacksPrivateKey::from_hex(
"6d430bb91222408e7706c9001cfaeb91b08c2be6d5ac95779ab52c6b431950e001",
)
.unwrap();
let auth = TransactionAuth::from_p2pkh(&privk).unwrap();
let addr = auth.origin().address_testnet();

for (dbi, burn_db) in ALL_BURN_DBS.iter().enumerate() {
let mut conn = chainstate.block_begin(
burn_db,
&FIRST_BURNCHAIN_CONSENSUS_HASH,
&FIRST_STACKS_BLOCK_HASH,
&ConsensusHash([(dbi + 1) as u8; 20]),
&BlockHeaderHash([(dbi + 1) as u8; 32]),
);

let mut next_nonce = 0;
for i in 0..contracts.len() {
let contract_name = contract_names[i];
let contract = contracts[i].to_string();

test_debug!("\ninstantiate contract\n{}\n", &contract);

let mut tx_contract = StacksTransaction::new(
TransactionVersion::Testnet,
auth.clone(),
TransactionPayload::new_smart_contract(&contract_name, &contract, None)
.unwrap(),
);

tx_contract.chain_id = 0x80000000;
tx_contract.set_tx_fee(0);
tx_contract.set_origin_nonce(next_nonce);

let mut signer = StacksTransactionSigner::new(&tx_contract);
signer.sign_origin(&privk).unwrap();

let signed_tx = signer.get_tx().unwrap();

let _contract_id = QualifiedContractIdentifier::new(
StandardPrincipalData::from(addr.clone()),
ContractName::from(contract_name),
);

let (fee, receipt) = StacksChainState::process_transaction(
&mut conn,
&signed_tx,
false,
ASTRules::PrecheckSize,
)
.unwrap();

// Verify that the syntax error is recorded in the receipt
let expected_error =
if burn_db.get_stacks_epoch(0).unwrap().epoch_id == StacksEpochId::Epoch21 {
expected_errors_2_1[i].to_string()
} else {
expected_errors[i].to_string()
};
assert_eq!(receipt.vm_error.unwrap(), expected_error);

next_nonce += 1;
}

conn.commit_block();
}
}

#[test]
fn process_smart_contract_transaction_runtime_error() {
let contract_correct = "
Expand Down

0 comments on commit dff6c54

Please sign in to comment.