added Hand-testing Guide + Testlib

This commit is contained in:
Hernán Di Pietro 2021-11-17 11:13:08 -03:00
parent 8470c0d881
commit 64a44969de
2 changed files with 235 additions and 0 deletions

147
test/Handtest-guide.md Normal file
View File

@ -0,0 +1,147 @@
Hand-testing guide
------------------
Compile PyTEAL sources,
```
C:\src\PriceCasterService>python teal\wormhole\pyteal\vaa-processor.py vaap.teal vaap-clear.teal
VAA Processor Program, (c) 2021-22 Randlabs Inc.
Compiling approval program...
Written to vaap.teal
Compiling clear state program...
Written to vaap-clear.teal
```
Copy compiled teal files to Sandbox (optional):
```
./sandbox copyTo /mnt/c/src/PriceCasterService/vaap.teal
Now copying /mnt/c/src/PriceCasterService/vaap.teal to Algod container in /opt/data//mnt/c/src/PriceCasterService/vaap.teal
./sandbox copyTo /mnt/c/src/PriceCasterService/vaap-clear.teal
Now copying /mnt/c/src/PriceCasterService/vaap-clear.teal to Algod container in /opt/data//mnt/c/src/PriceCasterService/vaap-clear.teal
```
Three sample guardian keys:
0x52A26Ce40F8CAa8D36155d37ef0D5D783fc614d2
K: 563d8d2fd4e701901d3846dee7ae7a92c18f1975195264d676f8407ac5976757
0x389A74E8FFa224aeAD0778c786163a7A2150768C
K: 8d97f25916a755df1d9ef74eb4dbebc5f868cb07830527731e94478cdc2b9d5f
0xB4459EA6482D4aE574305B239B4f2264239e7599
K: 9bd728ad7617c05c31382053b57658d4a8125684c0098f740a054d87ddc0e93b
Set environment variables for convenience.
```
export OWNER_ADDR=OPDM7ACAW64Q4VBWAL77Z5SHSJVZZ44V3BAN7W44U43SUXEOUENZMZYOQU
export OWNER_MNEMO='assault approve result rare float sugar power float soul kind galaxy edit unusual pretty tone tilt net range pelican avoid unhappy amused recycle abstract master'
export GUARDIAN_KEYS='52A26Ce40F8CAa8D36155d37ef0D5D783fc614d2389A74E8FFa224aeAD0778c786163a7A2150768CB4459EA6482D4aE574305B239B4f2264239e7599'
export GKEYSBASE64=`node -e "console.log(Buffer.from('$GUARDIAN_KEYS', 'hex').toString('base64'))"`
```
* Make sure to clear previously created VAA Processor Apps, example:
```
goal account info -a OPDM7ACAW64Q4VBWAL77Z5SHSJVZZ44V3BAN7W44U43SUXEOUENZMZYOQU
Created Assets:
<none>
Held Assets:
ID 14704676, Wrapped Algo Testnet, balance 0.000000 wALGO Ts
Created Apps:
ID 45231352, global state used 2/2 uints, 20/20 byte slices
Opted In Apps:
ID 14713804, local state used 1/3 uints, 1/2 byte slices
goal app delete --app-id 45231352 --from OPDM7ACAW64Q4VBWAL77Z5SHSJVZZ44V3BAN7W44U43SUXEOUENZMZYOQU -o delete.txn
algokey -t delete.txn -o delete.stxn sign -m $OWNER_MNEMO
goal clerk rawsend -f delete.sxtn
```
* Deploy and bootstrap the VAA Processor contract.
```
goal app create --creator "$OWNER_ADDR" --global-ints 4 --global-byteslices 20 --local-byteslices 0 --local-ints 0 --approval-prog vaap.teal --clear-prog vaap-clear.teal --app-arg "b64:$GKEYSBASE64" --app-arg 'int:0' --app-arg 'int:0' -o create.txn
algokey -t create.txn -o create.stxn sign -m "$OWNER_MNEMO" && goal clerk rawsend -f create.stxn
```
Check the deployed application ID according to the final TX ID.
* Compile the stateless logic with the VAA Processor ID, for example:
```
python teal\wormhole\pyteal\vaa-verify.py 45504480 vaaverify.teal
goal clerk compile vaaverify.teal
vaaverify.teal: 4H2VD6GY4L7HEOVTZBKGTO6EYFASYFOWN34ONR5HIFEE2JIJ2M5GK26SXI
```
* Set the stateless program hash with the "setvphash" appcall:
```
goal app call --app-id 45504480 --from "$OWNER_ADDR" --app-arg "str:setvphash" --app-arg "addr:4H2VD6GY4L7HEOVTZBKGTO6EYFASYFOWN34ONR5HIFEE2JIJ2M5GK26SXI" -o setvphash.txn
algokey -t setvphash.txn -o setvphash.stxn sign -m "$OWNER_MNEMO" && goal clerk rawsend -f setvphash.stxn
```
* To verify a sample VAA, you can use the testing library using Nodejs as follows:
```
Welcome to Node.js v14.17.6.
Type ".help" for more information.
> TestLib = require('./test/testlib')
{ TestLib: [class TestLib] }
> t = new TestLib.TestLib
TestLib {}
> sigkeys = ['563d8d2fd4e701901d3846dee7ae7a92c18f1975195264d676f8407ac5976757', '8d97f25916a755df1d9ef74eb4dbebc5f868cb07830527731e94478cdc2b9d5f', '9bd728ad7617c05c31382053b57658d4a8125684c0098f740a054d87ddc0e93b']
[
'563d8d2fd4e701901d3846dee7ae7a92c18f1975195264d676f8407ac5976757',
'8d97f25916a755df1d9ef74eb4dbebc5f868cb07830527731e94478cdc2b9d5f',
'9bd728ad7617c05c31382053b57658d4a8125684c0098f740a054d87ddc0e93b'
]
> t.createSignedVAA(0, sigkeys, 1, 1, 1, '0x000000000000000000000000000000000000000000000000000000000000ffff', 0, 0, '0x12345678')
'0100000000030025a2cec435380f6413e8b5d5531cd8789322a1d8bc488309bb868c33a26cc9492947b48895460d8d2261d669bcef210987cc5eeb9fa21504c3f5a9b5a0ff32df0001ee4d1a5e589b5aa0d4787eaf57ba4b41e6a54e35e8ca60a028a0f1e35db3a8ed5d901a9831272fc117f472fcd0115d31365efd575a19a28eaf5ad9be7cf5f0d90102a671b7c2af66aa6bff3337adaa7e5f196630508f85491e650cfdaccd2f67d2a605faf1c267eddaa50ac6de8d35894afce7974f14982f6173b0d020e0567f2a4a0100000001000000010001000000000000000000000000000000000000000000000000000000000000ffff00000000000000000012345678'
```
The resulting decomposed in fields VAA is:
```
01 Version
00000000 Guardian-set-index
03 Signature count
sig indexes + signatures:
00
25a2cec435380f6413e8b5d5531cd8789322a1d8bc488309bb868c33a26cc9492947b48895460d8d2261d669bcef210987cc5eeb9fa21504c3f5a9b5a0ff32df00
01
ee4d1a5e589b5aa0d4787eaf57ba4b41e6a54e35e8ca60a028a0f1e35db3a8ed5d901a9831272fc117f472fcd0115d31365efd575a19a28eaf5ad9be7cf5f0d901
02
a671b7c2af66aa6bff3337adaa7e5f196630508f85491e650cfdaccd2f67d2a605faf1c267eddaa50ac6de8d35894afce7974f14982f6173b0d020e0567f2a4a01
00000001 timestamp
00000001 nonce
0001 chain-id
000000000000000000000000000000000000000000000000000000000000ffff emitterAddress
0000000000000000 sequence
00 consistency-level
payload:
12345678
```

