From e2fec1935558ad3c69ce219892b6f63ae35b4d03 Mon Sep 17 00:00:00 2001 From: nduchak Date: Fri, 17 May 2019 17:36:12 +0300 Subject: [PATCH 1/5] fix(AEP exampe): Fix contract in AEPP example --- .../connect-two-ae/aepp/src/components/Home.vue | 4 ++-- package-lock.json | 15 +++++++-------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/examples/connect-two-ae/aepp/src/components/Home.vue b/examples/connect-two-ae/aepp/src/components/Home.vue index 5c00258824..3786a83342 100644 --- a/examples/connect-two-ae/aepp/src/components/Home.vue +++ b/examples/connect-two-ae/aepp/src/components/Home.vue @@ -157,8 +157,8 @@ spendResult: null, spendError: null, contractCode: `contract Identity = - type state = () - function main(x : int) = x`, + type state = () + function main(x : int) = x`, byteCode: null, compileError: null, contractInitState: [], diff --git a/package-lock.json b/package-lock.json index d213b7bbdf..318708e39c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@aeternity/aepp-sdk", - "version": "3.2.0", + "version": "3.2.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1992,6 +1992,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "requires": { "sprintf-js": "~1.0.2" } @@ -4616,11 +4617,6 @@ "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", "dev": true }, - "esm": { - "version": "3.2.23", - "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.23.tgz", - "integrity": "sha512-p7iNpE0K3nLn1KE2O0Vz/2Gpg93U+JroVqAdHZwK7l3MmPKh4iu5CEvw1Gym9DT23BgNNvnY5wOf9vMjBFw7Ug==" - }, "esprima": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", @@ -6750,6 +6746,7 @@ "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -6758,7 +6755,8 @@ "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true } } }, @@ -9645,7 +9643,8 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true }, "sshpk": { "version": "1.14.2", From f4cdb1ef17816b8272be411498016acca6020acb Mon Sep 17 00:00:00 2001 From: nduchak Date: Mon, 20 May 2019 15:22:03 +0200 Subject: [PATCH 2/5] feat(TX VALIDATOR): Implement vm/abi validation for contract/oracle tx based on consensus protocol v --- es/tx/builder/schema.js | 13 ++++++++++--- es/tx/validator.js | 23 ++++++++++++++++++++--- test/integration/txVerification.js | 22 ++++++++++++++-------- 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/es/tx/builder/schema.js b/es/tx/builder/schema.js index b714eb4a6f..3f75d88e7e 100644 --- a/es/tx/builder/schema.js +++ b/es/tx/builder/schema.js @@ -1019,7 +1019,8 @@ const VALIDATORS = { insufficientBalanceForAmount: 'insufficientBalanceForAmount', nonceUsed: 'nonceUsed', nonceHigh: 'nonceHigh', - minGasPrice: 'minGasPrice' + minGasPrice: 'minGasPrice', + vmAndAbiVersion: 'vmAndAbiVersion' } const ERRORS = { @@ -1030,7 +1031,8 @@ const ERRORS = { insufficientBalanceForAmount: { key: 'InsufficientBalanceForAmount', type: ERROR_TYPE.WARNING, txKey: 'amount' }, nonceUsed: { key: 'NonceUsed', type: ERROR_TYPE.ERROR, txKey: 'nonce' }, nonceHigh: { key: 'NonceHigh', type: ERROR_TYPE.WARNING, txKey: 'nonce' }, - minGasPrice: { key: 'minGasPrice', type: ERROR_TYPE.ERROR, txKey: 'gasPrice' } + minGasPrice: { key: 'minGasPrice', type: ERROR_TYPE.ERROR, txKey: 'gasPrice' }, + vmAndAbiVersion: { key: 'vmAndAbiVersion', type: ERROR_TYPE.ERROR, txKey: 'ctVersion' } } export const SIGNATURE_VERIFICATION_SCHEMA = [ @@ -1075,5 +1077,10 @@ export const BASE_VERIFICATION_SCHEMA = [ () => `The gasPrice must be bigger then ${MIN_GAS_PRICE}`, VALIDATORS.minGasPrice, ERRORS.minGasPrice - ) + ), + VERIFICATION_FIELD( + ({ ctVersion, consensusProtocolVersion, txType }) => `Wrong abi/vm version, Supported is: ${PROTOCOL_VM_ABI[consensusProtocolVersion] ? JSON.stringify(PROTOCOL_VM_ABI[consensusProtocolVersion][txType]) : ' None for this protocol ' + consensusProtocolVersion}`, + VALIDATORS.vmAndAbiVersion, + ERRORS.vmAndAbiVersion + ), ] diff --git a/es/tx/validator.js b/es/tx/validator.js index a9aa5d7f37..2d9fbdf87f 100644 --- a/es/tx/validator.js +++ b/es/tx/validator.js @@ -8,7 +8,7 @@ import { encode } from '../tx/builder/helpers' import { BigNumber } from 'bignumber.js' import { BASE_VERIFICATION_SCHEMA, MIN_GAS_PRICE, OBJECT_ID_TX_TYPE, - OBJECT_TAG_SIGNED_TRANSACTION, + OBJECT_TAG_SIGNED_TRANSACTION, PROTOCOL_VM_ABI, SIGNATURE_VERIFICATION_SCHEMA } from './builder/schema' import { calculateFee, unpackTx } from './builder' @@ -53,6 +53,21 @@ const VALIDATORS = { }, minGasPrice ({ gasPrice }) { return isNaN(gasPrice) || BigNumber(gasPrice).gte(BigNumber(MIN_GAS_PRICE)) + }, + // VM/ABI version validation based on consensus protocol version + vmAndAbiVersion ({ ctVersion, consensusProtocolVersion, txType }) { + // If not contract tx + if (!ctVersion) return true + const supportedProtocol = PROTOCOL_VM_ABI[consensusProtocolVersion] + // If protocol not implemented + if (!supportedProtocol) return true + // If protocol for tx type not implemented + const txProtocol = supportedProtocol[txType] + + return !Object.entries(ctVersion) + .reduce((acc, [key, value]) => + [...acc, value === undefined ? true : txProtocol[key].includes(parseInt(value))], + []).includes(false) } } @@ -68,7 +83,8 @@ const resolveDataForBase = async (chain, { ownerPublicKey }) => { height: (await chain.api.getCurrentKeyBlockHeight()).height, balance: accountBalance, accountNonce, - ownerPublicKey + ownerPublicKey, + consensusProtocolVersion: chain.consensusProtocolVersion } } @@ -147,7 +163,8 @@ async function verifyTx ({ tx, signatures, rlpEncoded }, networkId) { const resolvedData = { minFee: calculateFee(0, OBJECT_ID_TX_TYPE[+tx.tag], { gas, params: tx, showWarning: false }), ...(await resolveDataForBase(this, { ownerPublicKey })), - ...tx + ...tx, + txType: OBJECT_ID_TX_TYPE[+tx.tag] } const signatureVerification = signatures && signatures.length ? verifySchema(SIGNATURE_VERIFICATION_SCHEMA, { diff --git a/test/integration/txVerification.js b/test/integration/txVerification.js index 17f5b85c3c..259c1c6e55 100644 --- a/test/integration/txVerification.js +++ b/test/integration/txVerification.js @@ -4,8 +4,8 @@ import { configure, ready } from '.' import { generateKeyPair } from '../../es/utils/crypto' import { BASE_VERIFICATION_SCHEMA, SIGNATURE_VERIFICATION_SCHEMA } from '../../es/tx/builder/schema' -const WARNINGS = [...SIGNATURE_VERIFICATION_SCHEMA, ...BASE_VERIFICATION_SCHEMA].reduce((acc, [msg, v, error]) => error.type === 'warning' ? [...acc, error.txKey]: acc, []) -const ERRORS = [...BASE_VERIFICATION_SCHEMA, ...SIGNATURE_VERIFICATION_SCHEMA,].reduce((acc, [msg, v, error]) => error.type === 'error' ? [...acc, error.txKey]: acc, []) +const WARNINGS = [...SIGNATURE_VERIFICATION_SCHEMA, ...BASE_VERIFICATION_SCHEMA].reduce((acc, [msg, v, error]) => error.type === 'warning' ? [...acc, error.txKey] : acc, []) +const ERRORS = [...BASE_VERIFICATION_SCHEMA, ...SIGNATURE_VERIFICATION_SCHEMA,].reduce((acc, [msg, v, error]) => error.type === 'error' ? [...acc, error.txKey] : acc, []) describe('Verify Transaction', function () { configure(this) @@ -31,12 +31,11 @@ describe('Verify Transaction', function () { absoluteTtl: true }) - const {validation} = await client.unpackAndVerify(spendTx) + const { validation } = await client.unpackAndVerify(spendTx) const warning = validation - .filter(({type}) => type === 'warning') + .filter(({ type }) => type === 'warning') .map(({ txKey }) => txKey) - JSON.stringify(WARNINGS).should.be.equals(JSON.stringify(warning)) }) it('check errors', async () => { @@ -54,12 +53,12 @@ describe('Verify Transaction', function () { // Sign using another account const signedTx = await client.signTransaction(spendTx) - const {validation} = await client.unpackAndVerify(signedTx) + const { validation } = await client.unpackAndVerify(signedTx) const error = validation - .filter(({type}) => type === 'error') + .filter(({ type, txKey }) => type === 'error') // exclude contract vm/abi, has separated test for it .map(({ txKey }) => txKey) - JSON.stringify(ERRORS.filter(e => e !== 'gasPrice')).should.be.equals(JSON.stringify(error)) + JSON.stringify(ERRORS.filter(e => e !== 'gasPrice' && e !== 'ctVersion')).should.be.equals(JSON.stringify(error)) }) it('verify transaction before broadcast', async () => { client = await ready(this) @@ -78,4 +77,11 @@ describe('Verify Transaction', function () { atLeastOneError.should.be.equal(true) } }) + it('Verify vmVersion/abiVersion for contract transactions', async () => { + // Contract create transaction with wrong abi/vm version (vm: 3, abi: 0) + const contractCreateTx = 'tx_+QSaKgGhASLDuRmSBJZv91HE219uqXb2L0adh+bilzBWUi93m5blArkD+PkD9UYCoI2tdssfNdXZOclcaOwkTNB2S/SXIVsLDi7KUoxJ3Jki+QL7+QEqoGjyZ2M4/1CIOaukd0nv+ovofvKE8gf7PZmYcBzVOIfFhG1haW64wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACg//////////////////////////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPkBy6C5yVbyizFJqfWYeqUF89obIgnMVzkjQAYrtsG9n5+Z6oRpbml0uGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////////////////////////////////+5AUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAP//////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////////////////////////////////7jMYgAAZGIAAISRgICAUX+5yVbyizFJqfWYeqUF89obIgnMVzkjQAYrtsG9n5+Z6hRiAADAV1CAUX9o8mdjOP9QiDmrpHdJ7/qL6H7yhPIH+z2ZmHAc1TiHxRRiAACvV1BgARlRAFtgABlZYCABkIFSYCCQA2ADgVKQWWAAUVlSYABSYADzW2AAgFJgAPNbWVlgIAGQgVJgIJADYAAZWWAgAZCBUmAgkANgA4FSgVKQVltgIAFRUVlQgJFQUICQUJBWW1BQgpFQUGIAAIxWhTIuMS4wgwMAAIcF9clYKwgAAAAAgxgX+IQ7msoAuGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAILnJVvKLMUmp9Zh6pQXz2hsiCcxXOSNABiu2wb2fn5nqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkansY' + const { validation } = await client.unpackAndVerify(contractCreateTx) + const vmAbiError = validation.find(el => el.txKey === 'ctVersion') + vmAbiError.msg.split(',')[0].should.be.equal('Wrong abi/vm version') + }) }) From 099efbfaaf4ad4d38da44178cbf211f0125c113f Mon Sep 17 00:00:00 2001 From: nduchak Date: Mon, 20 May 2019 15:25:02 +0200 Subject: [PATCH 3/5] fix linter --- es/tx/builder/schema.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/es/tx/builder/schema.js b/es/tx/builder/schema.js index 3f75d88e7e..dd84140131 100644 --- a/es/tx/builder/schema.js +++ b/es/tx/builder/schema.js @@ -1082,5 +1082,5 @@ export const BASE_VERIFICATION_SCHEMA = [ ({ ctVersion, consensusProtocolVersion, txType }) => `Wrong abi/vm version, Supported is: ${PROTOCOL_VM_ABI[consensusProtocolVersion] ? JSON.stringify(PROTOCOL_VM_ABI[consensusProtocolVersion][txType]) : ' None for this protocol ' + consensusProtocolVersion}`, VALIDATORS.vmAndAbiVersion, ERRORS.vmAndAbiVersion - ), + ) ] From 1bbc16c430275bb2f9d0c3635c5801a5746b2c78 Mon Sep 17 00:00:00 2001 From: nduchak Date: Mon, 20 May 2019 15:25:26 +0200 Subject: [PATCH 4/5] enable channel test --- test/integration/channel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/channel.js b/test/integration/channel.js index 205dd87557..b68d5c50b0 100644 --- a/test/integration/channel.js +++ b/test/integration/channel.js @@ -44,7 +44,7 @@ function waitForChannel (channel) { ) } -describe.skip('Channel', function () { +describe('Channel', function () { configure(this) let initiator From 007ca9271ae2168e4c50bdc221bcd023b994dea3 Mon Sep 17 00:00:00 2001 From: Michal Powaga Date: Mon, 20 May 2019 16:59:07 +0100 Subject: [PATCH 5/5] Fix channel tests --- test/integration/channel.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/integration/channel.js b/test/integration/channel.js index b68d5c50b0..0f63a667d1 100644 --- a/test/integration/channel.js +++ b/test/integration/channel.js @@ -661,7 +661,7 @@ describe('Channel', function () { ).should.be.equal(true) }) - it.skip('can create a contract and accept', async () => { + it('can create a contract and accept', async () => { initiatorCh = await Channel({ ...sharedParams, role: 'initiator', @@ -689,7 +689,7 @@ describe('Channel', function () { contractEncodeCall = (method, args) => initiator.contractEncodeCallDataAPI(identityContract, method, args) }) - it.skip('can create a contract and reject', async () => { + it('can create a contract and reject', async () => { responderShouldRejectUpdate = true const code = await initiator.compileContractAPI(identityContract) const callData = await initiator.contractEncodeCallDataAPI(identityContract, 'init', []) @@ -777,7 +777,7 @@ describe('Channel', function () { }).should.eventually.be.rejectedWith('Rejected: Call not found') }) - it.skip('can get contract state', async () => { + it('can get contract state', async () => { const result = await initiatorCh.getContractState(contractAddress) result.should.eql({ contract: {