@@ -20,8 +20,8 @@ use super::errors::RuntimeErrorType;
20
20
use super :: events:: * ;
21
21
use super :: functions:: crypto:: { pubkey_to_address_v1, pubkey_to_address_v2} ;
22
22
use super :: types:: {
23
- ASCIIData , AssetIdentifier , BlockInfoProperty , BuffData , BurnBlockInfoProperty , CharType ,
24
- FixedFunction , FunctionType , ListData , ListTypeData , OptionalData , PrincipalData ,
23
+ ASCIIData , AssetIdentifier , BlockInfoProperty , BuffData , BurnBlockInfoProperty , CallableData ,
24
+ CharType , FixedFunction , FunctionType , ListData , ListTypeData , OptionalData , PrincipalData ,
25
25
QualifiedContractIdentifier , ResponseData , SequenceData , StacksAddressExtensions ,
26
26
StandardPrincipalData , TraitIdentifier , TupleData , TupleTypeSignature , UTF8Data , BUFF_1 ,
27
27
BUFF_32 , BUFF_33 ,
@@ -539,21 +539,16 @@ pub fn call_function<'a, 'b, 'c>(
539
539
540
540
// Convert the args into wasmtime values
541
541
let mut wasm_args = vec ! [ ] ;
542
- for arg in args {
542
+ for ( arg, ty ) in args. iter ( ) . zip ( func_types . get_arg_types ( ) ) {
543
543
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) ?;
545
545
wasm_args. extend ( arg_vec) ;
546
546
offset = new_offset;
547
547
in_mem_offset = new_in_mem_offset;
548
548
}
549
549
550
550
// 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
557
552
. get_return_type ( )
558
553
. as_ref ( )
559
554
. ok_or ( Error :: Wasm ( WasmError :: ExpectedReturnValue ) ) ?
@@ -1459,6 +1454,7 @@ fn write_to_wasm(
1459
1454
fn pass_argument_to_wasm (
1460
1455
memory : Memory ,
1461
1456
mut store : impl AsContextMut ,
1457
+ ty : & TypeSignature ,
1462
1458
value : & Value ,
1463
1459
offset : i32 ,
1464
1460
in_mem_offset : i32 ,
@@ -1482,27 +1478,71 @@ fn pass_argument_to_wasm(
1482
1478
in_mem_offset,
1483
1479
) ) ,
1484
1480
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 (
1487
1515
memory,
1488
1516
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 ,
1492
1523
offset,
1493
1524
in_mem_offset,
1494
1525
) ?;
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
1502
1528
} 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
+
1506
1546
Ok ( ( buffer, new_offset, new_in_mem_offset) )
1507
1547
}
1508
1548
Value :: Sequence ( SequenceData :: String ( CharType :: ASCII ( s) ) ) => {
@@ -1519,8 +1559,20 @@ fn pass_argument_to_wasm(
1519
1559
let adjusted_in_mem_offset = in_mem_offset + s. data . len ( ) as i32 ;
1520
1560
Ok ( ( buffer, offset, adjusted_in_mem_offset) )
1521
1561
}
1522
- Value :: Sequence ( SequenceData :: String ( CharType :: UTF8 ( _s) ) ) => {
1523
- todo ! ( "Value type not yet implemented: {:?}" , value)
1562
+ Value :: Sequence ( SequenceData :: String ( CharType :: UTF8 ( s) ) ) => {
1563
+ // For a utf8 string, convert the chars to big-endian i32, convert this into a list of
1564
+ // bytes, then pass the offset and length to the wasm function
1565
+ let bytes: Vec < u8 > = String :: from_utf8 ( s. items ( ) . iter ( ) . flatten ( ) . copied ( ) . collect ( ) )
1566
+ . map_err ( |e| Error :: Wasm ( WasmError :: WasmGeneratorError ( e. to_string ( ) ) ) ) ?
1567
+ . chars ( )
1568
+ . flat_map ( |c| ( c as u32 ) . to_be_bytes ( ) )
1569
+ . collect ( ) ;
1570
+ let buffer = vec ! [ Val :: I32 ( in_mem_offset) , Val :: I32 ( bytes. len( ) as i32 ) ] ;
1571
+ memory
1572
+ . write ( & mut store, in_mem_offset as usize , & bytes)
1573
+ . map_err ( |e| Error :: Wasm ( WasmError :: UnableToWriteMemory ( e. into ( ) ) ) ) ?;
1574
+ let adjusted_in_mem_offset = in_mem_offset + bytes. len ( ) as i32 ;
1575
+ Ok ( ( buffer, offset, adjusted_in_mem_offset) )
1524
1576
}
1525
1577
Value :: Sequence ( SequenceData :: Buffer ( b) ) => {
1526
1578
// For a buffer, write the bytes into the memory, then pass the
@@ -1537,14 +1589,18 @@ fn pass_argument_to_wasm(
1537
1589
Ok ( ( buffer, offset, adjusted_in_mem_offset) )
1538
1590
}
1539
1591
Value :: Sequence ( SequenceData :: List ( l) ) => {
1592
+ let TypeSignature :: SequenceType ( SequenceSubtype :: ListType ( ltd) ) = ty else {
1593
+ return Err ( Error :: Wasm ( WasmError :: ValueTypeMismatch ) ) ;
1594
+ } ;
1595
+
1540
1596
let mut buffer = vec ! [ Val :: I32 ( offset) ] ;
1541
1597
let mut written = 0 ;
1542
1598
let mut in_mem_written = 0 ;
1543
1599
for item in & l. data {
1544
1600
let ( len, in_mem_len) = write_to_wasm (
1545
1601
& mut store,
1546
1602
memory,
1547
- l . type_signature . get_list_item_type ( ) ,
1603
+ ltd . get_list_item_type ( ) ,
1548
1604
offset + written,
1549
1605
in_mem_offset + in_mem_written,
1550
1606
item,
@@ -1556,9 +1612,61 @@ fn pass_argument_to_wasm(
1556
1612
buffer. push ( Val :: I32 ( written) ) ;
1557
1613
Ok ( ( buffer, offset + written, in_mem_offset + in_mem_written) )
1558
1614
}
1559
- Value :: Principal ( _p) => todo ! ( "Value type not yet implemented: {:?}" , value) ,
1560
- Value :: CallableContract ( _c) => todo ! ( "Value type not yet implemented: {:?}" , value) ,
1561
- Value :: Tuple ( _t) => todo ! ( "Value type not yet implemented: {:?}" , value) ,
1615
+ Value :: Principal ( PrincipalData :: Standard ( StandardPrincipalData ( v, h) ) ) => {
1616
+ let bytes: Vec < u8 > = std:: iter:: once ( v) . chain ( h. iter ( ) ) . copied ( ) . collect ( ) ;
1617
+ let buffer = vec ! [ Val :: I32 ( in_mem_offset) , Val :: I32 ( bytes. len( ) as i32 ) ] ;
1618
+ memory
1619
+ . write ( & mut store, in_mem_offset as usize , & bytes)
1620
+ . map_err ( |e| Error :: Wasm ( WasmError :: UnableToWriteMemory ( e. into ( ) ) ) ) ?;
1621
+ let adjusted_in_mem_offset = in_mem_offset + bytes. len ( ) as i32 ;
1622
+ Ok ( ( buffer, offset, adjusted_in_mem_offset) )
1623
+ }
1624
+ Value :: Principal ( PrincipalData :: Contract ( p) )
1625
+ | Value :: CallableContract ( CallableData {
1626
+ contract_identifier : p,
1627
+ ..
1628
+ } ) => {
1629
+ // Callable types can just ignore the optional trait identifier, and
1630
+ // is handled like a qualified contract
1631
+ let QualifiedContractIdentifier {
1632
+ issuer : StandardPrincipalData ( v, h) ,
1633
+ name,
1634
+ } = p;
1635
+ let bytes: Vec < u8 > = std:: iter:: once ( v)
1636
+ . chain ( h. iter ( ) )
1637
+ . chain ( std:: iter:: once ( & name. len ( ) ) )
1638
+ . chain ( name. as_bytes ( ) )
1639
+ . copied ( )
1640
+ . collect ( ) ;
1641
+ let buffer = vec ! [ Val :: I32 ( in_mem_offset) , Val :: I32 ( bytes. len( ) as i32 ) ] ;
1642
+ memory
1643
+ . write ( & mut store, in_mem_offset as usize , & bytes)
1644
+ . map_err ( |e| Error :: Wasm ( WasmError :: UnableToWriteMemory ( e. into ( ) ) ) ) ?;
1645
+ let adjusted_in_mem_offset = in_mem_offset + bytes. len ( ) as i32 ;
1646
+ Ok ( ( buffer, offset, adjusted_in_mem_offset) )
1647
+ }
1648
+ Value :: Tuple ( TupleData { data_map, .. } ) => {
1649
+ let TypeSignature :: TupleType ( tuple_ty) = ty else {
1650
+ return Err ( Error :: Wasm ( WasmError :: ValueTypeMismatch ) ) ;
1651
+ } ;
1652
+
1653
+ let mut buffer = vec ! [ ] ;
1654
+ let mut offset = offset;
1655
+ let mut in_mem_offset = in_mem_offset;
1656
+ for ( name, ty) in tuple_ty. get_type_map ( ) {
1657
+ let b;
1658
+ ( b, offset, in_mem_offset) = pass_argument_to_wasm (
1659
+ memory,
1660
+ store. as_context_mut ( ) ,
1661
+ ty,
1662
+ & data_map[ name] ,
1663
+ offset,
1664
+ in_mem_offset,
1665
+ ) ?;
1666
+ buffer. extend ( b) ;
1667
+ }
1668
+ Ok ( ( buffer, offset, in_mem_offset) )
1669
+ }
1562
1670
}
1563
1671
}
1564
1672
0 commit comments