88
test/testlib.js Normal file
View File

@ -0,0 +1,88 @@
/**
*
* Pricecaster Testing Library.
* (c) 2021-22 Randlabs, Inc.
*
*/
const web3EthAbi = require('web3-eth-abi')
const web3Utils = require('web3-utils')
const elliptic = require('elliptic')
class TestLib {
/**
* Create a packed and signed VAA for testing.
* See https://github.com/certusone/wormhole/blob/dev.v2/design/0001_generic_message_passing.md
*
* @param {} guardianSetIndex The guardian set index
* @param {*} signers The list of private keys for signing the VAA
* @param {*} timestamp The timestamp of VAA
* @param {*} nonce The nonce.
* @param {*} emitterChainId The emitter chain identifier
* @param {*} emitterAddress The emitter chain address, prefixed with 0x
* @param {*} sequence The sequence.
* @param {*} consistencyLevel The reported consistency level
* @param {*} payload This VAA Payload hex string, prefixed with 0x
*/
createSignedVAA (guardianSetIndex,
signers,
timestamp,
nonce,
emitterChainId,
emitterAddress,
sequence,
consistencyLevel,
payload) {
const body = [
web3EthAbi.encodeParameter('uint32', timestamp).substring(2 + (64 - 8)),
web3EthAbi.encodeParameter('uint32', nonce).substring(2 + (64 - 8)),
web3EthAbi.encodeParameter('uint16', emitterChainId).substring(2 + (64 - 4)),
web3EthAbi.encodeParameter('bytes32', emitterAddress).substring(2),
web3EthAbi.encodeParameter('uint64', sequence).substring(2 + (64 - 16)),
web3EthAbi.encodeParameter('uint8', consistencyLevel).substring(2 + (64 - 2)),
payload.substr(2)
]
const hash = web3Utils.soliditySha3(web3Utils.soliditySha3('0x' + body.join('')))
let signatures = ''
for (const i in signers) {
// eslint-disable-next-line new-cap
const ec = new elliptic.ec('secp256k1')
const key = ec.keyFromPrivate(signers[i])
const signature = key.sign(hash.substr(2), { canonical: true })
const packSig = [
web3EthAbi.encodeParameter('uint8', i).substring(2 + (64 - 2)),
this.zeroPadBytes(signature.r.toString(16), 32),
this.zeroPadBytes(signature.s.toString(16), 32),
web3EthAbi.encodeParameter('uint8', signature.recoveryParam).substr(2 + (64 - 2))
]
signatures += packSig.join('')
}
const vm = [
web3EthAbi.encodeParameter('uint8', 1).substring(2 + (64 - 2)),
web3EthAbi.encodeParameter('uint32', guardianSetIndex).substring(2 + (64 - 8)),
web3EthAbi.encodeParameter('uint8', signers.length).substring(2 + (64 - 2)),
signatures,
body.join('')
].join('')
return vm
}
zeroPadBytes (value, length) {
while (value.length < 2 * length) {
value = '0' + value
}
return value
}
}
module.exports = {
TestLib
}