-
Notifications
You must be signed in to change notification settings - Fork 0
/
vaa_verify.py
107 lines (85 loc) · 3.92 KB
/
vaa_verify.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#!/usr/bin/python3
"""
================================================================================================
The VAA Signature Verify Stateless Program
Copyright 2022 Wormhole Project Contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
------------------------------------------------------------------------------------------------
This program verifies a subset of the signatures in a VAA against the guardian set. This
program works in tandem with the VAA Processor stateful program.
The difference between this version and the Randlabs version is I removed most of the asserts
since we are going to have to completely validate the arguments again in the
TokenBridge contract.
We also cannot retroactively see/verify what arguments were passed into this
function unless all the arguments are in the Txn.application_args so
everything has to get moved out of the lsig args and into the txn_args
================================================================================================
"""
from pyteal.ast import *
from pyteal.types import *
from pyteal.compiler import *
from pyteal.ir import *
from globals import *
from inlineasm import *
import sys
SLOTID_RECOVERED_PK_X = 240
SLOTID_RECOVERED_PK_Y = 241
@Subroutine(TealType.uint64)
def sig_check(signatures, dhash, keys):
si = ScratchVar(TealType.uint64) # signature index (zero-based)
ki = ScratchVar(TealType.uint64) # key index
slen = ScratchVar(TealType.uint64) # signature length
rec_pk_x = ScratchVar(TealType.bytes, SLOTID_RECOVERED_PK_X)
rec_pk_y = ScratchVar(TealType.bytes, SLOTID_RECOVERED_PK_Y)
return Seq(
[
rec_pk_x.store(Bytes("")),
rec_pk_y.store(Bytes("")),
slen.store(Len(signatures)),
For(Seq([
si.store(Int(0)),
ki.store(Int(0))
]),
si.load() < slen.load(),
Seq([
si.store(si.load() + Int(66)),
ki.store(ki.load() + Int(20))
])).Do(
Seq([
InlineAssembly(
"ecdsa_pk_recover Secp256k1",
dhash,
Btoi(Extract(signatures, si.load() + Int(65), Int(1))),
Extract(signatures, si.load() + Int(1), Int(32)), # R
Extract(signatures, si.load() + Int(33), Int(32)), # S
type=TealType.none),
# returned values in stack, pass to scratch-vars
InlineAssembly("store " + str(SLOTID_RECOVERED_PK_Y)),
InlineAssembly("store " + str(SLOTID_RECOVERED_PK_X)),
# Generate Ethereum-type public key, compare with guardian key.
Assert(Extract(keys, ki.load(), Int(20)) == Substring(Keccak256(Concat(rec_pk_x.load(), rec_pk_y.load())), Int(12), Int(32)))
])
),
Return(Int(1))
]
)
def vaa_verify_program():
signatures = Txn.application_args[1]
keys = Txn.application_args[2]
dhash = Txn.application_args[3]
return Seq([
Assert(Txn.rekey_to() == Global.zero_address()),
Assert(Txn.type_enum() == TxnType.ApplicationCall),
Assert(sig_check(signatures, dhash, keys)),
Approve()]
)
def get_vaa_verify():
return compileTeal(vaa_verify_program(), mode=Mode.Signature, version=5)