Skip to content

Commit

Permalink
Merge pull request #32 from fjl/withdrawals-storage-interleave
Browse files Browse the repository at this point in the history
withdrawals: interleave storage reads with output formatting
  • Loading branch information
lightclient authored Nov 18, 2024
2 parents 3375a2a + 4637ffa commit a1b3f44
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 127 deletions.
134 changes: 73 additions & 61 deletions src/consolidations/main.eas
Original file line number Diff line number Diff line change
Expand Up @@ -234,77 +234,89 @@ accum_loop:
jumpi @update_head ;; [i, count, head_idx, tail_idx]

;; Determine the storage slot of the address for this iteration. This value is
;; also the base for the other storage slots containing the source and the target
;; public keys. The base slot will be (queue_offset + (queue_head + i)*SLOTS_PER_ITEM).
;; also the base for the other storage slots containing the source and target
;; public keys. The base slot will be (queue_offset + (queue_head + i)*4).
dup3 ;; [head_idx, i, ..]
dup2 ;; [i, head_idx, i, ..]
add ;; [i+head_idx, i, ..]
push SLOTS_PER_ITEM ;; [SLOTS_PER_ITEM, i+head_idx, i, ..]
mul ;; [SLOTS_PER_ITEM*(i+head_idx), i, ..]
push QUEUE_OFFSET ;; [offset, SLOTS_PER_ITEM*(i+head_idx), i, ..]
add ;; [addr_offset, i, ..]

;; Read address from slot 0.
dup1 ;; [addr_offset, addr_offset, i, ..]
sload ;; [addr, addr_offset, i, ..]

;; Read source[0:32] from slot 1.
swap1 ;; [addr_offset, addr, i, ..]
push 1 ;; [1, addr_offset, addr, i, ..]
add ;; [slot1_offset, addr, i, ..]
dup1 ;; [slot1_offset, slot1_offset, addr, i, ..]
sload ;; [source[0:32], slot1_offset, addr, i, ..]

;; Read source[32:48] and target[0:16] from slot 2.
swap1 ;; [slot1_offset, source[0:32], addr, i, ..]
push 1 ;; [1, slot1_offset, source[0:32], addr, i, ..]
add ;; [slot2_offset, source[0:32], addr, i, ..]
dup1 ;; [slot2_offset, slot2_offset, source[0:32], addr, i, ..]
sload ;; [src[32:48] ++ tgt[0:16], slot2_offset, source[0:32], addr, i, ..]
push SLOTS_PER_ITEM ;; [4, i+head_idx, i, ..]
mul ;; [4*(i+head_idx), i, ..]
push QUEUE_OFFSET ;; [offset, 4*(i+head_idx), i, ..]
add ;; [slotbase, i, ..]

;; Read target[16:48] from slot 3.
swap1 ;; [slot2_offset, src[32:48] ++ tgt[0:16], source[0:32], addr, i, ..]
push 1 ;; [1, slot2_offset, src[32:48] ++ tgt[0:16], source[0:32], addr, i, ..]
add ;; [slot3_offset, src[32:48] ++ tgt[0:16], source[0:32], addr, i, ..]
sload ;; [target[16:32], src[32:48] ++ tgt[0:16], source[0:32], addr, i, ..]

;; Write values to memory flat and contiguously. This require combining the
;; four storage elements so there is no padding:
;; (addr, source[0:32], source[32:48] ++ target[0:16], target[16:48])
;; Write values to memory flat and contiguously. This requires combining the
;; four storage elements (addr, spk1, spk2_tpk1, tpk2) so there is no padding.
;;
;; The slots have the following layout:
;;
;; 0: addr
;; 0x00 | 00 00 00 00 00 00 00 00 00 00 00 00 aa aa aa aa
;; 0x10 | aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa
;;
;; 1: source[0:32] -> spk1
;; 0x00 | bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb
;; 0x10 | bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb
;;
;; 2: source[32:48] ++ target[0:16] -> spk2_tpk1
;; 0x00 | bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb
;; 0x10 | cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc
;;
;; 3: target[16:48] -> tpk2
;; 0x20 | cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc
;; 0x30 | cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc

