naive: move signature verification inside loop

Before this change, signatures were verified according to the owners at
the beginning of batch, which is wrong.  Now we do it per wrap, but this
is *also* wrong because they should actually be verified per tx, in case
the owner changes within a wrap.

Also introduces the roll/wrap terminology.
This commit is contained in:
Philip Monk 2021-04-20 23:08:32 -07:00
parent f9e93fa660
commit 05dbd8cddd
No known key found for this signature in database
GPG Key ID: B66E1F02604E44EC
2 changed files with 73 additions and 58 deletions

View File

@ -28,6 +28,8 @@
-- --
:: ::
|% |%
:: TODO: is `dat` supposed to be a 32-byte hash? I guess so
::
++ verifier ++ verifier
^- ^verifier:naive ^- ^verifier:naive
|= [dat=@ v=@ r=@ s=@] |= [dat=@ v=@ r=@ s=@]

View File

@ -31,6 +31,10 @@
:: ::
:: TODO: could remove `ship` from most txs since it's in `from` :: TODO: could remove `ship` from most txs since it's in `from`
:: ::
:: TODO: hmm i don't think wraps can be done easily? because how do
:: you keep track of intra-wrap ownership changes. you need to verify
:: the eth signature outside, then verify owner as you go along
::
/+ std /+ std
=> => std => => std
:: Laconic bit :: Laconic bit
@ -186,8 +190,9 @@
+$ operators (jug address address) +$ operators (jug address address)
+$ effects (list diff) +$ effects (list diff)
+$ proxy ?(%own %spawn %manage %vote %transfer) +$ proxy ?(%own %spawn %manage %vote %transfer)
+$ tx +$ roll (list wrap)
[from=[=ship =proxy] skim-tx] +$ wrap [raw=@ txs=(list tx)]
+$ tx [from=[=ship =proxy] skim-tx]
+$ skim-tx +$ skim-tx
$% [%transfer-point =ship =address reset=?] $% [%transfer-point =ship =address reset=?]
[%spawn =ship =address] [%spawn =ship =address]
@ -224,43 +229,36 @@
~> %slog.[0 meg] ~> %slog.[0 meg]
+<+ +<+
:: ::
++ parse-batch ++ parse-roll
|= [=verifier =state batch=@] |= [=state batch=@]
^- (list tx) =| =roll
=| txs=(list tx) |- ^+ roll
|- ^- (list tx)
?~ batch ?~ batch
(flop txs) (flop roll)
=/ parse-result (parse-tx verifier state batch) =/ parse-result (parse-wrap state batch)
:: Parsing failed, abort batch :: Parsing failed, abort batch
:: ::
?~ parse-result ?~ parse-result
(debug %parse-failed ~) (debug %parse-failed ~)
=^ signed=(list tx) batch u.parse-result =^ =wrap batch u.parse-result
$(txs (welp (flop signed) txs)) $(roll [wrap roll])
:: ::
:: TODO: change batch to be a cursor to avoid allocating atoms :: TODO: change batch to be a cursor to avoid allocating atoms
:: ::
++ parse-tx ++ parse-wrap
|= [=verifier =state batch=@] |= [=state batch=@]
^- (unit [(list tx) rest=@]) ^- (unit [wrap rest=@])
=/ batch [len=0 rest=batch] =/ batch [len=0 rest=batch]
|^
=^ sig batch (take 3 65)
:: TODO: reset len?
::
=/ signed-batch +.batch
=- ?~ res =- ?~ res
~ ~
:- ~ `[[(end [0 len.batch.u.res] rest.batch) txs.u.res] rest.batch.u.res]
?. (verify-sig-and-nonce txs.u.res sig len.batch.u.res signed-batch) |^
[(debug %sig-failed ~) rest.batch.u.res] =^ sig batch (take 3 65)
[txs.u.res rest.batch.u.res]
^- res=(unit [txs=(list tx) =_batch]) ^- res=(unit [txs=(list tx) =_batch])
=^ single=@ batch (take 0) =^ single=@ batch (take 0)
?: =(0 single) ?: =(0 single)
:: Single tx :: Single tx
=/ single-res=(unit [=tx batch=_batch]) parse-single-tx =/ single-res=(unit [=tx batch=_batch]) parse-tx
?~ single-res ?~ single-res
~ ~
`[[tx.u.single-res ~] batch.u.single-res] `[[tx.u.single-res ~] batch.u.single-res]
@ -274,7 +272,7 @@
?: =(count 0) ?: =(count 0)
`[~ batch] `[~ batch]
=^ pad batch (take 0) :: byte align =^ pad batch (take 0) :: byte align
=/ next-res=(unit [=tx batch=_batch]) parse-single-tx =/ next-res=(unit [=tx batch=_batch]) parse-tx
?~ next-res ?~ next-res
~ ~
=. batch batch.u.next-res =. batch batch.u.next-res
@ -284,7 +282,7 @@
=. batch batch.u.rest-res =. batch batch.u.rest-res
`[[tx.u.next-res txs.u.rest-res] batch] `[[tx.u.next-res txs.u.rest-res] batch]
:: ::
++ parse-single-tx ++ parse-tx
^- (unit [tx _batch]) ^- (unit [tx _batch])
=^ from-proxy=@ batch (take 0 3) =^ from-proxy=@ batch (take 0 3)
?: (gth from-proxy 4) (debug %bad-proxy ~) ?: (gth from-proxy 4) (debug %bad-proxy ~)
@ -355,33 +353,33 @@
=^ child=ship batch (take 3 4) =^ child=ship batch (take 3 4)
=^ parent=ship batch (take 3 4) =^ parent=ship batch (take 3 4)
[[child parent] batch] [[child parent] batch]
:: --
++ verify-sig-and-nonce ::
|= [txs=(list tx) sig=@ len=@ud signed-batch=@] ++ verify-sig-and-nonce
^- ? |= [=verifier =state =wrap]
=/ creds=(list [=address =nonce]) ^- ?
%+ turn txs |^
|= =tx =/ creds=(list [=address =nonce])
=/ point (get-point state ship.from.tx) %+ turn txs.wrap
?> ?=(^ point) :: we never parse more than four bytes |= =tx
?- proxy.from.tx =/ point (get-point state ship.from.tx)
%own owner.own.u.point ?> ?=(^ point) :: we never parse more than four bytes
%spawn spawn-proxy.own.u.point ?- proxy.from.tx
%manage management-proxy.own.u.point %own owner.own.u.point
%vote voting-proxy.own.u.point %spawn spawn-proxy.own.u.point
%transfer transfer-proxy.own.u.point %manage management-proxy.own.u.point
== %vote voting-proxy.own.u.point
=/ nonces (turn creds |=([* =nonce] nonce)) %transfer transfer-proxy.own.u.point
=/ signed-data ==
%: can 0 =/ nonces (turn creds |=([* =nonce] nonce))
[(mul (bex 5) (lent nonces)) (rep 5 nonces)] =/ sig (end [3 65] raw.wrap)
[len (end [0 len] signed-batch)] =/ signed-data
~ %^ dad [5 (lent nonces)] (rep 5 nonces)
== (rsh [3 65] raw.wrap)
=/ dress (verify-sig sig signed-data) =/ dress (verify-sig sig signed-data)
?~ dress ?~ dress
| |
(levy creds |=([=address *] =(address u.dress))) (levy creds |=([=address *] =(address u.dress)))
:: Verify signature and produce signer address :: Verify signature and produce signer address
:: ::
++ verify-sig ++ verify-sig
@ -596,21 +594,36 @@
:: ::
++ receive-batch ++ receive-batch
|= [=verifier =state batch=@] |= [=verifier =state batch=@]
=/ txs=(list tx) (parse-batch verifier state batch) =/ =roll (parse-roll state batch)
:: Handle each wrap
::
|- ^- [effects ^state] |- ^- [effects ^state]
?~ txs =* roll-loop $
?~ roll
[~ state] [~ state]
:: Verify signature, else skip wrap
::
=* wrap i.roll
?. (verify-sig-and-nonce verifier state wrap)
%+ debug %l2-sig-failed
roll-loop(roll t.roll)
:: Handle each transaction in this wrap
::
|- ^- [effects ^state]
=* wrap-loop $
?~ txs.wrap
roll-loop(roll t.roll)
:: Increment nonce, even if it later fails :: Increment nonce, even if it later fails
:: ::
=^ effects-1 points.state (increment-nonce state from.i.txs) =^ effects-1 points.state (increment-nonce state from.i.txs.wrap)
:: Process tx :: Process tx
:: ::
=^ effects-2 state =^ effects-2 state
=/ tx-result=(unit [effects ^state]) (receive-tx state i.txs) =/ tx-result=(unit [effects ^state]) (receive-tx state i.txs.wrap)
?~ tx-result ?~ tx-result
(debug %l2-tx-failed `state) (debug %l2-tx-failed `state)
u.tx-result u.tx-result
=^ effects-3 state $(txs t.txs) =^ effects-3 state wrap-loop(txs.wrap t.txs.wrap)
[:(welp effects-1 effects-2 effects-3) state] [:(welp effects-1 effects-2 effects-3) state]
:: ::
++ increment-nonce ++ increment-nonce