From a4e80c74f3d4f9d605df3686e474cdc76a611713 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Fri, 15 Feb 2019 21:20:15 +0000 Subject: [PATCH] This resolves #57, resolves #58. 1. Changed default SHA3_512 to SHA3_256 2. Adding Op_Keccak_256, Op_Hash_160, Op_Hash_256 --- e2e/infrastructure/TransactionHttp.spec.ts | 328 ++++++++++++++++-- package-lock.json | 7 +- package.json | 2 + src/model/transaction/HashType.ts | 23 +- .../HashTypeLengthValidator.spec.ts | 59 +++- .../transaction/SecretLockTransaction.spec.ts | 122 ++++++- .../SecretProofTransaction.spec.ts | 99 +++++- 7 files changed, 582 insertions(+), 58 deletions(-) diff --git a/e2e/infrastructure/TransactionHttp.spec.ts b/e2e/infrastructure/TransactionHttp.spec.ts index d66837d356..7fe39ebe15 100644 --- a/e2e/infrastructure/TransactionHttp.spec.ts +++ b/e2e/infrastructure/TransactionHttp.spec.ts @@ -14,8 +14,9 @@ * limitations under the License. */ import {expect} from 'chai'; +import * as CryptoJS from 'crypto-js'; import {ChronoUnit} from 'js-joda'; -import {sha3_512} from 'js-sha3'; +import {keccak_256, sha3_256} from 'js-sha3'; import {convert, nacl_catapult} from 'nem2-library'; import {AccountHttp} from '../../src/infrastructure/AccountHttp'; import {Listener} from '../../src/infrastructure/Listener'; @@ -346,49 +347,269 @@ describe('TransactionHttp', () => { }); describe('SecretLockTransaction', () => { + describe('HashType: Op_Sha3_256', () => { + it('standalone', (done) => { + const secretLockTransaction = SecretLockTransaction.create( + Deadline.create(), + XEM.createAbsolute(10), + UInt64.fromUint(100), + HashType.Op_Sha3_256, + sha3_256.create().update(nacl_catapult.randomBytes(20)).hex(), + Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL'), + NetworkType.MIJIN_TEST, + ); + validateTransactionAnnounceCorrectly(account.address, done); + transactionHttp.announce(secretLockTransaction.signWith(account)); + }); + + it('aggregate', (done) => { + const secretLockTransaction = SecretLockTransaction.create( + Deadline.create(), + XEM.createAbsolute(10), + UInt64.fromUint(100), + HashType.Op_Sha3_256, + sha3_256.create().update(nacl_catapult.randomBytes(20)).hex(), + Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL'), + NetworkType.MIJIN_TEST, + ); + const aggregateSecretLockTransaction = AggregateTransaction.createComplete(Deadline.create(), + [secretLockTransaction.toAggregate(account.publicAccount)], + NetworkType.MIJIN_TEST, + []); + validateTransactionAnnounceCorrectly(account.address, done); + transactionHttp.announce(aggregateSecretLockTransaction.signWith(account)); + }); + }); + describe('HashType: Keccak_256', () => { + it('standalone', (done) => { + const secretLockTransaction = SecretLockTransaction.create( + Deadline.create(), + XEM.createAbsolute(10), + UInt64.fromUint(100), + HashType.Op_Keccak_256, + sha3_256.create().update(nacl_catapult.randomBytes(20)).hex(), + Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL'), + NetworkType.MIJIN_TEST, + ); + validateTransactionAnnounceCorrectly(account.address, done); + transactionHttp.announce(secretLockTransaction.signWith(account)); + }); + + it('aggregate', (done) => { + const secretLockTransaction = SecretLockTransaction.create( + Deadline.create(), + XEM.createAbsolute(10), + UInt64.fromUint(100), + HashType.Op_Keccak_256, + sha3_256.create().update(nacl_catapult.randomBytes(20)).hex(), + Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL'), + NetworkType.MIJIN_TEST, + ); + const aggregateSecretLockTransaction = AggregateTransaction.createComplete(Deadline.create(), + [secretLockTransaction.toAggregate(account.publicAccount)], + NetworkType.MIJIN_TEST, + []); + validateTransactionAnnounceCorrectly(account.address, done); + transactionHttp.announce(aggregateSecretLockTransaction.signWith(account)); + }); + }); + describe('HashType: Op_Hash_160', () => { + it('standalone', (done) => { + const secretLockTransaction = SecretLockTransaction.create( + Deadline.create(), + XEM.createAbsolute(10), + UInt64.fromUint(100), + HashType.Op_Hash_160, + sha3_256.create().update(nacl_catapult.randomBytes(20)).hex(), + Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL'), + NetworkType.MIJIN_TEST, + ); + validateTransactionAnnounceCorrectly(account.address, done); + transactionHttp.announce(secretLockTransaction.signWith(account)); + }); + + it('aggregate', (done) => { + const secretLockTransaction = SecretLockTransaction.create( + Deadline.create(), + XEM.createAbsolute(10), + UInt64.fromUint(100), + HashType.Op_Hash_160, + sha3_256.create().update(nacl_catapult.randomBytes(20)).hex(), + Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL'), + NetworkType.MIJIN_TEST, + ); + const aggregateSecretLockTransaction = AggregateTransaction.createComplete(Deadline.create(), + [secretLockTransaction.toAggregate(account.publicAccount)], + NetworkType.MIJIN_TEST, + []); + validateTransactionAnnounceCorrectly(account.address, done); + transactionHttp.announce(aggregateSecretLockTransaction.signWith(account)); + }); + }); + describe('HashType: Op_Hash_256', () => { + it('standalone', (done) => { + const secretLockTransaction = SecretLockTransaction.create( + Deadline.create(), + XEM.createAbsolute(10), + UInt64.fromUint(100), + HashType.Op_Hash_256, + sha3_256.create().update(nacl_catapult.randomBytes(20)).hex(), + Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL'), + NetworkType.MIJIN_TEST, + ); + validateTransactionAnnounceCorrectly(account.address, done); + transactionHttp.announce(secretLockTransaction.signWith(account)); + }); + + it('aggregate', (done) => { + const secretLockTransaction = SecretLockTransaction.create( + Deadline.create(), + XEM.createAbsolute(10), + UInt64.fromUint(100), + HashType.Op_Hash_256, + sha3_256.create().update(nacl_catapult.randomBytes(20)).hex(), + Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL'), + NetworkType.MIJIN_TEST, + ); + const aggregateSecretLockTransaction = AggregateTransaction.createComplete(Deadline.create(), + [secretLockTransaction.toAggregate(account.publicAccount)], + NetworkType.MIJIN_TEST, + []); + validateTransactionAnnounceCorrectly(account.address, done); + transactionHttp.announce(aggregateSecretLockTransaction.signWith(account)); + }); + }); + }); + describe('SecretProofTransaction', () => { + describe('HashType: Op_Sha3_256', () => { + it('standalone', (done) => { + const secretSeed = nacl_catapult.randomBytes(20); + const secret = sha3_256.create().update(secretSeed).hex(); + const proof = convert.uint8ToHex(secretSeed); + const secretLockTransaction = SecretLockTransaction.create( + Deadline.create(), + XEM.createAbsolute(10), + UInt64.fromUint(100), + HashType.Op_Sha3_256, + secret, + account2.address, + NetworkType.MIJIN_TEST, + ); + validateTransactionAnnounceCorrectly(account.address, () => { + const secretProofTransaction = SecretProofTransaction.create( + Deadline.create(), + HashType.Op_Sha3_256, + secret, + proof, + NetworkType.MIJIN_TEST, + ); + validateTransactionAnnounceCorrectly(account2.address, done); + transactionHttp.announce(secretProofTransaction.signWith(account2)); + }); + transactionHttp.announce(secretLockTransaction.signWith(account)); + }); + + it('aggregate', (done) => { + const secretSeed = nacl_catapult.randomBytes(20); + const secret = sha3_256.create().update(secretSeed).hex(); + const proof = convert.uint8ToHex(secretSeed); + const secretLockTransaction = SecretLockTransaction.create( + Deadline.create(), + XEM.createAbsolute(10), + UInt64.fromUint(100), + HashType.Op_Sha3_256, + secret, + account2.address, + NetworkType.MIJIN_TEST, + ); + validateTransactionAnnounceCorrectly(account.address, () => { + const secretProofTransaction = SecretProofTransaction.create( + Deadline.create(), + HashType.Op_Sha3_256, + secret, + proof, + NetworkType.MIJIN_TEST, + ); + const aggregateSecretProofTransaction = AggregateTransaction.createComplete(Deadline.create(), + [secretProofTransaction.toAggregate(account2.publicAccount)], + NetworkType.MIJIN_TEST, + []); + validateTransactionAnnounceCorrectly(account2.address, done); + transactionHttp.announce(aggregateSecretProofTransaction.signWith(account2)); + }); + transactionHttp.announce(secretLockTransaction.signWith(account)); + }); + }); + }); + describe('HashType: Op_Keccak_256', () => { it('standalone', (done) => { + const secretSeed = nacl_catapult.randomBytes(20); + const secret = keccak_256.create().update(secretSeed).hex(); + const proof = convert.uint8ToHex(secretSeed); const secretLockTransaction = SecretLockTransaction.create( Deadline.create(), XEM.createAbsolute(10), UInt64.fromUint(100), - HashType.SHA3_512, - sha3_512.create().update(nacl_catapult.randomBytes(20)).hex(), - Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL'), + HashType.Op_Keccak_256, + secret, + account2.address, NetworkType.MIJIN_TEST, ); - validateTransactionAnnounceCorrectly(account.address, done); + validateTransactionAnnounceCorrectly(account.address, () => { + const secretProofTransaction = SecretProofTransaction.create( + Deadline.create(), + HashType.Op_Keccak_256, + secret, + proof, + NetworkType.MIJIN_TEST, + ); + validateTransactionAnnounceCorrectly(account2.address, done); + transactionHttp.announce(secretProofTransaction.signWith(account2)); + }); transactionHttp.announce(secretLockTransaction.signWith(account)); }); it('aggregate', (done) => { + const secretSeed = nacl_catapult.randomBytes(20); + const secret = keccak_256.create().update(secretSeed).hex(); + const proof = convert.uint8ToHex(secretSeed); const secretLockTransaction = SecretLockTransaction.create( Deadline.create(), XEM.createAbsolute(10), UInt64.fromUint(100), - HashType.SHA3_512, - sha3_512.create().update(nacl_catapult.randomBytes(20)).hex(), - Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL'), + HashType.Op_Keccak_256, + secret, + account2.address, NetworkType.MIJIN_TEST, ); - const aggregateSecretLockTransaction = AggregateTransaction.createComplete(Deadline.create(), - [secretLockTransaction.toAggregate(account.publicAccount)], - NetworkType.MIJIN_TEST, - []); - validateTransactionAnnounceCorrectly(account.address, done); - transactionHttp.announce(aggregateSecretLockTransaction.signWith(account)); + validateTransactionAnnounceCorrectly(account.address, () => { + const secretProofTransaction = SecretProofTransaction.create( + Deadline.create(), + HashType.Op_Keccak_256, + secret, + proof, + NetworkType.MIJIN_TEST, + ); + const aggregateSecretProofTransaction = AggregateTransaction.createComplete(Deadline.create(), + [secretProofTransaction.toAggregate(account2.publicAccount)], + NetworkType.MIJIN_TEST, + []); + validateTransactionAnnounceCorrectly(account2.address, done); + transactionHttp.announce(aggregateSecretProofTransaction.signWith(account2)); + }); + transactionHttp.announce(secretLockTransaction.signWith(account)); }); }); - describe('SecretProofTransaction', () => { + describe('HashType: Op_Hash_160', () => { it('standalone', (done) => { - const secretSeed = nacl_catapult.randomBytes(20); - const secret = sha3_512.create().update(secretSeed).hex(); + const secretSeed = String.fromCharCode.apply(null, nacl_catapult.randomBytes(20)); + const secret = CryptoJS.RIPEMD160(CryptoJS.SHA256(secretSeed).toString(CryptoJS.enc.Hex)).toString(CryptoJS.enc.Hex); const proof = convert.uint8ToHex(secretSeed); - const secretLockTransaction = SecretLockTransaction.create( Deadline.create(), XEM.createAbsolute(10), UInt64.fromUint(100), - HashType.SHA3_512, + HashType.Op_Hash_160, secret, account2.address, NetworkType.MIJIN_TEST, @@ -396,27 +617,26 @@ describe('TransactionHttp', () => { validateTransactionAnnounceCorrectly(account.address, () => { const secretProofTransaction = SecretProofTransaction.create( Deadline.create(), - HashType.SHA3_512, + HashType.Op_Hash_160, secret, proof, NetworkType.MIJIN_TEST, ); validateTransactionAnnounceCorrectly(account2.address, done); transactionHttp.announce(secretProofTransaction.signWith(account2)); - }); transactionHttp.announce(secretLockTransaction.signWith(account)); }); it('aggregate', (done) => { - const secretSeed = nacl_catapult.randomBytes(20); - const secret = sha3_512.create().update(secretSeed).hex(); + const secretSeed = String.fromCharCode.apply(null, nacl_catapult.randomBytes(20)); + const secret = CryptoJS.RIPEMD160(CryptoJS.SHA256(secretSeed).toString(CryptoJS.enc.Hex)).toString(CryptoJS.enc.Hex); const proof = convert.uint8ToHex(secretSeed); const secretLockTransaction = SecretLockTransaction.create( Deadline.create(), XEM.createAbsolute(10), UInt64.fromUint(100), - HashType.SHA3_512, + HashType.Op_Hash_160, secret, account2.address, NetworkType.MIJIN_TEST, @@ -424,7 +644,7 @@ describe('TransactionHttp', () => { validateTransactionAnnounceCorrectly(account.address, () => { const secretProofTransaction = SecretProofTransaction.create( Deadline.create(), - HashType.SHA3_512, + HashType.Op_Hash_160, secret, proof, NetworkType.MIJIN_TEST, @@ -435,7 +655,65 @@ describe('TransactionHttp', () => { []); validateTransactionAnnounceCorrectly(account2.address, done); transactionHttp.announce(aggregateSecretProofTransaction.signWith(account2)); + }); + transactionHttp.announce(secretLockTransaction.signWith(account)); + }); + }); + describe('HashType: Op_Hash_256', () => { + it('standalone', (done) => { + const secretSeed = String.fromCharCode.apply(null, nacl_catapult.randomBytes(20)); + const secret = CryptoJS.SHA256(CryptoJS.SHA256(secretSeed).toString(CryptoJS.enc.Hex)).toString(CryptoJS.enc.Hex); + const proof = convert.uint8ToHex(secretSeed); + const secretLockTransaction = SecretLockTransaction.create( + Deadline.create(), + XEM.createAbsolute(10), + UInt64.fromUint(100), + HashType.Op_Hash_256, + secret, + account2.address, + NetworkType.MIJIN_TEST, + ); + validateTransactionAnnounceCorrectly(account.address, () => { + const secretProofTransaction = SecretProofTransaction.create( + Deadline.create(), + HashType.Op_Hash_256, + secret, + proof, + NetworkType.MIJIN_TEST, + ); + validateTransactionAnnounceCorrectly(account2.address, done); + transactionHttp.announce(secretProofTransaction.signWith(account2)); + }); + transactionHttp.announce(secretLockTransaction.signWith(account)); + }); + it('aggregate', (done) => { + const secretSeed = String.fromCharCode.apply(null, nacl_catapult.randomBytes(20)); + const secret = CryptoJS.SHA256(CryptoJS.SHA256(secretSeed).toString(CryptoJS.enc.Hex)).toString(CryptoJS.enc.Hex); + const proof = convert.uint8ToHex(secretSeed); + const secretLockTransaction = SecretLockTransaction.create( + Deadline.create(), + XEM.createAbsolute(10), + UInt64.fromUint(100), + HashType.Op_Hash_256, + secret, + account2.address, + NetworkType.MIJIN_TEST, + ); + validateTransactionAnnounceCorrectly(account.address, () => { + const secretProofTransaction = SecretProofTransaction.create( + Deadline.create(), + HashType.Op_Hash_256, + secret, + proof, + NetworkType.MIJIN_TEST, + ); + const aggregateSecretProofTransaction = AggregateTransaction.createComplete(Deadline.create(), + [secretProofTransaction.toAggregate(account2.publicAccount)], + NetworkType.MIJIN_TEST, + []); + validateTransactionAnnounceCorrectly(account2.address, done); + transactionHttp.announce(aggregateSecretProofTransaction.signWith(account2)); }); transactionHttp.announce(secretLockTransaction.signWith(account)); }); diff --git a/package-lock.json b/package-lock.json index 294549bedd..cc197e985c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "nem2-sdk", - "version": "0.10.0", + "version": "0.10.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -16,6 +16,11 @@ "integrity": "sha512-D8uQwKYUw2KESkorZ27ykzXgvkDJYXVEihGklgfp5I4HUP8D6IxtcdLTMB1emjQiWzV7WZ5ihm1cxIzVwjoleQ==", "dev": true }, + "@types/crypto-js": { + "version": "3.1.43", + "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-3.1.43.tgz", + "integrity": "sha512-EHe/YKctU3IYNBsDmSOPX/7jLHPRlx8WaiDKSY9JCTnJ8XJeM4c0ZJvx+9Gxmr2s2ihI92R+3U/gNL1sq5oRuQ==" + }, "@types/form-data": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz", diff --git a/package.json b/package.json index 55c476d483..bfb4feb575 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,8 @@ "typescript-require": "^0.2.9-1" }, "dependencies": { + "@types/crypto-js": "^3.1.43", + "crypto-js": "^3.1.9-1", "js-joda": "^1.6.2", "nem2-library": "^0.9.5", "request": "^2.83.0", diff --git a/src/model/transaction/HashType.ts b/src/model/transaction/HashType.ts index fb4b99376f..d05cd87ca9 100644 --- a/src/model/transaction/HashType.ts +++ b/src/model/transaction/HashType.ts @@ -16,17 +16,32 @@ /** * Hash type. Supported types are: - * 0: SHA3_512. + * 0: Op_Sha3_256 (default). + * 1: Op_Keccak_256 (ETH compatibility). + * 2: Op_Hash_160 (first with SHA-256 and then with RIPEMD-160 (BTC compatibility)) + * 3: Op_Hash_256: input is hashed twice with SHA-256 (BTC compatibility) */ import {convert} from 'nem2-library'; export enum HashType { - SHA3_512 = 0, + Op_Sha3_256 = 0, + Op_Keccak_256 = 1, + Op_Hash_160 = 2, + Op_Hash_256 = 3, } export function HashTypeLengthValidator(hashType: HashType, input: string): boolean { - if (hashType === HashType.SHA3_512 && convert.isHexString(input)) { - return input.length === 128; + if (convert.isHexString(input)) { + switch (hashType) { + case HashType.Op_Sha3_256: + case HashType.Op_Hash_256: + case HashType.Op_Keccak_256: + return input.length === 64; + case HashType.Op_Hash_160: + return input.length === 40; + default: + break; + } } return false; } diff --git a/test/model/transaction/HashTypeLengthValidator.spec.ts b/test/model/transaction/HashTypeLengthValidator.spec.ts index 311d58a457..14cef84c9c 100644 --- a/test/model/transaction/HashTypeLengthValidator.spec.ts +++ b/test/model/transaction/HashTypeLengthValidator.spec.ts @@ -14,21 +14,66 @@ * limitations under the License. */ import {expect} from 'chai'; -import {sha3_256, sha3_512} from 'js-sha3'; +import * as CryptoJS from 'crypto-js'; +import {keccak_256, sha3_256, sha3_512} from 'js-sha3'; import {HashType, HashTypeLengthValidator} from '../../../src/model/transaction/HashType'; describe('HashTypeLengthValidator', () => { - it('HashType.SHA3_512 should be exactly 128 chars length', () => { - expect(HashTypeLengthValidator(HashType.SHA3_512, sha3_512.create().update('abcxyz').hex())).to.be.equal(true); + it('HashType.SHA3_256 should be exactly 64 chars length', () => { + expect(HashTypeLengthValidator(HashType.Op_Sha3_256, sha3_256.create().update('abcxyz').hex())).to.be.equal(true); }); - it('HashType.SHA3_512 should return false if it is not 128 chars length', () => { - expect(HashTypeLengthValidator(HashType.SHA3_512, sha3_256.create().update('abcxyz').hex())).to.be.equal(false); + it('HashType.SHA3_256 should return false if it is not 64 chars length', () => { + expect(HashTypeLengthValidator(HashType.Op_Sha3_256, sha3_512.create().update('abcxyz').hex())).to.be.equal(false); }); - it('HashType.SHA_512 should return false if it is not a hash valid', () => { + it('HashType.SHA_256 should return false if it is not a hash valid', () => { const invalidHash = 'zyz6053bb910a6027f138ac5ebe92d43a9a18b7239b3c4d5ea69f1632e50aeef28184e46cd22ded096b76631858' + '0a569e74521a9d63885cc8d5e8644793be928'; - expect(HashTypeLengthValidator(HashType.SHA3_512, invalidHash)).to.be.equal(false); + expect(HashTypeLengthValidator(HashType.Op_Sha3_256, invalidHash)).to.be.equal(false); + }); + + it('HashType.Keccak_256 should be exactly 64 chars length', () => { + expect(HashTypeLengthValidator(HashType.Op_Keccak_256, keccak_256.create().update('abcxyz').hex())).to.be.equal(true); + }); + + it('HashType.Keccak_256 should return false if it is not 64 chars length', () => { + expect(HashTypeLengthValidator(HashType.Op_Keccak_256, sha3_512.create().update('abcxyz').toString())).to.be.equal(false); + }); + + it('HashType.Keccak_256 should return false if it is not a hash valid', () => { + const invalidHash = 'zyz6053bb910a6027f138ac5ebe92d43a9a18b7239b3c4d5ea69f1632e50aeef28184e46cd22ded096b76631858' + + '0a569e74521a9d63885cc8d5e8644793be928'; + expect(HashTypeLengthValidator(HashType.Op_Keccak_256, invalidHash)).to.be.equal(false); + }); + + it('HashType.Op_Hash_256 should be exactly 64 chars length', () => { + // tslint:disable-next-line:max-line-length + expect(HashTypeLengthValidator(HashType.Op_Hash_256, CryptoJS.SHA256(CryptoJS.SHA256('abcxyz').toString(CryptoJS.enc.Hex)).toString(CryptoJS.enc.Hex))).to.be.equal(true); + }); + + it('HashType.Op_Hash_256 should return false if it is not 64 chars length', () => { + expect(HashTypeLengthValidator(HashType.Op_Hash_256, sha3_512.create().update('abcxyz').toString())).to.be.equal(false); + }); + + it('HashType.Op_Hash_256 should return false if it is not a hash valid', () => { + const invalidHash = 'zyz6053bb910a6027f138ac5ebe92d43a9a18b7239b3c4d5ea69f1632e50aeef28184e46cd22ded096b76631858' + + '0a569e74521a9d63885cc8d5e8644793be928'; + expect(HashTypeLengthValidator(HashType.Op_Hash_256, invalidHash)).to.be.equal(false); + }); + + it('HashType.Op_Hash_160 should be exactly 40 chars length', () => { + // tslint:disable-next-line:max-line-length + expect(HashTypeLengthValidator(HashType.Op_Hash_160, CryptoJS.RIPEMD160(CryptoJS.SHA256('abcxyz').toString(CryptoJS.enc.Hex)).toString(CryptoJS.enc.Hex))).to.be.equal(true); + }); + + it('HashType.Op_Hash_160 should return false if it is not 64 chars length', () => { + expect(HashTypeLengthValidator(HashType.Op_Hash_160, sha3_512.create().update('abcxyz').toString())).to.be.equal(false); + }); + + it('HashType.Op_Hash_160 should return false if it is not a hash valid', () => { + const invalidHash = 'zyz6053bb910a6027f138ac5ebe92d43a9a18b7239b3c4d5ea69f1632e50aeef28184e46cd22ded096b76631858' + + '0a569e74521a9d63885cc8d5e8644793be928'; + expect(HashTypeLengthValidator(HashType.Op_Hash_160, invalidHash)).to.be.equal(false); }); }); diff --git a/test/model/transaction/SecretLockTransaction.spec.ts b/test/model/transaction/SecretLockTransaction.spec.ts index 47752a8a4b..d26261e95e 100644 --- a/test/model/transaction/SecretLockTransaction.spec.ts +++ b/test/model/transaction/SecretLockTransaction.spec.ts @@ -14,7 +14,8 @@ * limitations under the License. */ import {expect} from 'chai'; -import {sha3_512} from 'js-sha3'; +import * as CryptoJS from 'crypto-js'; +import {keccak_256, sha3_256} from 'js-sha3'; import {convert} from 'nem2-library'; import {Address} from '../../../src/model/account/Address'; import {NetworkType} from '../../../src/model/blockchain/NetworkType'; @@ -26,16 +27,15 @@ import {UInt64} from '../../../src/model/UInt64'; describe('SecretLockTransaction', () => { - it('should be created', () => { - const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9DF538782BF199C189DABEAC7680ADA57' + - 'DCEC8EEE91C4E3BF3BFA9AF6FFDE90CD1D249D1C6121D7B759A001B1'; + it('should be created with HashType: Op_Sha3_256 secret', () => { + const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9DF538782BF199C189DABEAC7'; const recipient = Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL'); const secretLockTransaction = SecretLockTransaction.create( Deadline.create(), XEM.createAbsolute(10), UInt64.fromUint(100), - HashType.SHA3_512, - sha3_512.create().update(convert.hexToUint8(proof)).hex(), + HashType.Op_Sha3_256, + sha3_256.create().update(convert.hexToUint8(proof)).hex(), recipient, NetworkType.MIJIN_TEST, ); @@ -43,19 +43,121 @@ describe('SecretLockTransaction', () => { expect(secretLockTransaction.mosaic.amount.equals(UInt64.fromUint(10))).to.be.equal(true); expect(secretLockTransaction.duration.equals(UInt64.fromUint(100))).to.be.equal(true); expect(secretLockTransaction.hashType).to.be.equal(0); - expect(secretLockTransaction.secret).to.be.equal('d23859866f93f2698a5b48586543c608d85a57c74e9ce92d86a0b25065d' + - '8155c16754d840026b8c536f2bcb963a7d867f034ec241b87162ac33daf7b707cb5f7'); + expect(secretLockTransaction.secret).to.be.equal('9b3155b37159da50aa52d5967c509b410f5a36a3b1e31ecb5ac76675d79b4a5e'); expect(secretLockTransaction.recipient).to.be.equal(recipient); }); - it('should throw exception when the input is not related to HashType', () => { + it('should throw exception when the input is not related to HashTyp: Op_Sha3_256', () => { expect(() => { const recipient = Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL'); const secretLockTransaction = SecretLockTransaction.create( Deadline.create(), XEM.createAbsolute(10), UInt64.fromUint(100), - HashType.SHA3_512, + HashType.Op_Sha3_256, + 'non valid hash', + recipient, + NetworkType.MIJIN_TEST, + ); + }).to.throw(Error); + }); + + it('should be created with HashType: Op_Keccak_256 secret', () => { + const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9DF538782BF199C189DABEAC7'; + const recipient = Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL'); + const secretLockTransaction = SecretLockTransaction.create( + Deadline.create(), + XEM.createAbsolute(10), + UInt64.fromUint(100), + HashType.Op_Keccak_256, + keccak_256.create().update(convert.hexToUint8(proof)).hex(), + recipient, + NetworkType.MIJIN_TEST, + ); + expect(secretLockTransaction.mosaic.id).to.be.equal(XEM.MOSAIC_ID); + expect(secretLockTransaction.mosaic.amount.equals(UInt64.fromUint(10))).to.be.equal(true); + expect(secretLockTransaction.duration.equals(UInt64.fromUint(100))).to.be.equal(true); + expect(secretLockTransaction.hashType).to.be.equal(1); + expect(secretLockTransaction.secret).to.be.equal('241c1d54c18c8422def03aa16b4b243a8ba491374295a1a6965545e6ac1af314'); + expect(secretLockTransaction.recipient).to.be.equal(recipient); + }); + + it('should throw exception when the input is not related to HashTyp: Op_Keccak_256', () => { + expect(() => { + const recipient = Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL'); + const secretLockTransaction = SecretLockTransaction.create( + Deadline.create(), + XEM.createAbsolute(10), + UInt64.fromUint(100), + HashType.Op_Keccak_256, + 'non valid hash', + recipient, + NetworkType.MIJIN_TEST, + ); + }).to.throw(Error); + }); + it('should be created with HashType: Op_Hash_160 secret', () => { + const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9'; + const recipient = Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL'); + const secretLockTransaction = SecretLockTransaction.create( + Deadline.create(), + XEM.createAbsolute(10), + UInt64.fromUint(100), + HashType.Op_Hash_160, + CryptoJS.RIPEMD160(CryptoJS.SHA256(proof).toString(CryptoJS.enc.Hex)).toString(CryptoJS.enc.Hex), + recipient, + NetworkType.MIJIN_TEST, + ); + expect(secretLockTransaction.mosaic.id).to.be.equal(XEM.MOSAIC_ID); + expect(secretLockTransaction.mosaic.amount.equals(UInt64.fromUint(10))).to.be.equal(true); + expect(secretLockTransaction.duration.equals(UInt64.fromUint(100))).to.be.equal(true); + expect(secretLockTransaction.hashType).to.be.equal(2); + expect(secretLockTransaction.secret).to.be.equal('3fc43d717d824302e3821de8129ea2f7786912e5'); + expect(secretLockTransaction.recipient).to.be.equal(recipient); + }); + + it('should throw exception when the input is not related to HashTyp: Op_Hash_160', () => { + expect(() => { + const recipient = Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL'); + const secretLockTransaction = SecretLockTransaction.create( + Deadline.create(), + XEM.createAbsolute(10), + UInt64.fromUint(100), + HashType.Op_Hash_160, + 'non valid hash', + recipient, + NetworkType.MIJIN_TEST, + ); + }).to.throw(Error); + }); + it('should be created with HashType: Op_Hash_256 secret', () => { + const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9DF538782BF199C189DABEAC7'; + const recipient = Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL'); + const secretLockTransaction = SecretLockTransaction.create( + Deadline.create(), + XEM.createAbsolute(10), + UInt64.fromUint(100), + HashType.Op_Hash_256, + CryptoJS.SHA256(CryptoJS.SHA256(proof).toString(CryptoJS.enc.Hex)).toString(CryptoJS.enc.Hex), + recipient, + NetworkType.MIJIN_TEST, + ); + expect(secretLockTransaction.mosaic.id).to.be.equal(XEM.MOSAIC_ID); + expect(secretLockTransaction.mosaic.amount.equals(UInt64.fromUint(10))).to.be.equal(true); + expect(secretLockTransaction.duration.equals(UInt64.fromUint(100))).to.be.equal(true); + expect(secretLockTransaction.hashType).to.be.equal(3); + expect(secretLockTransaction.secret).to.be.equal('c346f5ecf5bcfa54ab14fad815c8239bdeb051df8835d212dba2af59f688a00e'); + expect(secretLockTransaction.recipient).to.be.equal(recipient); + }); + + it('should throw exception when the input is not related to HashTyp: Op_Hash_256', () => { + expect(() => { + const recipient = Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL'); + const secretLockTransaction = SecretLockTransaction.create( + Deadline.create(), + XEM.createAbsolute(10), + UInt64.fromUint(100), + HashType.Op_Hash_256, 'non valid hash', recipient, NetworkType.MIJIN_TEST, diff --git a/test/model/transaction/SecretProofTransaction.spec.ts b/test/model/transaction/SecretProofTransaction.spec.ts index 8b8870fe98..1434017965 100644 --- a/test/model/transaction/SecretProofTransaction.spec.ts +++ b/test/model/transaction/SecretProofTransaction.spec.ts @@ -14,7 +14,8 @@ * limitations under the License. */ import {expect} from 'chai'; -import {sha3_512} from 'js-sha3'; +import * as CryptoJS from 'crypto-js'; +import {keccak_256, sha3_256} from 'js-sha3'; import {convert} from 'nem2-library'; import {NetworkType} from '../../../src/model/blockchain/NetworkType'; import {Deadline} from '../../../src/model/transaction/Deadline'; @@ -23,29 +24,105 @@ import {SecretProofTransaction} from '../../../src/model/transaction/SecretProof describe('SecretProofTransaction', () => { - it('should be created', () => { - const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9DF538782BF199C189DABEAC7680ADA57DCEC8EEE91C' + - '4E3BF3BFA9AF6FFDE90CD1D249D1C6121D7B759A001B1'; + it('should be created with HashType: Op_Sha3_256 secret', () => { + const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9DF538782BF199C189DABEAC7'; const secretProofTransaction = SecretProofTransaction.create( Deadline.create(), - HashType.SHA3_512, - sha3_512.create().update(convert.hexToUint8(proof)).hex(), + HashType.Op_Sha3_256, + sha3_256.create().update(convert.hexToUint8(proof)).hex(), proof, NetworkType.MIJIN_TEST, ); expect(secretProofTransaction.hashType).to.be.equal(0); - expect(secretProofTransaction.secret).to.be.equal('d23859866f93f2698a5b48586543c608d85a57c74e9ce92d86a0b25065d8' + - '155c16754d840026b8c536f2bcb963a7d867f034ec241b87162ac33daf7b707cb5f7'); + expect(secretProofTransaction.secret).to.be.equal('9b3155b37159da50aa52d5967c509b410f5a36a3b1e31ecb5ac76675d79b4a5e' ); expect(secretProofTransaction.proof).to.be.equal(proof); }); it('should throw exception when the input is not related to HashType', () => { expect(() => { - const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9DF538782BF199C189DABEAC7680ADA57DCEC8EEE91C' + - '4E3BF3BFA9AF6FFDE90CD1D249D1C6121D7B759A001B1'; + const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9DF538782BF199C189DABEAC7'; const secretProofTransaction = SecretProofTransaction.create( Deadline.create(), - HashType.SHA3_512, + HashType.Op_Sha3_256, + 'non valid hash', + proof, + NetworkType.MIJIN_TEST, + ); + }).to.throw(Error); + }); + it('should be created with HashType: Op_Keccak_256 secret', () => { + const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9DF538782BF199C189DABEAC7'; + const secretProofTransaction = SecretProofTransaction.create( + Deadline.create(), + HashType.Op_Keccak_256, + keccak_256.create().update(convert.hexToUint8(proof)).hex(), + proof, + NetworkType.MIJIN_TEST, + ); + expect(secretProofTransaction.hashType).to.be.equal(1); + expect(secretProofTransaction.secret).to.be.equal('241c1d54c18c8422def03aa16b4b243a8ba491374295a1a6965545e6ac1af314' ); + expect(secretProofTransaction.proof).to.be.equal(proof); + }); + + it('should throw exception when the input is not related to HashType', () => { + expect(() => { + const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9DF538782BF199C189DABEAC7'; + const secretProofTransaction = SecretProofTransaction.create( + Deadline.create(), + HashType.Op_Keccak_256, + 'non valid hash', + proof, + NetworkType.MIJIN_TEST, + ); + }).to.throw(Error); + }); + it('should be created with HashType: Op_Hash_160 secret', () => { + const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9'; + const secretProofTransaction = SecretProofTransaction.create( + Deadline.create(), + HashType.Op_Hash_160, + CryptoJS.RIPEMD160(CryptoJS.SHA256(proof).toString(CryptoJS.enc.Hex)).toString(CryptoJS.enc.Hex), + proof, + NetworkType.MIJIN_TEST, + ); + expect(secretProofTransaction.hashType).to.be.equal(2); + expect(secretProofTransaction.secret).to.be.equal('3fc43d717d824302e3821de8129ea2f7786912e5' ); + expect(secretProofTransaction.proof).to.be.equal(proof); + }); + + it('should throw exception when the input is not related to HashType', () => { + expect(() => { + const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9DF538782BF199C189DABEAC7'; + const secretProofTransaction = SecretProofTransaction.create( + Deadline.create(), + HashType.Op_Hash_160, + 'non valid hash', + proof, + NetworkType.MIJIN_TEST, + ); + }).to.throw(Error); + }); + + it('should be created with HashType: Op_Hash_256 secret', () => { + const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9DF538782BF199C189DABEAC7'; + const secretProofTransaction = SecretProofTransaction.create( + Deadline.create(), + HashType.Op_Hash_256, + CryptoJS.SHA256(CryptoJS.SHA256(proof).toString(CryptoJS.enc.Hex)).toString(CryptoJS.enc.Hex), + proof, + NetworkType.MIJIN_TEST, + ); + expect(secretProofTransaction.hashType).to.be.equal(3); + expect(secretProofTransaction.secret).to.be.equal('c346f5ecf5bcfa54ab14fad815c8239bdeb051df8835d212dba2af59f688a00e' ); + expect(secretProofTransaction.proof).to.be.equal(proof); + }); + + it('should throw exception when the input is not related to HashType', () => { + expect(() => { + const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9DF538782BF199C189DABEAC7'; + const secretProofTransaction = SecretProofTransaction.create( + Deadline.create(), + HashType.Op_Hash_256, 'non valid hash', proof, NetworkType.MIJIN_TEST,