;; Compute offset = i*RECORD_SIZE.
;; Compute the output offset = i*RECORD_SIZE.
dup2 ;; [i, slotbase, i, ..]
push RECORD_SIZE ;; [size, i, slotbase, i, ..]
mul ;; [offset=size*i, slotbase, i, ..]

dup5 ;; [i, target[16:32], src[32:48] ++ tgt[0:16], source[0:32], addr, i, ..]
push RECORD_SIZE ;; [size, i, target[16:32], src[32:48] ++ tgt[0:16], source[0:32], addr, i, ..]
mul ;; [offset, target[16:32], src[32:48] ++ tgt[0:16], source[0:32], addr, i, ..]
;; Read slot 'addr' from storage.
dup2 ;; [slotbase, offset, slotbase, ..]
sload ;; [addr, offset, slotbase, ..]

;; Shift addr bytes.
swap4 ;; [addr, src[32:48] ++ tgt[0:16], source[0:32], target[16:32], offset, i, ..]
push 12*8 ;; [96, addr, src[32:48] ++ tgt[0:16], source[0:32], target[16:32], offset, i, ..]
shl ;; [addr<<96, src[32:48] ++ tgt[0:16], source[0:32], target[16:32], offset, i, ..]
push 12*8 ;; [96, addr, offset, slotbase, ..]
shl ;; [addr<<96, offset, slotbase, ..]

;; Store addr at offset = i*RECORD_SIZE.
dup5 ;; [offset, addr<<96, offset, src[32:48] ++ tgt[0:16], source[0:32], target[16:32], i, ..]
mstore ;; [offset, src[32:48] ++ tgt[0:16], source[0:32], target[16:32], i, ..]

;; Store source[0:32] at offset = i*RECORD_SIZE + 20.
swap2 ;; [source[0:32], src[32:48] ++ tgt[0:16], target[16:32], offset, i, ..]
dup4 ;; [offset, source[0:32], src[32:48] ++ tgt[0:16], target[16:32], offset, i, ..]
push 20 ;; [20, offset, source[0:32], src[32:48] ++ tgt[0:16], target[16:32], offset, i, ..]
add ;; [offset+20, source[0:32], src[32:48] ++ tgt[0:16], target[16:32], offset, i, ..]
mstore ;; [src[32:48] ++ tgt[0:16], target[16:32], offset, i, ..]

;; Store src[32:48] ++ tgt[0:16] at offset = i*RECORD_SIZE + 52.
dup3 ;; [offset, src[32:48] ++ tgt[0:16], target[16:32], offset, i, ..]
push 52 ;; [52, offset, src[32:48] ++ tgt[0:16], target[16:32], offset, i, ..]
add ;; [offset+52, src[32:48] ++ tgt[0:16], target[16:32], offset, i, ..]
mstore ;; [target[16:32], offset, i, ..]

;; Store target[16:48] at offset = i*RECORD_SIZE + 84.
swap1 ;; [offset, target[16:32], i, ..]
push 84 ;; [84, offset, target[16:32], i, ..]
add ;; [offset+84, target[16:32], i, ..]
mstore ;; [i, ..]
dup2 ;; [offset, addr<<96, offset, slotbase, ..]
mstore ;; [offset, slotbase, ..]
push 20 ;; [20, offset, slotbase, ..]
add ;; [offset=offset+20, slotbase, ..]

;; Read slot 'spk1' from storage.
dup2 ;; [slotbase, offset, slotbase, ..]
push 1 ;; [1, slotbase, offset, slotbase, ..]
add ;; [slot, offset, slotbase, ..]
sload ;; [spk1, offset, slotbase, ..]

;; Store spk1 at output offset = i*RECORD_SIZE+20.
dup2 ;; [offset, spk1, offset, slotbase, ..]
mstore ;; [offset, slotbase, ..]
push 32 ;; [32, offset, slotbase, ..]
add ;; [offset=offset+32, slotbase, ..]

;; Read slot 'spk2_tpk1' from stoarge.
dup2 ;; [slotbase, offset, slotbase, ..]
push 2 ;; [1, slotbase, offset, slotbase, ..]
add ;; [slot, offset, slotbase, ..]
sload ;; [spk2_tpk1, offset, slotbase, ..]

