From EVM
pub_input
:
from
to
value
fee
good until block
Rolling current state before update
from_leaf
, to_leaf
:
pubkey
nonce
balance
merkle_path: Fr[TREE_HEIGHT]
Modified EdDSA signature: meddsa_sign(pub_input || nonce || good_until_block)
sig
Rolling current state after update
merkle_root_updated
Public input:
final_hash
(see rolling_hash_cur
calculation in circuit)Witness:
merkle_root_old
merkle_root_new
total_fees
block number
tx_witness
# Initialize variables
merkle_root_cur := merkle_root_old
total_fees_cur := 0
block_number := N
rolling_hash_cur := sha256(total_fees|| block_number || xor(merkle_root_old, merkle_root_new)) // should fit into 512 bit for input, 256 bits of output
for tx in tx_witness:
# Add pub input to the rolling tx hash
rolling_hash_cur = sha256(tx.pub_input || rolling_hash_cur)
# Ensure from and to leaves are rooted in the current Merkle tree state
enforce_leaves_in_merkle_tree(merkle_root_cur, [tx.from_leaf, tx.from_leaf])
# Verify signature
enforce( meddsa_verify(tx.pub_input || tx.from_leaf.nonce, sig) )
# Check balance
value_uncompressed := uncompress(tx.pub_input.value)
enforce( value_uncompressed > 0 ) # unless enforced by uncompress()
enforce( tx.from_leaf.balance >= value_uncompressed )
# Overflow check unneccessary if token supply is bounded
# Check fee
fee_uncompressed := uncompress(tx.pub_input.fee)
tx.from_leaf.balance = safe_sub(tx.from_leaf.balance, fee_uncompressed)
# Update leaves (intermediate witness variables required for the next loop cycle)
tx.from_leaf.nonce += 1
tx.from_leaf.balance -= value_uncompressed
tx.to_leaf.balance += value_uncompressed
# Update total sum of fees (this should take only one constraint per proof)
total_fees_cur += fee_uncompressed
# Check post-update state
enforce( tx.to_leaf.balance >= 0 ) # this overflow check unnecessary if total token supply is limited
merkle_root_cur = tx.merkle_root_updated
enforce_leaves_in_merkle_tree(merkle_root_cur, [tx.from_leaf, tx.from_leaf])
enforce( tx.good_until_block <= block_number)
# OPTION save on constraints by placing bytes
# from more than one transaction into the rolling hash
# at once. It also saves on sha256 calls in smart-contract
for i in (0, num_txes / (512/pub_input_length)):
pub_input_bytes = []
for j in (0, 512/pub_input_length):
pub_input_bytes += tx[i*(512/pub_input_length) + j].pub_input
rolling_hash_batched = sha256(pub_input_bytes || rolling_hash_batched)
# Last Merkle state must equal input parameter
enforce( merkle_root_cur == merkle_root_new )
# Final check verifies validity of all input parameters
enforce( truncated(rolling_hash_cur) == final_hash )
Non-trivial part here will be to find the intersection point of two merkle paths and properly update this node on recomputation of the root
for leaf in leaves:
leaf_hash := pedersen_hash(leaf.pubkey || leaf.balance || leaf.nonce)
enforce( merkle_root_cur == merkle_root(leaf_hash, leaf.merkle_path) )
return ( 10 ^ (val & (2 ^ EXPONENT_BITS - 1) ) ) * (val >> EXPONENT_BITS)
Trivial.
or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Syncing