Last edited by 桂忠
EVM-LOG指令定义
参考:https://ethervm.io/#LOG0
uint8 |
Mnemonic |
Stack Input |
Stack Output |
Expression |
Notes |
A0 |
LOG0 |
offset,length |
- |
LOG0(memory[offset:offset+length]) |
fires an event |
A1 |
LOG1 |
offset,length,topic0 |
- |
LOG1(memory[offset:offset+length], topic0) |
fires an event |
A2 |
LOG2 |
offset,length,topic0,topic1 |
- |
LOG2(memory[offset:offset+length], topic0, topic1) |
fires an event |
A3 |
LOG3 |
offset,length,topic0,topic1,topic2 |
- |
LOG3(memory[offset:offset+length], topic0,topic1,topic2) |
fires an event |
A4 |
LOG4 |
offset,length,topic0,topic1,topic2,topic3 |
- |
LOG4(memory[offset:offset+length], topic0, topic1,topic2,topic3) |
fires an event |
处理流程
LOG0
flowchart LR
LogBytes --> LogTopicNumAddr
LOG1-LOG4
flowchart LR
LogBytes --> LogTopicNumAddr --> LogTopic:topic0 --> LogTopic:topic1 --> ...
- LogBytes: 处理Log数据拷贝(Copy Lookup Memory->PublicLog)和数据长度记录(Public Lookup)
- LogTopicNumAddr: 处理Log数据地址(Public Lookup)
- LogTopic: 处理每一个TopicHash处理(Public Lookup)
具体Gadget设计
LogBytesGadget设计
处理memory[offset:offset+length],数据从Memory拷贝到PulbicLog
主要约束:
- state_stamp = pre + 2
- log_stamp = pre + 1
- next_pc = pc
gen_witness状态变化
cnt |
|
|
|
|
2 |
COPY(9) |
- |
- |
PUBLIC(6) |
1 |
STATE1(8) |
STATE2(8) |
- |
LO_INV(1) |
0 |
DYNA_SELECTOR(20) |
AUX(7) |
- |
- |
CoreRow2-COPY(9) vers_0~vers_8,负责Copy Lookup(处理Log数据拷贝)
cnt |
vers_0 |
vers_1 |
vers_2 |
vers_3 |
vers_4 |
vers_5 |
vers_6 |
vers_7 |
vers_8 |
2 |
src_type=Memory |
src_id=self.call_id |
src_pointer=1 |
src_stamp=2 |
dst_type=PublicLog |
dst_id=self.tx_idx |
dst_pointer=0(PublicLogIndex) |
dst_stamp=log_stamp |
len=length |
CoreRow2-PUBlIC(6) vers_24~vers_31,负责Public Lookup(处理Log数据长度)
cnt |
vers_26 |
vers_27 |
vers_28 |
vers_29 |
vers_30 |
vers_31 |
2 |
tag=TxLog |
tx_idx=self.tx_idx |
log_index=self.log_stamp |
log_tag=DataSize |
0 |
data_len=length |
CoreRow1-STATE1(8) vers_0~vers_7,负责从栈中取出的offset
cnt |
vers_0 |
vers_1 |
vers_2 |
vers_3 |
vers_4 |
vers_5 |
vers_6 |
vers_7 |
1 |
tag=Stack |
stamp=0 |
value_hi=0 |
value_lo=offset |
call_id_contract_addr=self.call_id |
- |
pointer_lo=2 |
is_write=0 |
CoreRow1-STATE2(8) vers_8~vers_15,负责从栈中取出的length
cnt |
vers_0 |
vers_1 |
vers_2 |
vers_3 |
vers_4 |
vers_5 |
vers_6 |
vers_7 |
1 |
tag=Stack |
stamp=0 |
value_hi=0 |
value_lo=length |
call_id_contract_addr=self.call_id |
- |
pointer_lo=2 |
is_write=0 |
CoreRow1-LO_INV(1) vers_24
LogTopicNumAddrGadget设计
主要约束:
- state_stamp = pre
- log_stamp = pre
- next_pc = pc + (1 * topic_left_0)
gen_witness状态变化
- 根据opcode 初始化state.topic_left
cnt |
|
|
|
|
2 |
- |
- |
- |
PUBLIC(6) |
1 |
- |
LOG_LEFT_X(5) |
- |
- |
0 |
DYNA_SELECTOR(20) |
AUX(7) |
- |
- |
CoreRow2-PUBlIC(6) vers_24~vers_31,负责Public Lookup(处理Topic哈希数据)
cnt |
vers_26 |
vers_27 |
vers_28 |
vers_29 |
vers_30 |
vers_31 |
2 |
tag=TxLog |
tx_idx=self.tx_idx |
log_index=self.log_stamp |
topic_log_tag=AddrWithLogX |
address[..4] |
address[4..] |
CoreRow1-LOG_LEFT_X(5) vers_8~vers_12,选择器LOG_LEFT_4~LOG_LEFT_0
cnt |
vers_8 |
vers_9 |
vers_10 |
vers_11 |
vers_12 |
1 |
LOG_LEFT_4 |
LOG_LEFT_3 |
LOG_LEFT_2 |
LOG_LEFT_1 |
LOG_LEFT_0 |
LogTopicGadget设计
主要约束:
- state_stamp = pre
- log_stamp = pre
- next_pc = pc + (1 * topic_left_0)
gen_witness状态变化
cnt |
|
|
|
|
2 |
- |
- |
- |
PUBLIC(6) |
1 |
STATE1(8) |
LOG_LEFT_X(5) |
- |
- |
0 |
DYNA_SELECTOR(20) |
AUX(7) |
- |
- |
CoreRow2-PUBlIC(6) vers_24~vers_31,负责Public Lookup(处理Topic哈希数据)
cnt |
vers_26 |
vers_27 |
vers_28 |
vers_29 |
vers_30 |
vers_31 |
2 |
tag=TxLog |
tx_idx=self.tx_idx |
log_index=self.log_stamp |
topic_log_tag=TopicX |
topic hash[..16] |
topic hash[16..] |
CoreRow1-STATE1(8) vers_0~vers_7,负责从栈中取出的topic_hash
cnt |
vers_0 |
vers_1 |
vers_2 |
vers_3 |
vers_4 |
vers_5 |
vers_6 |
vers_7 |
1 |
tag=Stack |
stamp=0 |
value_hi=0 |
value_lo=topic_hash |
call_id_contract_addr=self.call_id |
- |
pointer_lo=2 |
is_write=0 |
CoreRow1-LOG_LEFT_X(5) vers_8~vers_12,选择器LOG_LEFT_4~LOG_LEFT_0
cnt |
vers_8 |
vers_9 |
vers_10 |
vers_11 |
vers_12 |
1 |
LOG_LEFT_4 |
LOG_LEFT_3 |
LOG_LEFT_2 |
LOG_LEFT_1 |
LOG_LEFT_0 |