Skip to content

Commit ac21217

Browse files
committed
fix(clarity-wasm): pass_argument_to_wasm has correct ABI representation for optional and response
1 parent b06b89c commit ac21217

File tree

1 file changed

+75
-29
lines changed

1 file changed

+75
-29
lines changed

clarity/src/vm/clarity_wasm.rs

Lines changed: 75 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -539,21 +539,16 @@ pub fn call_function<'a, 'b, 'c>(
539539

540540
// Convert the args into wasmtime values
541541
let mut wasm_args = vec![];
542-
for arg in args {
542+
for (arg, ty) in args.iter().zip(func_types.get_arg_types()) {
543543
let (arg_vec, new_offset, new_in_mem_offset) =
544-
pass_argument_to_wasm(memory, &mut store, arg, offset, in_mem_offset)?;
544+
pass_argument_to_wasm(memory, &mut store, ty, arg, offset, in_mem_offset)?;
545545
wasm_args.extend(arg_vec);
546546
offset = new_offset;
547547
in_mem_offset = new_in_mem_offset;
548548
}
549549

550550
// Reserve stack space for the return value, if necessary.
551-
let return_type = store
552-
.data()
553-
.contract_context()
554-
.functions
555-
.get(function_name)
556-
.ok_or(CheckErrors::UndefinedFunction(function_name.to_string()))?
551+
let return_type = func_types
557552
.get_return_type()
558553
.as_ref()
559554
.ok_or(Error::Wasm(WasmError::ExpectedReturnValue))?
@@ -1459,6 +1454,7 @@ fn write_to_wasm(
14591454
fn pass_argument_to_wasm(
14601455
memory: Memory,
14611456
mut store: impl AsContextMut,
1457+
ty: &TypeSignature,
14621458
value: &Value,
14631459
offset: i32,
14641460
in_mem_offset: i32,
@@ -1482,27 +1478,71 @@ fn pass_argument_to_wasm(
14821478
in_mem_offset,
14831479
)),
14841480
Value::Optional(o) => {
1485-
let mut buffer = vec![Val::I32(if o.data.is_some() { 1 } else { 0 })];
1486-
let (inner, new_offset, new_in_mem_offset) = pass_argument_to_wasm(
1481+
let TypeSignature::OptionalType(inner_ty) = ty else {
1482+
return Err(Error::Wasm(WasmError::ValueTypeMismatch));
1483+
};
1484+
1485+
if let Some(inner_value) = o.data.as_ref() {
1486+
let mut buffer = vec![Val::I32(1)];
1487+
let (inner_buffer, new_offset, new_in_mem_offset) = pass_argument_to_wasm(
1488+
memory,
1489+
store,
1490+
inner_ty,
1491+
inner_value,
1492+
offset,
1493+
in_mem_offset,
1494+
)?;
1495+
buffer.extend(inner_buffer);
1496+
Ok((buffer, new_offset, new_in_mem_offset))
1497+
} else {
1498+
let buffer = clar2wasm_ty(ty)
1499+
.into_iter()
1500+
.map(|vt| match vt {
1501+
ValType::I32 => Val::I32(0),
1502+
ValType::I64 => Val::I64(0),
1503+
_ => unreachable!("No other types used in Clarity-Wasm"),
1504+
})
1505+
.collect();
1506+
Ok((buffer, offset, in_mem_offset))
1507+
}
1508+
}
1509+
Value::Response(r) => {
1510+
let TypeSignature::ResponseType(inner_tys) = ty else {
1511+
return Err(Error::Wasm(WasmError::ValueTypeMismatch));
1512+
};
1513+
let mut buffer = vec![Val::I32(r.committed as i32)];
1514+
let (value_buffer, new_offset, new_in_mem_offset) = pass_argument_to_wasm(
14871515
memory,
14881516
store,
1489-
o.data
1490-
.as_ref()
1491-
.map_or(&Value::none(), |boxed_value| &boxed_value),
1517+
if r.committed {
1518+
&inner_tys.0
1519+
} else {
1520+
&inner_tys.1
1521+
},
1522+
&r.data,
14921523
offset,
14931524
in_mem_offset,
14941525
)?;
1495-
buffer.extend(inner);
1496-
Ok((buffer, new_offset, new_in_mem_offset))
1497-
}
1498-
Value::Response(r) => {
1499-
let mut buffer = vec![Val::I32(if r.committed { 1 } else { 0 })];
1500-
let (inner, new_offset, new_in_mem_offset) = if r.committed {
1501-
pass_argument_to_wasm(memory, store, &r.data, offset, in_mem_offset)?
1526+
let empty_buffer = clar2wasm_ty(if r.committed {
1527+
&inner_tys.1
15021528
} else {
1503-
pass_argument_to_wasm(memory, store, &r.data, offset, in_mem_offset)?
1504-
};
1505-
buffer.extend(inner);
1529+
&inner_tys.0
1530+
})
1531+
.into_iter()
1532+
.map(|vt| match vt {
1533+
ValType::I32 => Val::I32(0),
1534+
ValType::I64 => Val::I64(0),
1535+
_ => unreachable!("No other types used in Clarity-Wasm"),
1536+
});
1537+
1538+
if r.committed {
1539+
buffer.extend(value_buffer);
1540+
buffer.extend(empty_buffer);
1541+
} else {
1542+
buffer.extend(empty_buffer);
1543+
buffer.extend(value_buffer);
1544+
}
1545+
15061546
Ok((buffer, new_offset, new_in_mem_offset))
15071547
}
15081548
Value::Sequence(SequenceData::String(CharType::ASCII(s))) => {
@@ -1549,14 +1589,18 @@ fn pass_argument_to_wasm(
15491589
Ok((buffer, offset, adjusted_in_mem_offset))
15501590
}
15511591
Value::Sequence(SequenceData::List(l)) => {
1592+
let TypeSignature::SequenceType(SequenceSubtype::ListType(ltd)) = ty else {
1593+
return Err(Error::Wasm(WasmError::ValueTypeMismatch));
1594+
};
1595+
15521596
let mut buffer = vec![Val::I32(offset)];
15531597
let mut written = 0;
15541598
let mut in_mem_written = 0;
15551599
for item in &l.data {
15561600
let (len, in_mem_len) = write_to_wasm(
15571601
&mut store,
15581602
memory,
1559-
l.type_signature.get_list_item_type(),
1603+
ltd.get_list_item_type(),
15601604
offset + written,
15611605
in_mem_offset + in_mem_written,
15621606
item,
@@ -1601,18 +1645,20 @@ fn pass_argument_to_wasm(
16011645
let adjusted_in_mem_offset = in_mem_offset + bytes.len() as i32;
16021646
Ok((buffer, offset, adjusted_in_mem_offset))
16031647
}
1604-
Value::Tuple(TupleData {
1605-
type_signature,
1606-
data_map,
1607-
}) => {
1648+
Value::Tuple(TupleData { data_map, .. }) => {
1649+
let TypeSignature::TupleType(tuple_ty) = ty else {
1650+
return Err(Error::Wasm(WasmError::ValueTypeMismatch));
1651+
};
1652+
16081653
let mut buffer = vec![];
16091654
let mut offset = offset;
16101655
let mut in_mem_offset = in_mem_offset;
1611-
for name in type_signature.get_type_map().keys() {
1656+
for (name, ty) in tuple_ty.get_type_map() {
16121657
let b;
16131658
(b, offset, in_mem_offset) = pass_argument_to_wasm(
16141659
memory,
16151660
store.as_context_mut(),
1661+
ty,
16161662
&data_map[name],
16171663
offset,
16181664
in_mem_offset,

0 commit comments

Comments
 (0)