Working VAA verification test.

Change-Id: Ib44e96ce8979161cdf703b1c4c92742cdc3e9cae
This commit is contained in:
Hernán Di Pietro 2021-12-09 10:40:10 -03:00 committed by Leopold Schabel
parent e68b9b2c7b
commit 98d8912a12
2 changed files with 76 additions and 54 deletions

View File

@ -5,7 +5,6 @@
*
*/
const { LogicSigAccount } = require('algosdk')
const algosdk = require('algosdk')
const fs = require('fs')
// eslint-disable-next-line camelcase
@ -24,6 +23,7 @@ class PricecasterLib {
this.ownerAddr = ownerAddr
this.minFee = 1000
this.groupTx = []
this.lsigs = {}
/** Overrides the default VAA processor approval program filename
* @param {string} filename New file name to use.
@ -518,7 +518,6 @@ class PricecasterLib {
*/
this.beginTxGroup = function () {
this.groupTx = []
this.lsigs = {}
}
/**
@ -551,34 +550,50 @@ class PricecasterLib {
/**
* @param {*} sender The sender account.
* @param {function} signCallback The sign callback routine.
* @param {*} programBytes Compiled program bytes.
* @param {*} sigSubsets The signature subsets i..j for logicsig arguments.
* @returns Transaction id.
*/
this.commitTxGroupSignedByLogic = async function () {
this.commitVerifyTxGroup = async function (programBytes, sigSubsets) {
algosdk.assignGroupID(this.groupTx)
const signedGroup = []
let i = 0
for (const tx of this.groupTx) {
const stxn = algosdk.signLogicSigTransaction(tx, this.lsigs[tx.txID])
const lsig = new algosdk.LogicSigAccount(programBytes, [Buffer.from(sigSubsets[i++], 'hex')])
const stxn = algosdk.signLogicSigTransaction(tx, lsig)
signedGroup.push(stxn.blob)
}
// Save transaction for debugging.
// fs.unlinkSync('signedgroup.stxn')
// for (let i = 0; i < signedGroup.length; ++i) {
// fs.appendFileSync('signedgroup.stxn', signedGroup[i])
// }
// const dr = await algosdk.createDryrun({
// client: algodClient,
// txns: drtxns,
// sources: [new algosdk.modelsv2.DryrunSource('lsig', fs.readFileSync(vaaVerifyStatelessProgramFilename).toString('utf8'))]
// })
// // const drobj = await algodClient.dryrun(dr).do()
// fs.writeFileSync('dump.dr', algosdk.encodeObj(dr.get_obj_for_encoding(true)))
// Submit the transaction
const tx = await this.algodClient.sendRawTransaction(signedGroup).do()
this.groupTx = []
this.lsigs = {}
return tx.txId
}
/**
* VAA Processor: Add a verification step to a transaction group.
* @param {*} sender The sender account (typically the VAA verification stateless program)
* @param {*} payload The VAA payload as Uint8Array.
* @param {*} payload The VAA payload.
* @param {*} gksubset An hex string containing the keys for the guardian subset in this step.
* @param {*} totalguardians The total number of known guardians.
* @param {LogicSigAccount} lsig The logic sig account that will sign this transaction
*/
this.addVerifyTx = function (sender, params, payload, gksubset, totalguardians, lsig) {
this.addVerifyTx = function (sender, params, payload, gksubset, totalguardians) {
const appArgs = []
appArgs.push(new Uint8Array(Buffer.from('verify')),
new Uint8Array(Buffer.from(gksubset.join(''), 'hex')),
@ -589,9 +604,9 @@ class PricecasterLib {
this.appId,
appArgs, undefined, undefined, undefined,
new Uint8Array(payload))
this.groupTx.push(tx)
this.lsigs[tx.txID] = lsig
return tx.txID()
}
}
}

View File

@ -8,9 +8,8 @@ chai.use(require('chai-as-promised'))
const spawnSync = require('child_process').spawnSync
const fs = require('fs')
const TestLib = require('../test/testlib.js')
const { assert } = require('console')
const { verify } = require('crypto')
const { makePaymentTxnWithSuggestedParams, mnemonicToSecretKey } = require('algosdk')
const { makePaymentTxnWithSuggestedParams } = require('algosdk')
const { doesNotMatch } = require('assert')
const testLib = new TestLib.TestLib()
let pclib
let algodClient
@ -25,25 +24,26 @@ SIGNATURES[OWNER_ADDR] = algosdk.mnemonicToSecretKey(OWNER_MNEMO)
SIGNATURES[OTHER_ADDR] = algosdk.mnemonicToSecretKey(OTHER_MNEMO)
const gkeys = [
'13947Bd48b18E53fdAeEe77F3473391aC727C638',
'F18AbBac073741DD0F002147B735Ff642f3D113F',
'9925A94DC043D0803f8ef502D2dB15cAc9e02D76',
'9e4EC2D92af8602bCE74a27F99A836f93C4a31E4',
'9C40c4052A3092AfB8C99B985fcDfB586Ed19c98',
'B86020cF1262AA4dd5572Af76923E271169a2CA7',
'1937617fE1eD801fBa14Bd8BB9EDEcBA7A942FFe',
'9475b8D45DdE53614d92c779787C27fE2ef68752',
'15A53B22c28AbC7B108612146B6aAa4a537bA305',
'63842657C7aC7e37B04FBE76b8c54EFe014D04E1',
'948ca1bBF4B858DF1A505b4C69c5c61bD95A12Bd',
'A6923e2259F8B5541eD18e410b8DdEE618337ff0',
'F678Daf4b7f2789AA88A081618Aa966D6a39e064',
'8cF31021838A8B3fFA43a71a50609877846f9E6d',
'eB15bCF2ae4f957012330B4741ecE3242De96184',
'cc3766a03e4faec44Bda7a46D9Ea2A9D124e9Bf8',
'841f499Ba89a6a8E9dD273BAd82Beb175094E5d7',
'f5F2b82576e6CA17965dee853d08bbB471FA2433',
'2bC2B1204599D4cA0d4Dde4a658a42c4dD13103a'
'52A26Ce40F8CAa8D36155d37ef0D5D783fc614d2',
'389A74E8FFa224aeAD0778c786163a7A2150768C',
'B4459EA6482D4aE574305B239B4f2264239e7599',
'072491bd66F63356090C11Aae8114F5372aBf12B',
'51280eA1fd2B0A1c76Ae29a7d54dda68860A2bfF',
'fa9Aa60CfF05e20E2CcAA784eE89A0A16C2057CB',
'e42d59F8FCd86a1c5c4bA351bD251A5c5B05DF6A',
'4B07fF9D5cE1A6ed58b6e9e7d6974d1baBEc087e',
'c8306B84235D7b0478c61783C50F990bfC44cFc0',
'C8C1035110a13fe788259A4148F871b52bAbcb1B',
'58A2508A20A7198E131503ce26bBE119aA8c62b2',
'8390820f04ddA22AFe03be1c3bb10f4ba6CF94A0',
'1FD6e97387C34a1F36DE0f8341E9D409E06ec45b',
'255a41fC2792209CB998A8287204D40996df9E54',
'bA663B12DD23fbF4FbAC618Be140727986B3BBd0',
'79040E577aC50486d0F6930e160A5C75FD1203C6',
'3580D2F00309A9A85efFAf02564Fc183C0183A96',
'3869795913D3B6dBF3B24a1C7654672c69A23c35',
'1c0Cc52D7673c52DE99785741344662F5b2308a0'
]
const sigkeys = [
'563d8d2fd4e701901d3846dee7ae7a92c18f1975195264d676f8407ac5976757',
@ -83,16 +83,24 @@ function signCallback (sender, tx) {
return txSigned
}
async function getTxParams () {
const params = await algodClient.getTransactionParams().do()
params.fee = 1000
params.flatFee = true
return params
}
describe('VAA Processor Smart-contract Tests', function () {
let appId
before(async function () {
algodClient = new algosdk.Algodv2('', 'https://api.testnet.algoexplorer.io', '')
// algodClient = new algosdk.Algodv2('', 'https://api.betanet.algoexplorer.io', '')
algodClient = new algosdk.Algodv2('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'http://localhost', '4001')
pclib = new PricecasterLib.PricecasterLib(algodClient)
const ownerAcc = algosdk.mnemonicToSecretKey(OWNER_MNEMO)
const ownerAccInfo = await algodClient.accountInformation(ownerAcc.addr).do()
expect(ownerAccInfo.amount).to.be.at.least(algosdk.algosToMicroalgos(1), 'Owner must have enough funding to run tests')
expect(ownerAccInfo.amount).to.be.at.least(algosdk.algosToMicroalgos(10), 'Owner must have enough funding (10 ALGO) to run tests')
console.log('Clearing accounts of all previous apps...')
const appsTo = await tools.readCreatedApps(algodClient, OWNER_ADDR)
@ -144,7 +152,7 @@ describe('VAA Processor Smart-contract Tests', function () {
verifyProgramHash = compiledVerifyProgram.hash
console.log(' - Stateless program: ', verifyProgramHash)
let txid = await pclib.setVAAVerifyProgramHash(OWNER_ADDR, verifyProgramHash, signCallback)
const txid = await pclib.setVAAVerifyProgramHash(OWNER_ADDR, verifyProgramHash, signCallback)
await pclib.waitForTransactionResponse(txid)
const vphstate = await tools.readAppGlobalStateByKey(algodClient, appId, OWNER_ADDR, 'vphash')
expect(vphstate).to.equal(verifyProgramHash)
@ -180,16 +188,18 @@ describe('VAA Processor Smart-contract Tests', function () {
const badSize = 1 + Math.ceil(gscount / vssize)
const params = await getTxParams()
const vaa = testLib.createSignedVAA(0, sigkeys, 1, 1, 1, PYTH_EMITTER, 0, 0, PYTH_PAYLOAD)
pclib.beginTxGroup()
const vaaBody = Buffer.from(vaa.substr(12 + sigkeys.length * 132), 'hex')
const signatures = vaa.substr(12, sigkeys.length * 132)
pclib.beginTxGroup()
const sigSubsets = []
for (let i = 0; i < badSize; i++) {
const sigSubset = sigkeys.slice(vssize * i, i < badSize - 1 ? ((vssize * i) + vssize) : undefined)
sigSubsets.push(signatures.slice(i * 132 * vssize, i < badSize - 1 ? ((i * 132 * vssize) + 132 * vssize) : undefined))
const keySubset = gkeys.slice(vssize * i, i < badSize - 1 ? ((vssize * i) + vssize) : undefined)
const lsig = new algosdk.LogicSigAccount(compiledVerifyProgram.compiledBytes, [new Uint8Array(Buffer.from(sigSubset.join(''), 'hex'))])
pclib.addVerifyTx(verifyProgramHash, params, vaaBody, keySubset, gscount, lsig)
pclib.addVerifyTx(verifyProgramHash, params, vaaBody, keySubset, gscount)
}
await expect(pclib.commitTxGroupSignedByLogic()).to.be.rejectedWith('Bad Request')
await expect(pclib.commitVerifyTxGroup(compiledVerifyProgram.compiledBytes, sigSubsets)).to.be.rejectedWith('Bad Request')
})
it('Must reject incorrect argument count for verify call', async function () {
@ -218,16 +228,19 @@ describe('VAA Processor Smart-contract Tests', function () {
const groupSize = Math.ceil(gscount / vssize)
const params = await getTxParams()
const vaa = testLib.createSignedVAA(0, sigkeys, 1, 1, 1, PYTH_EMITTER, 0, 0, PYTH_PAYLOAD)
pclib.beginTxGroup()
const vaaBody = Buffer.from(vaa.substr(12 + sigkeys.length * 132), 'hex')
const signatures = vaa.substr(12, sigkeys.length * 132)
pclib.beginTxGroup()
const sigSubsets = []
for (let i = 0; i < groupSize; i++) {
const sigSubset = sigkeys.slice(vssize * i, i < groupSize - 1 ? ((vssize * i) + vssize) : undefined)
const keySubset = gkeys.slice(vssize * i, i < groupSize - 1 ? ((vssize * i) + vssize) : undefined)
const lsig = new algosdk.LogicSigAccount(compiledVerifyProgram.compiledBytes, [new Uint8Array(Buffer.from(sigSubset.join(''), 'hex'))])
pclib.addVerifyTx(verifyProgramHash, params, vaaBody, keySubset, gscount, lsig)
const st = vssize * i
const keySubset = gkeys.slice(st, i < groupSize - 1 ? st + vssize : undefined)
sigSubsets.push(signatures.slice(i * 132 * vssize, i < groupSize - 1 ? ((i * 132 * vssize) + 132 * vssize) : undefined))
pclib.addVerifyTx(verifyProgramHash, params, vaaBody, keySubset, gscount)
}
await pclib.commitTxGroupSignedByLogic()
await pclib.commitVerifyTxGroup(compiledVerifyProgram.compiledBytes, sigSubsets)
await pclib.waitForConfirmation(tx)
})
it('Must verify and handle governance VAA', async function () {
@ -260,9 +273,3 @@ describe('VAA Processor Smart-contract Tests', function () {
})
})
async function getTxParams () {
const params = await algodClient.getTransactionParams().do()
params.fee = 1000
params.flatFee = true
return params
}