Skip to content

Commit 5c76924

Browse files
author
Grégory Saive
authored
Merge pull request #62 from rg911/issue/#57_#58
Issue/#57 #58 secretlock sha512 to sha256 && New lock hash algorithms for secret lock
2 parents 282937a + a4e80c7 commit 5c76924

File tree

7 files changed

+582
-58
lines changed

7 files changed

+582
-58
lines changed

e2e/infrastructure/TransactionHttp.spec.ts

Lines changed: 303 additions & 25 deletions
Large diffs are not rendered by default.

package-lock.json

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
"typescript-require": "^0.2.9-1"
5151
},
5252
"dependencies": {
53+
"@types/crypto-js": "^3.1.43",
54+
"crypto-js": "^3.1.9-1",
5355
"js-joda": "^1.6.2",
5456
"nem2-library": "^0.9.5",
5557
"request": "^2.83.0",

src/model/transaction/HashType.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,32 @@
1616

1717
/**
1818
* Hash type. Supported types are:
19-
* 0: SHA3_512.
19+
* 0: Op_Sha3_256 (default).
20+
* 1: Op_Keccak_256 (ETH compatibility).
21+
* 2: Op_Hash_160 (first with SHA-256 and then with RIPEMD-160 (BTC compatibility))
22+
* 3: Op_Hash_256: input is hashed twice with SHA-256 (BTC compatibility)
2023
*/
2124
import {convert} from 'nem2-library';
2225

2326
export enum HashType {
24-
SHA3_512 = 0,
27+
Op_Sha3_256 = 0,
28+
Op_Keccak_256 = 1,
29+
Op_Hash_160 = 2,
30+
Op_Hash_256 = 3,
2531
}
2632

2733
export function HashTypeLengthValidator(hashType: HashType, input: string): boolean {
28-
if (hashType === HashType.SHA3_512 && convert.isHexString(input)) {
29-
return input.length === 128;
34+
if (convert.isHexString(input)) {
35+
switch (hashType) {
36+
case HashType.Op_Sha3_256:
37+
case HashType.Op_Hash_256:
38+
case HashType.Op_Keccak_256:
39+
return input.length === 64;
40+
case HashType.Op_Hash_160:
41+
return input.length === 40;
42+
default:
43+
break;
44+
}
3045
}
3146
return false;
3247
}

test/model/transaction/HashTypeLengthValidator.spec.ts

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,66 @@
1414
* limitations under the License.
1515
*/
1616
import {expect} from 'chai';
17-
import {sha3_256, sha3_512} from 'js-sha3';
17+
import * as CryptoJS from 'crypto-js';
18+
import {keccak_256, sha3_256, sha3_512} from 'js-sha3';
1819
import {HashType, HashTypeLengthValidator} from '../../../src/model/transaction/HashType';
1920

2021
describe('HashTypeLengthValidator', () => {
21-
it('HashType.SHA3_512 should be exactly 128 chars length', () => {
22-
expect(HashTypeLengthValidator(HashType.SHA3_512, sha3_512.create().update('abcxyz').hex())).to.be.equal(true);
22+
it('HashType.SHA3_256 should be exactly 64 chars length', () => {
23+
expect(HashTypeLengthValidator(HashType.Op_Sha3_256, sha3_256.create().update('abcxyz').hex())).to.be.equal(true);
2324
});
2425

25-
it('HashType.SHA3_512 should return false if it is not 128 chars length', () => {
26-
expect(HashTypeLengthValidator(HashType.SHA3_512, sha3_256.create().update('abcxyz').hex())).to.be.equal(false);
26+
it('HashType.SHA3_256 should return false if it is not 64 chars length', () => {
27+
expect(HashTypeLengthValidator(HashType.Op_Sha3_256, sha3_512.create().update('abcxyz').hex())).to.be.equal(false);
2728
});
2829

29-
it('HashType.SHA_512 should return false if it is not a hash valid', () => {
30+
it('HashType.SHA_256 should return false if it is not a hash valid', () => {
3031
const invalidHash = 'zyz6053bb910a6027f138ac5ebe92d43a9a18b7239b3c4d5ea69f1632e50aeef28184e46cd22ded096b76631858' +
3132
'0a569e74521a9d63885cc8d5e8644793be928';
32-
expect(HashTypeLengthValidator(HashType.SHA3_512, invalidHash)).to.be.equal(false);
33+
expect(HashTypeLengthValidator(HashType.Op_Sha3_256, invalidHash)).to.be.equal(false);
34+
});
35+
36+
it('HashType.Keccak_256 should be exactly 64 chars length', () => {
37+
expect(HashTypeLengthValidator(HashType.Op_Keccak_256, keccak_256.create().update('abcxyz').hex())).to.be.equal(true);
38+
});
39+
40+
it('HashType.Keccak_256 should return false if it is not 64 chars length', () => {
41+
expect(HashTypeLengthValidator(HashType.Op_Keccak_256, sha3_512.create().update('abcxyz').toString())).to.be.equal(false);
42+
});
43+
44+
it('HashType.Keccak_256 should return false if it is not a hash valid', () => {
45+
const invalidHash = 'zyz6053bb910a6027f138ac5ebe92d43a9a18b7239b3c4d5ea69f1632e50aeef28184e46cd22ded096b76631858' +
46+
'0a569e74521a9d63885cc8d5e8644793be928';
47+
expect(HashTypeLengthValidator(HashType.Op_Keccak_256, invalidHash)).to.be.equal(false);
48+
});
49+
50+
it('HashType.Op_Hash_256 should be exactly 64 chars length', () => {
51+
// tslint:disable-next-line:max-line-length
52+
expect(HashTypeLengthValidator(HashType.Op_Hash_256, CryptoJS.SHA256(CryptoJS.SHA256('abcxyz').toString(CryptoJS.enc.Hex)).toString(CryptoJS.enc.Hex))).to.be.equal(true);
53+
});
54+
55+
it('HashType.Op_Hash_256 should return false if it is not 64 chars length', () => {
56+
expect(HashTypeLengthValidator(HashType.Op_Hash_256, sha3_512.create().update('abcxyz').toString())).to.be.equal(false);
57+
});
58+
59+
it('HashType.Op_Hash_256 should return false if it is not a hash valid', () => {
60+
const invalidHash = 'zyz6053bb910a6027f138ac5ebe92d43a9a18b7239b3c4d5ea69f1632e50aeef28184e46cd22ded096b76631858' +
61+
'0a569e74521a9d63885cc8d5e8644793be928';
62+
expect(HashTypeLengthValidator(HashType.Op_Hash_256, invalidHash)).to.be.equal(false);
63+
});
64+
65+
it('HashType.Op_Hash_160 should be exactly 40 chars length', () => {
66+
// tslint:disable-next-line:max-line-length
67+
expect(HashTypeLengthValidator(HashType.Op_Hash_160, CryptoJS.RIPEMD160(CryptoJS.SHA256('abcxyz').toString(CryptoJS.enc.Hex)).toString(CryptoJS.enc.Hex))).to.be.equal(true);
68+
});
69+
70+
it('HashType.Op_Hash_160 should return false if it is not 64 chars length', () => {
71+
expect(HashTypeLengthValidator(HashType.Op_Hash_160, sha3_512.create().update('abcxyz').toString())).to.be.equal(false);
72+
});
73+
74+
it('HashType.Op_Hash_160 should return false if it is not a hash valid', () => {
75+
const invalidHash = 'zyz6053bb910a6027f138ac5ebe92d43a9a18b7239b3c4d5ea69f1632e50aeef28184e46cd22ded096b76631858' +
76+
'0a569e74521a9d63885cc8d5e8644793be928';
77+
expect(HashTypeLengthValidator(HashType.Op_Hash_160, invalidHash)).to.be.equal(false);
3378
});
3479
});

test/model/transaction/SecretLockTransaction.spec.ts

Lines changed: 112 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
* limitations under the License.
1515
*/
1616
import {expect} from 'chai';
17-
import {sha3_512} from 'js-sha3';
17+
import * as CryptoJS from 'crypto-js';
18+
import {keccak_256, sha3_256} from 'js-sha3';
1819
import {convert} from 'nem2-library';
1920
import {Address} from '../../../src/model/account/Address';
2021
import {NetworkType} from '../../../src/model/blockchain/NetworkType';
@@ -26,36 +27,137 @@ import {UInt64} from '../../../src/model/UInt64';
2627

2728
describe('SecretLockTransaction', () => {
2829

29-
it('should be created', () => {
30-
const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9DF538782BF199C189DABEAC7680ADA57' +
31-
'DCEC8EEE91C4E3BF3BFA9AF6FFDE90CD1D249D1C6121D7B759A001B1';
30+
it('should be created with HashType: Op_Sha3_256 secret', () => {
31+
const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9DF538782BF199C189DABEAC7';
3232
const recipient = Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL');
3333
const secretLockTransaction = SecretLockTransaction.create(
3434
Deadline.create(),
3535
XEM.createAbsolute(10),
3636
UInt64.fromUint(100),
37-
HashType.SHA3_512,
38-
sha3_512.create().update(convert.hexToUint8(proof)).hex(),
37+
HashType.Op_Sha3_256,
38+
sha3_256.create().update(convert.hexToUint8(proof)).hex(),
3939
recipient,
4040
NetworkType.MIJIN_TEST,
4141
);
4242
expect(secretLockTransaction.mosaic.id).to.be.equal(XEM.MOSAIC_ID);
4343
expect(secretLockTransaction.mosaic.amount.equals(UInt64.fromUint(10))).to.be.equal(true);
4444
expect(secretLockTransaction.duration.equals(UInt64.fromUint(100))).to.be.equal(true);
4545
expect(secretLockTransaction.hashType).to.be.equal(0);
46-
expect(secretLockTransaction.secret).to.be.equal('d23859866f93f2698a5b48586543c608d85a57c74e9ce92d86a0b25065d' +
47-
'8155c16754d840026b8c536f2bcb963a7d867f034ec241b87162ac33daf7b707cb5f7');
46+
expect(secretLockTransaction.secret).to.be.equal('9b3155b37159da50aa52d5967c509b410f5a36a3b1e31ecb5ac76675d79b4a5e');
4847
expect(secretLockTransaction.recipient).to.be.equal(recipient);
4948
});
5049

51-
it('should throw exception when the input is not related to HashType', () => {
50+
it('should throw exception when the input is not related to HashTyp: Op_Sha3_256', () => {
5251
expect(() => {
5352
const recipient = Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL');
5453
const secretLockTransaction = SecretLockTransaction.create(
5554
Deadline.create(),
5655
XEM.createAbsolute(10),
5756
UInt64.fromUint(100),
58-
HashType.SHA3_512,
57+
HashType.Op_Sha3_256,
58+
'non valid hash',
59+
recipient,
60+
NetworkType.MIJIN_TEST,
61+
);
62+
}).to.throw(Error);
63+
});
64+
65+
it('should be created with HashType: Op_Keccak_256 secret', () => {
66+
const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9DF538782BF199C189DABEAC7';
67+
const recipient = Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL');
68+
const secretLockTransaction = SecretLockTransaction.create(
69+
Deadline.create(),
70+
XEM.createAbsolute(10),
71+
UInt64.fromUint(100),
72+
HashType.Op_Keccak_256,
73+
keccak_256.create().update(convert.hexToUint8(proof)).hex(),
74+
recipient,
75+
NetworkType.MIJIN_TEST,
76+
);
77+
expect(secretLockTransaction.mosaic.id).to.be.equal(XEM.MOSAIC_ID);
78+
expect(secretLockTransaction.mosaic.amount.equals(UInt64.fromUint(10))).to.be.equal(true);
79+
expect(secretLockTransaction.duration.equals(UInt64.fromUint(100))).to.be.equal(true);
80+
expect(secretLockTransaction.hashType).to.be.equal(1);
81+
expect(secretLockTransaction.secret).to.be.equal('241c1d54c18c8422def03aa16b4b243a8ba491374295a1a6965545e6ac1af314');
82+
expect(secretLockTransaction.recipient).to.be.equal(recipient);
83+
});
84+
85+
it('should throw exception when the input is not related to HashTyp: Op_Keccak_256', () => {
86+
expect(() => {
87+
const recipient = Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL');
88+
const secretLockTransaction = SecretLockTransaction.create(
89+
Deadline.create(),
90+
XEM.createAbsolute(10),
91+
UInt64.fromUint(100),
92+
HashType.Op_Keccak_256,
93+
'non valid hash',
94+
recipient,
95+
NetworkType.MIJIN_TEST,
96+
);
97+
}).to.throw(Error);
98+
});
99+
it('should be created with HashType: Op_Hash_160 secret', () => {
100+
const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9';
101+
const recipient = Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL');
102+
const secretLockTransaction = SecretLockTransaction.create(
103+
Deadline.create(),
104+
XEM.createAbsolute(10),
105+
UInt64.fromUint(100),
106+
HashType.Op_Hash_160,
107+
CryptoJS.RIPEMD160(CryptoJS.SHA256(proof).toString(CryptoJS.enc.Hex)).toString(CryptoJS.enc.Hex),
108+
recipient,
109+
NetworkType.MIJIN_TEST,
110+
);
111+
expect(secretLockTransaction.mosaic.id).to.be.equal(XEM.MOSAIC_ID);
112+
expect(secretLockTransaction.mosaic.amount.equals(UInt64.fromUint(10))).to.be.equal(true);
113+
expect(secretLockTransaction.duration.equals(UInt64.fromUint(100))).to.be.equal(true);
114+
expect(secretLockTransaction.hashType).to.be.equal(2);
115+
expect(secretLockTransaction.secret).to.be.equal('3fc43d717d824302e3821de8129ea2f7786912e5');
116+
expect(secretLockTransaction.recipient).to.be.equal(recipient);
117+
});
118+
119+
it('should throw exception when the input is not related to HashTyp: Op_Hash_160', () => {
120+
expect(() => {
121+
const recipient = Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL');
122+
const secretLockTransaction = SecretLockTransaction.create(
123+
Deadline.create(),
124+
XEM.createAbsolute(10),
125+
UInt64.fromUint(100),
126+
HashType.Op_Hash_160,
127+
'non valid hash',
128+
recipient,
129+
NetworkType.MIJIN_TEST,
130+
);
131+
}).to.throw(Error);
132+
});
133+
it('should be created with HashType: Op_Hash_256 secret', () => {
134+
const proof = 'B778A39A3663719DFC5E48C9D78431B1E45C2AF9DF538782BF199C189DABEAC7';
135+
const recipient = Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL');
136+
const secretLockTransaction = SecretLockTransaction.create(
137+
Deadline.create(),
138+
XEM.createAbsolute(10),
139+
UInt64.fromUint(100),
140+
HashType.Op_Hash_256,
141+
CryptoJS.SHA256(CryptoJS.SHA256(proof).toString(CryptoJS.enc.Hex)).toString(CryptoJS.enc.Hex),
142+
recipient,
143+
NetworkType.MIJIN_TEST,
144+
);
145+
expect(secretLockTransaction.mosaic.id).to.be.equal(XEM.MOSAIC_ID);
146+
expect(secretLockTransaction.mosaic.amount.equals(UInt64.fromUint(10))).to.be.equal(true);
147+
expect(secretLockTransaction.duration.equals(UInt64.fromUint(100))).to.be.equal(true);
148+
expect(secretLockTransaction.hashType).to.be.equal(3);
149+
expect(secretLockTransaction.secret).to.be.equal('c346f5ecf5bcfa54ab14fad815c8239bdeb051df8835d212dba2af59f688a00e');
150+
expect(secretLockTransaction.recipient).to.be.equal(recipient);
151+
});
152+
153+
it('should throw exception when the input is not related to HashTyp: Op_Hash_256', () => {
154+
expect(() => {
155+
const recipient = Address.createFromRawAddress('SDBDG4IT43MPCW2W4CBBCSJJT42AYALQN7A4VVWL');
156+
const secretLockTransaction = SecretLockTransaction.create(
157+
Deadline.create(),
158+
XEM.createAbsolute(10),
159+
UInt64.fromUint(100),
160+
HashType.Op_Hash_256,
59161
'non valid hash',
60162
recipient,
61163
NetworkType.MIJIN_TEST,

0 commit comments

Comments
 (0)