@@ -24,8 +24,11 @@ use eth_types::{
24
24
} ,
25
25
Address , Bytecode , GethExecStep , ToAddress , ToBigEndian , ToWord , Word , H256 , U256 ,
26
26
} ;
27
- use ethers_core:: utils:: { get_contract_address, get_create2_address, keccak256} ;
28
- use std:: { cmp:: max, mem} ;
27
+ use ethers_core:: {
28
+ k256:: { elliptic_curve:: consts:: U4 , sha2:: digest:: typenum:: Minimum } ,
29
+ utils:: { get_contract_address, get_create2_address, keccak256} ,
30
+ } ;
31
+ use std:: { cmp:: max, io:: copy, mem} ;
29
32
30
33
/// Reference to the internal state of the CircuitInputBuilder in a particular
31
34
/// [`ExecStep`].
@@ -1602,6 +1605,13 @@ impl<'a> CircuitInputStateRef<'a> {
1602
1605
Ok ( ( ) )
1603
1606
}
1604
1607
1608
+ // get word slot and shift pair for a memory address.
1609
+ pub ( crate ) fn get_addr_shift_slot ( & mut self , addr : u64 ) -> Result < ( u64 , u64 ) , Error > {
1610
+ let shift = addr % 32 ;
1611
+ let slot = addr - shift;
1612
+ Ok ( ( shift, slot) )
1613
+ }
1614
+
1605
1615
/// Generate copy steps for bytecode.
1606
1616
pub ( crate ) fn gen_copy_steps_for_bytecode (
1607
1617
& mut self ,
@@ -1613,17 +1623,56 @@ impl<'a> CircuitInputStateRef<'a> {
1613
1623
bytes_left : u64 ,
1614
1624
) -> Result < Vec < ( u8 , bool , bool ) > , Error > {
1615
1625
let mut copy_steps = Vec :: with_capacity ( bytes_left as usize ) ;
1616
- for idx in 0 ..bytes_left {
1617
- let addr = src_addr. checked_add ( idx) . unwrap_or ( src_addr_end) ;
1618
- let step = if addr < src_addr_end {
1619
- let code = bytecode. code . get ( addr as usize ) . unwrap ( ) ;
1620
- ( code. value , code. is_code , false )
1626
+ if bytes_left == 0 {
1627
+ return Ok ( copy_steps) ;
1628
+ }
1629
+
1630
+ let ( _, dst_begin_slot) = self . get_addr_shift_slot ( dst_addr) . unwrap ( ) ;
1631
+ let ( _, dst_end_slot) = self . get_addr_shift_slot ( dst_addr + bytes_left) . unwrap ( ) ;
1632
+ let mut memory = self . call_ctx_mut ( ) ?. memory . clone ( ) ;
1633
+
1634
+ let minimal_length = dst_end_slot as usize + 32 ;
1635
+ memory. extend_at_least ( minimal_length) ;
1636
+ // collect all bytecode to memory with padding word
1637
+ let code_slot_bytes =
1638
+ memory. 0 [ dst_begin_slot as usize ..( dst_end_slot + 32 ) as usize ] . to_vec ( ) ;
1639
+
1640
+ let mut copy_start = 0u64 ;
1641
+ let mut first_set = true ;
1642
+ for idx in 0 ..code_slot_bytes. len ( ) {
1643
+ let value = memory. 0 [ dst_begin_slot as usize + idx] ;
1644
+ if idx as u64 + dst_begin_slot < dst_addr {
1645
+ // front mask byte
1646
+ copy_steps. push ( ( value, false , true ) ) ;
1647
+ } else if idx as u64 + dst_begin_slot >= dst_addr + bytes_left {
1648
+ // back mask byte
1649
+ copy_steps. push ( ( value, false , true ) ) ;
1621
1650
} else {
1622
- ( 0 , false , false )
1623
- } ;
1624
- copy_steps. push ( step) ;
1625
- //TODO: change value to Word
1626
- self . memory_write ( exec_step, ( dst_addr + idx) . into ( ) , step. 0 ) ?;
1651
+ // real copy byte
1652
+ if first_set {
1653
+ copy_start = idx as u64 ;
1654
+ first_set = false ;
1655
+ }
1656
+
1657
+ let addr = src_addr
1658
+ . checked_add ( idx as u64 - copy_start)
1659
+ . unwrap_or ( src_addr_end) ;
1660
+ let step = if addr < src_addr_end {
1661
+ let code = bytecode. code . get ( addr as usize ) . unwrap ( ) ;
1662
+ ( code. value , code. is_code , false )
1663
+ } else {
1664
+ ( 0 , false , false )
1665
+ } ;
1666
+ copy_steps. push ( step) ;
1667
+ }
1668
+ }
1669
+
1670
+ let mut chunk_index = dst_begin_slot;
1671
+ // memory word writes to destination word
1672
+ for chunk in code_slot_bytes. chunks ( 32 ) {
1673
+ let dest_word = Word :: from_big_endian ( & chunk) ;
1674
+ self . memory_write_word ( exec_step, chunk_index. into ( ) , dest_word) ?;
1675
+ chunk_index = chunk_index + 32 ;
1627
1676
}
1628
1677
1629
1678
Ok ( copy_steps)
@@ -1639,20 +1688,24 @@ impl<'a> CircuitInputStateRef<'a> {
1639
1688
bytes_left : u64 , // number of bytes to copy, with padding
1640
1689
) -> Result < Vec < ( u8 , bool , bool ) > , Error > {
1641
1690
let mut copy_steps = Vec :: with_capacity ( bytes_left as usize ) ;
1691
+ if bytes_left == 0 {
1692
+ return Ok ( copy_steps) ;
1693
+ }
1694
+
1642
1695
println ! ( "calldata : {:?}" , self . call_ctx( ) ?. call_data) ;
1643
1696
let is_root = self . call ( ) ?. is_root ;
1644
- let dst_end_slot_shift = ( dst_addr + bytes_left) % 32 ;
1645
1697
// dest memory slot
1646
- let mut dst_end_slot = ( dst_addr + bytes_left ) - dst_end_slot_shift ;
1647
- let mut dst_begin_slot = dst_addr - dst_addr % 32 ;
1698
+ let ( _ , dst_begin_slot ) = self . get_addr_shift_slot ( dst_addr) . unwrap ( ) ;
1699
+ let ( _ , dst_end_slot ) = self . get_addr_shift_slot ( dst_addr + bytes_left ) . unwrap ( ) ;
1648
1700
let mut memory = if !is_root {
1649
1701
self . caller_ctx_mut ( ) ?. memory . clone ( )
1650
1702
} else {
1651
1703
// self.call_ctx_mut()?.memory already contains calldata
1652
1704
self . call_ctx_mut ( ) ?. memory . clone ( )
1653
1705
} ;
1654
1706
1655
- memory. extend_at_least ( dst_end_slot_shift as usize + 32 ) ;
1707
+ let minimal_length = dst_end_slot as usize + 32 ;
1708
+ memory. extend_at_least ( minimal_length) ;
1656
1709
// collect all bytes to calldata with padding word
1657
1710
let calldata_slot_bytes =
1658
1711
memory. 0 [ dst_begin_slot as usize ..( dst_end_slot + 32 ) as usize ] . to_vec ( ) ;
@@ -1669,19 +1722,24 @@ impl<'a> CircuitInputStateRef<'a> {
1669
1722
// real copy byte
1670
1723
copy_steps. push ( ( value, false , false ) ) ;
1671
1724
}
1672
- //todo: memory word reads if it is an internal call
1673
- // self.push_op(
1674
- // exec_step,
1675
- // RW::READ,
1676
- // MemoryOp::new(self.call()?.caller_id, addr.into(), byte)
1677
1725
}
1678
1726
1727
+ let mut chunk_index = dst_begin_slot;
1679
1728
// memory word writes to destination word
1729
+ chunk_index = dst_begin_slot;
1680
1730
for chunk in calldata_slot_bytes. chunks ( 32 ) {
1681
- println ! ( "{:?}" , chunk) ;
1682
1731
let dest_word = Word :: from_big_endian ( & chunk) ;
1683
- self . memory_write_word ( exec_step, dst_begin_slot. into ( ) , dest_word) ?;
1684
- dst_begin_slot = dst_begin_slot + 32 ;
1732
+ // memory word reads if it is an internal call
1733
+ if !is_root {
1734
+ self . push_op (
1735
+ exec_step,
1736
+ RW :: READ ,
1737
+ MemoryWordOp :: new ( self . call ( ) ?. caller_id , chunk_index. into ( ) , dest_word) ,
1738
+ ) ;
1739
+ }
1740
+
1741
+ self . memory_write_word ( exec_step, chunk_index. into ( ) , dest_word) ?;
1742
+ chunk_index = chunk_index + 32 ;
1685
1743
}
1686
1744
1687
1745
Ok ( copy_steps)
@@ -1693,30 +1751,56 @@ impl<'a> CircuitInputStateRef<'a> {
1693
1751
src_addr : u64 ,
1694
1752
bytes_left : u64 ,
1695
1753
) -> Result < Vec < ( u8 , bool , bool ) > , Error > {
1696
- // Get memory data
1697
- let mem = self
1698
- . call_ctx ( ) ?
1699
- . memory
1700
- . read_chunk ( src_addr. into ( ) , bytes_left. into ( ) ) ;
1701
-
1702
1754
let mut copy_steps = Vec :: with_capacity ( bytes_left as usize ) ;
1703
- for ( idx, byte) in mem. iter ( ) . enumerate ( ) {
1704
- let addr = src_addr + idx as u64 ;
1755
+ if bytes_left == 0 {
1756
+ return Ok ( copy_steps) ;
1757
+ }
1705
1758
1706
- // Read memory
1707
- self . memory_read ( exec_step, ( addr as usize ) . into ( ) , * byte) ?;
1759
+ let ( _, dst_begin_slot) = self . get_addr_shift_slot ( src_addr) . unwrap ( ) ;
1760
+ let ( _, dst_end_slot) = self . get_addr_shift_slot ( src_addr + bytes_left) . unwrap ( ) ;
1761
+ let mut memory = self . call_ctx_mut ( ) ?. memory . clone ( ) ;
1708
1762
1709
- copy_steps. push ( ( * byte, false , false ) ) ;
1763
+ let minimal_length = dst_end_slot as usize + 32 ;
1764
+ memory. extend_at_least ( minimal_length) ;
1765
+ // collect all memory bytes with padding word
1766
+ let log_slot_bytes =
1767
+ memory. 0 [ dst_begin_slot as usize ..( dst_end_slot + 32 ) as usize ] . to_vec ( ) ;
1710
1768
1711
- // Write log
1712
- self . tx_log_write (
1713
- exec_step,
1714
- self . tx_ctx . id ( ) ,
1715
- self . tx_ctx . log_id + 1 ,
1716
- TxLogField :: Data ,
1717
- idx,
1718
- Word :: from ( * byte) ,
1719
- ) ?;
1769
+ let mut copy_start = 0u64 ;
1770
+ let mut first_set = true ;
1771
+ let mut chunk_index = dst_begin_slot;
1772
+ // memory word writes to destination word
1773
+ for chunk in log_slot_bytes. chunks ( 32 ) {
1774
+ let dest_word = Word :: from_big_endian ( & chunk) ;
1775
+ self . memory_read_word ( exec_step, chunk_index. into ( ) , dest_word) ?;
1776
+ chunk_index = chunk_index + 32 ;
1777
+ }
1778
+
1779
+ for idx in 0 ..log_slot_bytes. len ( ) {
1780
+ let value = memory. 0 [ dst_begin_slot as usize + idx] ;
1781
+ if idx as u64 + dst_begin_slot < src_addr {
1782
+ // front mask byte
1783
+ copy_steps. push ( ( value, false , true ) ) ;
1784
+ } else if idx as u64 + dst_begin_slot >= src_addr + bytes_left {
1785
+ // back mask byte
1786
+ copy_steps. push ( ( value, false , true ) ) ;
1787
+ } else {
1788
+ // real copy byte
1789
+ if first_set {
1790
+ copy_start = idx as u64 ;
1791
+ first_set = false ;
1792
+ }
1793
+ copy_steps. push ( ( value, false , false ) ) ;
1794
+ // Write log
1795
+ self . tx_log_write (
1796
+ exec_step,
1797
+ self . tx_ctx . id ( ) ,
1798
+ self . tx_ctx . log_id + 1 ,
1799
+ TxLogField :: Data ,
1800
+ idx - copy_start as usize ,
1801
+ Word :: from ( value) ,
1802
+ ) ?;
1803
+ }
1720
1804
}
1721
1805
1722
1806
Ok ( copy_steps)
0 commit comments