From 9096ca58f95e90f8c47ade846ed903444cbf35ba Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 17 Dec 2019 13:11:14 +0100 Subject: [PATCH 1/4] Add previous period to proofs and roots if present. --- lib/period.js | 17 +++++++++++++--- lib/period.spec.js | 48 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/lib/period.js b/lib/period.js index 5c33319..f4c99b7 100644 --- a/lib/period.js +++ b/lib/period.js @@ -64,6 +64,7 @@ export default class Period { } } + // helpful: https://docs.google.com/drawings/d/13oFjua-v_E_yaFYUbralluI-EysgtTaZb_sSgGbxG_A periodData() { if (typeof this.slotId === 'undefined' || !this.ownerAddr) { throw Error('period is missing validator data to create period root.'); @@ -81,11 +82,20 @@ export default class Period { } validatorRoot.copy(rootBuf, 32); const casRoot = keccak256(rootBuf); - + + // make metaRoot + let metaRoot = Buffer.alloc(32, 0); + if (this.prevHash) { + rootBuf = Buffer.alloc(64, 0); + toBuffer(this.prevHash).copy(rootBuf, 32); + metaRoot = keccak256(rootBuf); + } + // make consensusRoot const blocksRoot = this.getMerkleTree().getRoot(); rootBuf = Buffer.alloc(64, 0); blocksRoot.copy(rootBuf); + metaRoot.copy(rootBuf, 32); const consensusRoot = keccak256(rootBuf); // make period root @@ -96,6 +106,7 @@ export default class Period { return { casRoot, periodRoot, + metaRoot }; } @@ -130,10 +141,10 @@ export default class Period { blockProof.forEach(elem => proof.push(elem)); // add extensible proof structure - const { casRoot, periodRoot } = this.periodData(); + const { casRoot, periodRoot, metaRoot } = this.periodData(); // update the proof - proof.push(bufferToHex(Buffer.alloc(32, 0))); + proof.push(bufferToHex(metaRoot)); proof.push(bufferToHex(casRoot)); proof[0] = periodRoot; return proof; diff --git a/lib/period.spec.js b/lib/period.spec.js index f4dbebb..826e89b 100644 --- a/lib/period.spec.js +++ b/lib/period.spec.js @@ -243,6 +243,54 @@ describe('periods', () => { done(); }); + it('should allow to get proof from period with prevPeriod.', (done) => { + const prevTx = '0x7777777777777777777777777777777777777777777777777777777777777777'; + const value = 99000000; + const color = 1337; + const transfer = Tx.transfer( + [new Input(new Outpoint(prevTx, 0))], + [new Output(value / 2, ADDR, color), new Output(value / 2, ADDR, color)], + ); + transfer.sign([PRIV]); + + const blocks = []; + let block; + for (let i = 0; i < 31; i++) { + if (i % 2) { + block = new Block(i).addTx(Tx.deposit(i, value, ADDR, color)); + blocks.push(block); + } else { + blocks.push(new Block(i)); + } + } + block = new Block(31).addTx(transfer); + blocks.push(block); + + const period = new Period("'0x8b04de057fe524a3118eb7c8e14a2e55323c67fd7b6080583d1047b700b2d674'", blocks); + period.setValidatorData(slotId, ADDR); + const proof = period.proof(transfer); + expect(proof).to.eql([ + '0xec7034f5cf812842edc14044fa453c60958c90063a31b623cf44f50402c14938', + '0x300800d0000000000000003e0000000003127777777777777777777777777777', + '0x77777777777777777777777777777777777700c2b5d5b0953f40dd9bbc5e534f', + '0x2db3d4847d897b6615103a157bd69c640490c07945dc613cd500f12a009aad63', + '0x1c530264507c1f5a8591ddc053bd5dc87bcf291b000000000000000000000000', + '0x0000000000000000000000000000000002f34f60053982e8c6cf42c8d1ff9594', + '0xb17a3f50e94a12cc860f00000000000000000000000000000000000000000000', + '0x00000000000002f34f60053982e8c6cf42c8d1ff9594b17a3f50e94a12cc860f', + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x7d63e2113d90d4316fd6fd3f25837061858b8401ac1331295e922a21fe5e9579', + '0x04fc4e57a69f3fc7b76e12212f843a49837b36dd7280539e52b12f303d1355c4', + '0x3d5087be87669128a31314d9a3cf9d52af2e6dc96132eef574f84ed4ba260b2c', + '0x7e85398f3d5b052c378cc3d2a15209a7e8fbaf2a2b65349f80f5faf033ddf172', + '0x4f23fef08ddaf966bed1b1a57541da6c5a6779fbb51c2d70e4674397ae33712f', + '0x03bfe7f7bc5ba5d5119009b30c5eb918b6ab5050af363b4c3844ec5565e4a604' + ]); + done(); + }); + + describe('periodForBlockRange', () => { it('should create period for a given block range'); }); From dcde9aa4937e1bfd7f6d1b27fb9b027e069539eb Mon Sep 17 00:00:00 2001 From: Jan Date: Fri, 20 Dec 2019 17:01:13 +0100 Subject: [PATCH 2/4] Add ability to produce and verify prevPeriod proofs. Also fix tests and fix backwards compatibility issue. --- lib/period.js | 44 +++++++++++++++++++++++++++++++++++++++++++- lib/period.spec.js | 37 ++++++++++--------------------------- 2 files changed, 53 insertions(+), 28 deletions(-) diff --git a/lib/period.js b/lib/period.js index f4c99b7..d9c25c2 100644 --- a/lib/period.js +++ b/lib/period.js @@ -64,6 +64,10 @@ export default class Period { } } + usePrevPeriod() { + this.usePrev = true; + } + // helpful: https://docs.google.com/drawings/d/13oFjua-v_E_yaFYUbralluI-EysgtTaZb_sSgGbxG_A periodData() { if (typeof this.slotId === 'undefined' || !this.ownerAddr) { @@ -85,7 +89,7 @@ export default class Period { // make metaRoot let metaRoot = Buffer.alloc(32, 0); - if (this.prevHash) { + if (this.usePrev) { rootBuf = Buffer.alloc(64, 0); toBuffer(this.prevHash).copy(rootBuf, 32); metaRoot = keccak256(rootBuf); @@ -115,6 +119,44 @@ export default class Period { return periodRoot; } + prevPeriodProof() { + if (!this.usePrev) { + throw Error('not set to use prev period in proofs'); + } + + const { casRoot, metaRoot } = this.periodData(); + + const proof = []; + + // fees hash + proof.push(bufferToHex(Buffer.alloc(32, 0))); + proof.push(this.prevHash); + proof.push(this.merkleRoot()); + proof.push(bufferToHex(casRoot)); + + return proof; + } + + // returns current period + static verifyPrevPeriodProof(proof) { + let result; + result = Buffer.alloc(64, 0); + // fees hash + toBuffer(proof[0]).copy(result); + // prevPeriod + toBuffer(proof[1]).copy(result, 32); + const metaRoot = keccak256(result); + result = Buffer.alloc(64, 0); + //blocks root + toBuffer(proof[2]).copy(result); + metaRoot.copy(result, 32); + const consensusRoot = keccak256(result); + result = Buffer.alloc(64, 0); + toBuffer(consensusRoot).copy(result); + toBuffer(proof[3]).copy(result, 32); + return bufferToHex(keccak256(result)); + } + proof(tx) { let periodPos = -1; for (let i = 0; i < this.blockList.length; i++) { diff --git a/lib/period.spec.js b/lib/period.spec.js index 826e89b..b6c26e0 100644 --- a/lib/period.spec.js +++ b/lib/period.spec.js @@ -255,38 +255,21 @@ describe('periods', () => { const blocks = []; let block; - for (let i = 0; i < 31; i++) { - if (i % 2) { - block = new Block(i).addTx(Tx.deposit(i, value, ADDR, color)); - blocks.push(block); - } else { - blocks.push(new Block(i)); - } + for (let i = 0; i < 30; i++) { + block = new Block(i).addTx(Tx.deposit(i, value, ADDR, color)); + blocks.push(block); } block = new Block(31).addTx(transfer); blocks.push(block); - const period = new Period("'0x8b04de057fe524a3118eb7c8e14a2e55323c67fd7b6080583d1047b700b2d674'", blocks); + const period = new Period("0x8b04de057fe524a3118eb7c8e14a2e55323c67fd7b6080583d1047b700b2d674", blocks); period.setValidatorData(slotId, ADDR); - const proof = period.proof(transfer); - expect(proof).to.eql([ - '0xec7034f5cf812842edc14044fa453c60958c90063a31b623cf44f50402c14938', - '0x300800d0000000000000003e0000000003127777777777777777777777777777', - '0x77777777777777777777777777777777777700c2b5d5b0953f40dd9bbc5e534f', - '0x2db3d4847d897b6615103a157bd69c640490c07945dc613cd500f12a009aad63', - '0x1c530264507c1f5a8591ddc053bd5dc87bcf291b000000000000000000000000', - '0x0000000000000000000000000000000002f34f60053982e8c6cf42c8d1ff9594', - '0xb17a3f50e94a12cc860f00000000000000000000000000000000000000000000', - '0x00000000000002f34f60053982e8c6cf42c8d1ff9594b17a3f50e94a12cc860f', - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x7d63e2113d90d4316fd6fd3f25837061858b8401ac1331295e922a21fe5e9579', - '0x04fc4e57a69f3fc7b76e12212f843a49837b36dd7280539e52b12f303d1355c4', - '0x3d5087be87669128a31314d9a3cf9d52af2e6dc96132eef574f84ed4ba260b2c', - '0x7e85398f3d5b052c378cc3d2a15209a7e8fbaf2a2b65349f80f5faf033ddf172', - '0x4f23fef08ddaf966bed1b1a57541da6c5a6779fbb51c2d70e4674397ae33712f', - '0x03bfe7f7bc5ba5d5119009b30c5eb918b6ab5050af363b4c3844ec5565e4a604' - ]); + const periodAfter = new Period(period.periodRoot(), blocks); + periodAfter.setValidatorData(slotId, ADDR); + periodAfter.usePrevPeriod(); + + const proof = periodAfter.prevPeriodProof(); + expect(Period.verifyPrevPeriodProof(proof)).to.eql(periodAfter.periodRoot()); done(); }); From ded6ec8c5c44a7ba8b0a7fb21d3d46f2662e2da1 Mon Sep 17 00:00:00 2001 From: Kosta Korenkov Date: Mon, 23 Dec 2019 18:07:59 +0200 Subject: [PATCH 3/4] chore: rework Period object constructor (#167) * chore: rework Period object constructor 1. Set `usePrev` by default. BREAKING change 2. Accept optional third arguments of `PeriodOptions` type: allows to set validator data and set `usePrev` to false for legacy proofs. * docs: add period hashing schema --- index.d.ts | 19 ++++++++++---- lib/helpers.js | 23 +++++++++-------- lib/helpers.spec.js | 19 +++++++++----- lib/period.js | 61 ++++++++++++++++++++++++++++++++++++--------- lib/period.spec.js | 54 +++++++++++++++++++++++++-------------- 5 files changed, 123 insertions(+), 53 deletions(-) diff --git a/index.d.ts b/index.d.ts index 65ef5f2..6131c00 100644 --- a/index.d.ts +++ b/index.d.ts @@ -254,15 +254,24 @@ declare module "leap-core" { public static from(height: number, timestamp: number, txList: LeapTransaction[]): Block; } + type PeriodOptions = { + validatorData?: { + slotId: number; + ownerAddr: string | Buffer | number; + casBitmap?: string | Buffer | number; + }; + excludePrevHashFromProof?: Boolean; + }; + class Period { - constructor(prevHash: string, blocks: Array); + constructor(prevHash: string, blocks: Array, opts?: PeriodOptions); addBlock(block: Block): Period; getMerkleTree(): MerkleTree; merkleRoot(): string; proof(tx: Tx): Proof; static periodBlockRange(blockNumber: number): [number, number]; - static periodForBlockRange(plasma: ExtendedWeb3, startBlock: number, endBlock: number): Promise; - static periodForTx(plasma: ExtendedWeb3, tx: LeapTransaction): Promise; + static periodForBlockRange(plasma: ExtendedWeb3, startBlock: number, endBlock: number, periodOpts?: PeriodOptions): Promise; + static periodForTx(plasma: ExtendedWeb3, tx: LeapTransaction, periodOpts?: PeriodOptions): Promise; } export type Proof = string[]; @@ -331,7 +340,7 @@ declare module "leap-core" { }; type PeriodData = { - validatorAddress: string; + ownerAddr: string; slotId: number; casBitmap?: string; periodStart?: number; @@ -360,7 +369,7 @@ declare module "leap-core" { export function periodBlockRange(blockNumber: number): [number, number]; export function getTxWithYoungestBlock(txs: LeapTransaction[]): InputTx; export function getYoungestInputTx(plasma: ExtendedWeb3, tx: Tx): Promise; - export function getProof(plasma: ExtendedWeb3, tx: LeapTransaction, fallbackPeriodData?: PeriodData): Promise; + export function getProof(plasma: ExtendedWeb3, tx: LeapTransaction, periodOpts?: PeriodOptions): Promise; // Depending on plasma instance, resolves to either Web3's Transaction or Ethers' TransactionReceipt export function sendSignedTransaction(plasma: ExtendedWeb3, tx: string): Promise; export function simulateSpendCond(plasma: ExtendedWeb3, tx: Tx): Promise; diff --git a/lib/helpers.js b/lib/helpers.js index 54c5f7f..233428c 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -213,25 +213,26 @@ export function getYoungestInputTx(plasma, tx) { * * @param {ExtendedWeb3|LeapProvider} plasma instance of Leap Web3 * @param {LeapTransaction} tx + * @param {PeriodOpts} periodOpts — options for cosntructed Period as defined in Period constructor * @returns {Promise} promise that resolves to period inclusion proof */ -export function getProof(plasma, tx, fallbackPeriodData) { - return Promise.all([ - Period.periodForTx(plasma, tx), - plasma.getPeriodByBlockHeight(tx.blockNumber) - ]).then(([period, periodData]) => { - const [periodDataObj] = periodData || [fallbackPeriodData]; - if (!periodData || !periodData.length) { +export function getProof(plasma, tx, periodOpts = {}) { + return plasma.getPeriodByBlockHeight(tx.blockNumber) + .then(periodData => { + if (periodData && periodData.length) { + Object.assign(periodOpts, { + validatorData: periodData[0], + }); + } else { const msg = `No period data for the given tx. Height: ${tx.blockNumber}`; - if (!fallbackPeriodData) { + if (!periodOpts.validatorData) { throw new Error(msg); } else { console.warn(msg, 'Using fallback values'); // eslint-disable-line no-console } } - const { slotId, validatorAddress, casBitmap } = periodDataObj; - - period.setValidatorData(slotId, validatorAddress, casBitmap); + return Period.periodForTx(plasma, tx, periodOpts); + }).then((period) => { return period.proof(Tx.fromRaw(tx.raw)); }); } diff --git a/lib/helpers.spec.js b/lib/helpers.spec.js index f423301..9950f00 100644 --- a/lib/helpers.spec.js +++ b/lib/helpers.spec.js @@ -180,7 +180,7 @@ describe('helpers', () => { const transactions = n === 4 ? [{ raw: deposit1.hex() }] : []; return { number: n, timestamp: 123, transactions }; }, - getPeriodByBlockHeight: () => null, + getPeriodByBlockHeight: () => Promise.resolve(null), }; expect( @@ -199,15 +199,18 @@ describe('helpers', () => { const transactions = n === 4 ? [{ raw: deposit1.hex() }] : []; return { number: n, timestamp: 123, transactions }; }, - getPeriodByBlockHeight: () => null, + getPeriodByBlockHeight: () => Promise.resolve(null), }; - const fallbackData = { slotId: 0, validatorAddress: ADDR_1 }; + const periodOpts = { + validatorData: { slotId: 0, ownerAddr: ADDR_1 }, + excludePrevHashFromProof: true, + }; const proof = getProof( plasma, { blockNumber: 4, raw: deposit1.hex() }, - fallbackData + periodOpts ); return expect(proof).to.eventually.eql([ '0x29aa1b0213471dbf84175e8f688e5a63c2e5724ad6bc581a10b9521f4b8a6083', @@ -240,11 +243,15 @@ describe('helpers', () => { }, getPeriodByBlockHeight: n => { expect(n).to.be.equal(4); - return [{ slotId: 0, validatorAddress: ADDR_1, casBitmap }]; + return Promise.resolve([{ slotId: 0, ownerAddr: ADDR_1, casBitmap }]); }, }; - const proof = getProof(plasma, { blockNumber: 4, raw: deposit1.hex() }); + const proof = getProof( + plasma, + { blockNumber: 4, raw: deposit1.hex() }, + { excludePrevHashFromProof: true } + ); return expect(proof).to.eventually.eql([ '0x6eefe22ae29bc837d66e743334a70ecc19635c3c9ef31d4c2987b337b9d015c6', '0x4404003c00000000000000080000000000000000000000000000000000000000', diff --git a/lib/period.js b/lib/period.js index d9c25c2..dc2744a 100644 --- a/lib/period.js +++ b/lib/period.js @@ -15,13 +15,40 @@ import Util from './util'; import { BLOCKS_PER_PERIOD } from './constants'; export default class Period { - constructor(prevHash, blocks) { + + /** + * + * Create a Period object linked to the previous Period via `prevHash` and + * containing given list of `blocks`. + * + * Optional parameters can be given via `opts` argument. Format as follows: + * + * type PeriodOptions = { + * validatorData?: { + * slotId: number; + * ownerAddr: string | Buffer | number; + * casBitmap?: string | Buffer | number; + * }; + * excludePrevHashFromProof?: Boolean; + * }; + * + * @param {string} prevHash - previous period root hash + * @param {Array} blocks - array of blocks to include in the period + * @param {PeriodOptions} opts - options defined as above. Default {} + */ + constructor(prevHash, blocks, opts = {}) { this.prevHash = prevHash; this.blockList = []; this.blockHashList = []; + this.usePrev = !opts.excludePrevHashFromProof; if (blocks) { blocks.forEach(block => this.addBlock(block)); } + + const { slotId, ownerAddr, casBitmap } = opts.validatorData || {}; + if ((slotId || slotId === 0) && ownerAddr) { + this.setValidatorData(slotId, ownerAddr, casBitmap); + } } addBlock(block) { @@ -64,11 +91,19 @@ export default class Period { } } - usePrevPeriod() { - this.usePrev = true; - } - - // helpful: https://docs.google.com/drawings/d/13oFjua-v_E_yaFYUbralluI-EysgtTaZb_sSgGbxG_A + // + /** + * helpful: https://docs.google.com/drawings/d/13oFjua-v_E_yaFYUbralluI-EysgtTaZb_sSgGbxG_A + * + * period root + * / \ + * consensus root CAS root + * / \ / \ + * blocks root meta root CAS bitmap validator root + * / \ / \ + * fees hash prevPeriodHash * slotId 0x0 + * * ownerAddr + */ periodData() { if (typeof this.slotId === 'undefined' || !this.ownerAddr) { throw Error('period is missing validator data to create period root.'); @@ -124,7 +159,7 @@ export default class Period { throw Error('not set to use prev period in proofs'); } - const { casRoot, metaRoot } = this.periodData(); + const { casRoot } = this.periodData(); const proof = []; @@ -147,7 +182,7 @@ export default class Period { toBuffer(proof[1]).copy(result, 32); const metaRoot = keccak256(result); result = Buffer.alloc(64, 0); - //blocks root + // blocks root toBuffer(proof[2]).copy(result); metaRoot.copy(result, 32); const consensusRoot = keccak256(result); @@ -212,9 +247,10 @@ export default class Period { * @param {ExtendedWeb3} plasma instance of Leap Web3 or Leap Ethers * @param {Number} startBlock first block to include in the period * @param {Number} endBlock last block to include in the period + * @param {PeriodOpts} periodOpts options for Period object as defined in Period constructor * @returns {Period} period */ - static periodForBlockRange(plasma, startBlock, endBlock) { + static periodForBlockRange(plasma, startBlock, endBlock, periodOpts = {}) { return Promise.all( Util.range(startBlock, endBlock).map(n => (plasma.eth || plasma).getBlock(n, true)), ).then((blocks) => { @@ -223,7 +259,7 @@ export default class Period { .map(({ number, timestamp, transactions }) => Block.from(number, timestamp, transactions), ); - return new Period(null, blockList); + return new Period(null, blockList, periodOpts); }); } @@ -232,12 +268,13 @@ export default class Period { * * @param {ExtendedWeb3} plasma instance of Leap Web3 * @param {Transaction} tx transaction to create {Period} for + * @param {PeriodOpts} periodOpts options for Period object as defined in Period constructor * @returns {Period} period */ - static periodForTx(plasma, tx) { + static periodForTx(plasma, tx, periodOpts = {}) { const { blockNumber } = tx; const [startBlock, endBlock] = Period.periodBlockRange(blockNumber); - return Period.periodForBlockRange(plasma, startBlock, endBlock); + return Period.periodForBlockRange(plasma, startBlock, endBlock, periodOpts); } } diff --git a/lib/period.spec.js b/lib/period.spec.js index b6c26e0..4ff4059 100644 --- a/lib/period.spec.js +++ b/lib/period.spec.js @@ -10,6 +10,20 @@ const PRIV = '0x94890218f2b0d04296f30aeafd13655eba4c5bbf1770273276fee52cbe3f2cb4 const ADDR = '0x82e8c6cf42c8d1ff9594b17a3f50e94a12cc860f'; const slotId = 4; +const validatorData = { + slotId, + ownerAddr: ADDR +}; + +/** + * Excluding prevHash from period proof as it was in the original version, + * so that we can verify proofs for older periods + */ +const legacyOpts = { + validatorData, + excludePrevHashFromProof: true +} + describe('periods', () => { it('should allow to get proof from period.', (done) => { const height = 123; @@ -24,8 +38,7 @@ describe('periods', () => { const block2 = new Block(height + 1); block2.addTx(Tx.deposit(2, value * 2, ADDR, color)); - const period = new Period(null, [block1, block2]); - period.setValidatorData(slotId, ADDR); + const period = new Period(null, [block1, block2], legacyOpts); const proof = period.proof(deposit1); expect(proof).to.eql([ period.periodRoot(), @@ -52,8 +65,7 @@ describe('periods', () => { const block2 = new Block(2); block2.addTx(deposit2); - const period = new Period(null, [block1]); - period.setValidatorData(slotId, ADDR); + const period = new Period(null, [block1], legacyOpts); expect( () => period.proof(deposit2) ).to.throw('tx not in this period'); @@ -73,8 +85,14 @@ describe('periods', () => { const block2 = new Block(height + 1); block2.addTx(Tx.deposit(2, value * 2, ADDR, color)); - const period = new Period(null, [block1, block2]); - period.setValidatorData(slotId, ADDR, PRIV); + const period = new Period(null, [block1, block2], { + validatorData: { + slotId, + ownerAddr: ADDR, + casBitmap: '0x4000000000000000000000000000000000000000000000000000000000000000' + }, + excludePrevHashFromProof: true + }); const proof = period.proof(deposit1); expect(proof).to.eql([ period.periodRoot(), @@ -84,7 +102,7 @@ describe('periods', () => { '0x430ce01c495ecaa94a3b4b3154906343e755b7f9e51bf3403b09dd932a0b18ee', '0x77bc0389ba07196637b929d5347b1453f3294175e9015e13b5e3c5fb19f3c0f4', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x492a381524e41b7bf6f1eef65ff5057dbfacea9e8bfea2c2c895c59b9369e245', + '0xde2318630368656c2cce43bb993c6a3c077bc0b1cc75341375439f5a1206d347', ]); done(); }); @@ -111,8 +129,7 @@ describe('periods', () => { block3.addTx(Tx.deposit(7, value, ADDR, color)); block3.addTx(Tx.deposit(8, value, ADDR, color)); - const period = new Period(null, [block1, block2, block3]); - period.setValidatorData(slotId, ADDR); + const period = new Period(null, [block1, block2, block3], legacyOpts); const proof = period.proof(deposit2); expect(proof).to.eql([ '0x8e08277cfeb7f80da02df9e165d59bd7fccc10221ee24c3d660d7a4739524fc7', @@ -140,8 +157,7 @@ describe('periods', () => { blocks.push(block); } - const period = new Period(null, blocks); - period.setValidatorData(slotId, ADDR); + const period = new Period(null, blocks, legacyOpts); const proof = period.proof(Tx.deposit(12, value, ADDR, color)); expect(proof).to.eql([ '0x275e30e070a5637312ec95d135e8b393824e38c420ab142e8b72bb1528a26088', @@ -175,8 +191,7 @@ describe('periods', () => { } } - const period = new Period(null, blocks); - period.setValidatorData(slotId, ADDR); + const period = new Period(null, blocks, legacyOpts); const proof = period.proof(Tx.deposit(13, value, ADDR, color)); expect(proof).to.eql([ '0x2f66d9caf3a49598e7259c850c5bf3bbf7cdc61be65846f03296b1c0f54386a2', @@ -218,8 +233,7 @@ describe('periods', () => { block = new Block(31).addTx(transfer); blocks.push(block); - const period = new Period(null, blocks); - period.setValidatorData(slotId, ADDR); + const period = new Period(null, blocks, legacyOpts); const proof = period.proof(transfer); expect(proof).to.eql([ @@ -262,11 +276,13 @@ describe('periods', () => { block = new Block(31).addTx(transfer); blocks.push(block); - const period = new Period("0x8b04de057fe524a3118eb7c8e14a2e55323c67fd7b6080583d1047b700b2d674", blocks); - period.setValidatorData(slotId, ADDR); - const periodAfter = new Period(period.periodRoot(), blocks); + const period = new Period( + "0x8b04de057fe524a3118eb7c8e14a2e55323c67fd7b6080583d1047b700b2d674", + blocks, + { validatorData } + ); + const periodAfter = new Period(period.periodRoot(), blocks, { validatorData }); periodAfter.setValidatorData(slotId, ADDR); - periodAfter.usePrevPeriod(); const proof = periodAfter.prevPeriodProof(); expect(Period.verifyPrevPeriodProof(proof)).to.eql(periodAfter.periodRoot()); From 856840552f5dd9ab644792661e1c07eded1144c3 Mon Sep 17 00:00:00 2001 From: Jan Date: Mon, 23 Dec 2019 17:20:00 +0100 Subject: [PATCH 4/4] PrevPeriod proof verification clarification --- lib/period.js | 6 +++--- lib/period.spec.js | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/period.js b/lib/period.js index dc2744a..83af4e3 100644 --- a/lib/period.js +++ b/lib/period.js @@ -172,8 +172,8 @@ export default class Period { return proof; } - // returns current period - static verifyPrevPeriodProof(proof) { + // returns [currentPeriodRoot, prevPeriodRoot] + static evaluatePrevPeriodProof(proof) { let result; result = Buffer.alloc(64, 0); // fees hash @@ -189,7 +189,7 @@ export default class Period { result = Buffer.alloc(64, 0); toBuffer(consensusRoot).copy(result); toBuffer(proof[3]).copy(result, 32); - return bufferToHex(keccak256(result)); + return [proof[1], bufferToHex(keccak256(result))]; } proof(tx) { diff --git a/lib/period.spec.js b/lib/period.spec.js index 4ff4059..532d3ef 100644 --- a/lib/period.spec.js +++ b/lib/period.spec.js @@ -285,7 +285,9 @@ describe('periods', () => { periodAfter.setValidatorData(slotId, ADDR); const proof = periodAfter.prevPeriodProof(); - expect(Period.verifyPrevPeriodProof(proof)).to.eql(periodAfter.periodRoot()); + const [currentPeriod, prevPeriod] = Period.evaluatePrevPeriodProof(proof); + expect(prevPeriod).to.eql(periodAfter.periodRoot()); + expect(currentPeriod).to.eql(period.periodRoot()); done(); });