;; Store spk2_tpk1 at output offset = i*RECORD_SIZE+52.
dup2 ;; [offset, src[32:48] ++ tgt[0:16], offset, slotbase, ..]
mstore ;; [offset, slotbase, ..]
push 32 ;; [32, offset, slotbase, ..]
add ;; [offset=offset+32, slotbase, ..]

;; Read target[16:48] from slot 3.
swap1 ;; [slotbase, offset, ..]
push 3 ;; [3, slotbase, offset, ..]
add ;; [slot, offset, ..]
sload ;; [tpk2, offset, ..]

;; Store tpk2 at output offset = i*RECORD_SIZE+84.
swap1 ;; [offset, tpk2, ..]
mstore ;; [..]

;; Increment i.
push 1 ;; [1, i, ..]
Expand Down
123 changes: 57 additions & 66 deletions src/withdrawals/main.eas
Original file line number Diff line number Diff line change
Expand Up @@ -236,92 +236,83 @@ accum_loop:
add ;; [i+head_idx, i, ..]
push 3 ;; [3, i+head_idx, i, ..]
mul ;; [3*(i+head_idx), i, ..]
push QUEUE_OFFSET ;; [offset, 3*(i+head_idx), i, ..]
add ;; [addr_offset, i, ..]

;; Read address.
dup1 ;; [addr_offset, addr_offset, i, ..]
sload ;; [addr, addr_offset, i, ..]

;; Compute pk1 offset and read it.
swap1 ;; [addr_offset, addr, i, ..]
push 1 ;; [1, addr_offset, addr, i, ..]
add ;; [pk1_offset, addr, i, ..]
dup1 ;; [pk1_offset, pk1_offset, addr, i, ..]
sload ;; [pk1, pk1_offset, addr, i, ..]

;; Compute pk2_am offset and read it.
swap1 ;; [pk1_offset, pk1, addr, i, ..]
push 1 ;; [1, pk1_offset, pk1, addr, i, ..]
add ;; [pk2_am_offset, pk1, addr, i, ..]
sload ;; [pk2_am, pk1, addr, i, ..]

;; Reorder values.
swap2 ;; [addr, pk1, pk2_am, i, ..]

;; Write values to memory flat and contiguously. This require combining the
push QUEUE_OFFSET ;; [queue_offset, 3*(i+head_idx), i, ..]
add ;; [slotbase, i, ..]

;; Write values to memory flat and contiguously. This requires combining the
;; three storage elements (addr, pk1, pk2_am) so there is no padding.
;;
;; Each stack element has the following layout:
;; The slots have the following layout:
;;
;; A: addr
;; 0: addr
;; 0x00 | 00 00 00 00 00 00 00 00 00 00 00 00 aa aa aa aa
;; 0x10 | aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa
;;
;; B: pk[0:32] -> pk1
;; 1: pk[0:32] -> pk1
;; 0x00 | bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb
;; 0x10 | bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb
;;
;; C: pk[32:48] ++ am[0:8] -> pk2_am
;; 0x00 | cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc
;; 0x10 | dd dd dd dd dd dd dd dd 00 00 00 00 00 00 00 00
;;
;; To get these three stack elements into the correct contiguous format, it is
;; neccessary to combine them in the follow form:
;;
;; (A[12:32] ++ B[0:12], B[12:32] ++ C[0:12], C[12:24])
;; 2: pk[32:48] ++ am[0:8] -> pk2_am
;; 0x00 | bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb
;; 0x10 | cc cc cc cc cc cc cc cc 00 00 00 00 00 00 00 00

;; Compute the output offset = i*RECORD_SIZE.
dup2 ;; [i, slotbase, i, ..]
push RECORD_SIZE ;; [size, i, slotbase, i, ..]
mul ;; [offset=size*i, slotbase, i, ..]

;; Compute offset = i*RECORD_SIZE.
dup4 ;; [i, addr, pk1, pk2_am, i, ..]
push RECORD_SIZE ;; [size, i, addr, pk1, pk2_am, i, ..]
mul ;; [offset, addr, pk1, pk2_am, i, ..]
;; Read slot 'addr' from storage.
dup2 ;; [slotbase, offset, slotbase, ..]
sload ;; [addr, offset, slotbase, ..]

;; Shift addr bytes.
swap1 ;; [addr, offset, pk1, pk2_am, i, ..]
push 12*8 ;; [96, addr, offset, pk1, pk2_am, i, ..]
shl ;; [addr<<96, offset, pk1, pk2_am, i, ..]

;; Store addr at current offset.
dup2 ;; [offset, addr<<96, offset, pk1, pk2_am, i, ..]
mstore ;; [offset, pk1, pk2_am, i, ..]
push 20 ;; [20, offset, pk1, pk2_am, i, ..]
add ;; [offset, pk1, pk2_am, i, ..]

;; Store pk1 at offset = i*RECORD_SIZE + 20.
swap1 ;; [pk1, offset, pk2_am, i, ..]
dup2 ;; [offset, pk1, offset, pk2_am, i, ..]
mstore ;; [offset, pk2_am, i, ..]
push 32 ;; [32, offset, pk2_am, i, ..]
add ;; [offset, pk2_am, i, ..]
push 12*8 ;; [96, addr, offset, slotbase, ..]
shl ;; [addr<<96, offset, slotbase, ..]

;; Store addr at output offset = i*RECORD_SIZE.
dup2 ;; [offset, addr<<96, offset, slotbase, ..]
mstore ;; [offset, slotbase, ..]
push 20 ;; [20, offset, slotbase, ..]
add ;; [offset=offset+20, slotbase, ..]

;; Read slot 'pk1' from storage.
dup2 ;; [slotbase, offset, slotbase, ..]
push 1 ;; [1, slotbase, offset, slotbase, ..]
add ;; [slot, offset, slotbase, ..]
sload ;; [pk1, offset, slotbase, ..]

;; Store pk1 at output offset = i*RECORD_SIZE + 20.
dup2 ;; [offset, pk1, offset, slotbase, ..]
mstore ;; [offset, slotbase, ..]
push 32 ;; [32, offset, slotbase, ..]
add ;; [offset=offset+32, slotbase, ..]

;; Read slot 'pk2_am' from storage.
swap1 ;; [slotbase, offset, ..]
push 2 ;; [2, slotbase, offset, ..]
add ;; [slot, offset, ..]
sload ;; [pk2_am, offset, ..]

;; Extract pk2 from pk2_am.
dup2 ;; [pk2_am, offset, pk2_am, i, ..]
push pk2_mask ;; [mask, pk2_am, offset, pk2_am, i, ..]
and ;; [pk2, offset, pk2_am, i, ..]
dup1 ;; [pk2_am, pk2_am, offset, ..]
push pk2_mask ;; [mask, pk2_am, offset, ..]
and ;; [pk2, pk2_am, offset, ..]

;; Store pk2 at offset = i*RECORD_SIZE + 52.
dup2 ;; [offset, pk2, offset, pk2_am, i, ..]
mstore ;; [offset, pk2_am, i, ..]
push 16 ;; [16, offset, pk2_am, i, ..]
add ;; [offset, pk2_am, i, ..]
dup3 ;; [offset, pk2, pk2_am, offset, ..]
mstore ;; [pk2_am, offset, ..]
swap1 ;; [offset, pk2_am, ..]
push 16 ;; [16, offset, pk2_am, ..]
add ;; [offset=offset+16, pk2_am, ..]

;; Extract am from pk2_am.
swap1 ;; [pk2_am, offset, i, ..]
push 8*8 ;; [shft, pk2_am, offset, i, ..]
shr ;; [am, offset, i, ..]
swap1 ;; [pk2_am, offset, slotbase, ..]
push 8*8 ;; [shft, pk2_am, offset, ..]
shr ;; [am, offset, ..]

;; Store am at offset = i*RECORD_SIZE + 68.
swap1 ;; [offset, am, i, ..]
;; Note we convert to little-endian.
swap1 ;; [offset, am, ..]
%mstore_uint64_le() ;; [i, ..]

;; Increment i.
Expand Down

0 comments on commit a1b3f44

Please sign in to comment.