Skip to content

Commit b3aaaff

Browse files
authored
Merge branch 'master' into patch-2
2 parents 2a5acb5 + 716c4db commit b3aaaff

File tree

5 files changed

+105
-14
lines changed

5 files changed

+105
-14
lines changed

e2e/infrastructure/TransactionHttp.spec.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {ChronoUnit} from 'js-joda';
1919
import {keccak_256, sha3_256} from 'js-sha3';
2020
import {Crypto} from '../../src/core/crypto';
2121
import { Convert as convert } from '../../src/core/format';
22+
import { TransactionMapping } from '../../src/core/utils/TransactionMapping';
2223
import {AccountHttp} from '../../src/infrastructure/AccountHttp';
2324
import { NamespaceHttp } from '../../src/infrastructure/infrastructure';
2425
import {Listener} from '../../src/infrastructure/Listener';
@@ -45,6 +46,7 @@ import { AccountRestrictionTransaction } from '../../src/model/transaction/Accou
4546
import { AddressAliasTransaction } from '../../src/model/transaction/AddressAliasTransaction';
4647
import {AggregateTransaction} from '../../src/model/transaction/AggregateTransaction';
4748
import {CosignatureSignedTransaction} from '../../src/model/transaction/CosignatureSignedTransaction';
49+
import { CosignatureTransaction } from '../../src/model/transaction/CosignatureTransaction';
4850
import {Deadline} from '../../src/model/transaction/Deadline';
4951
import { HashLockTransaction } from '../../src/model/transaction/HashLockTransaction';
5052
import {HashType} from '../../src/model/transaction/HashType';
@@ -1761,6 +1763,67 @@ describe('TransactionHttp', () => {
17611763
});
17621764
});
17631765

1766+
describe('SignTransactionGivenSignatures', () => {
1767+
let listener: Listener;
1768+
before (() => {
1769+
listener = new Listener(config.apiUrl);
1770+
return listener.open();
1771+
});
1772+
after(() => {
1773+
return listener.close();
1774+
});
1775+
it('Announce cosign signatures given', (done) => {
1776+
1777+
/**
1778+
* @see https://github.com/nemtech/nem2-sdk-typescript-javascript/issues/112
1779+
*/
1780+
// AliceAccount: account
1781+
// BobAccount: account
1782+
1783+
const sendAmount = NetworkCurrencyMosaic.createRelative(1000);
1784+
const backAmount = NetworkCurrencyMosaic.createRelative(1);
1785+
1786+
const aliceTransferTransaction = TransferTransaction.create(Deadline.create(), account2.address, [sendAmount],
1787+
PlainMessage.create('payout'), NetworkType.MIJIN_TEST);
1788+
const bobTransferTransaction = TransferTransaction.create(Deadline.create(), account.address, [backAmount],
1789+
PlainMessage.create('payout'), NetworkType.MIJIN_TEST);
1790+
1791+
// 01. Alice creates the aggregated tx and sign it. Then payload send to Bob
1792+
const aggregateTransaction = AggregateTransaction.createComplete(
1793+
Deadline.create(),
1794+
[
1795+
aliceTransferTransaction.toAggregate(account.publicAccount),
1796+
bobTransferTransaction.toAggregate(account2.publicAccount),
1797+
],
1798+
NetworkType.MIJIN_TEST,
1799+
[],
1800+
);
1801+
1802+
const aliceSignedTransaction = aggregateTransaction.signWith(account, generationHash);
1803+
1804+
// 02 Bob cosigns the tx and sends it back to Alice
1805+
const signedTxBob = CosignatureTransaction.signTransactionPayload(account2, aliceSignedTransaction.payload, generationHash);
1806+
1807+
// 03. Alice collects the cosignatures, recreate, sign, and announces the transaction
1808+
const cosignatureSignedTransactions = [
1809+
new CosignatureSignedTransaction(signedTxBob.parentHash, signedTxBob.signature, signedTxBob.signer),
1810+
];
1811+
const recreatedTx = TransactionMapping.createFromPayload(aliceSignedTransaction.payload) as AggregateTransaction;
1812+
1813+
const signedTransaction = recreatedTx.signTransactionGivenSignatures(account, cosignatureSignedTransactions, generationHash);
1814+
1815+
listener.confirmed(account.address).subscribe(() => {
1816+
done();
1817+
});
1818+
listener.status(account.address).subscribe((error) => {
1819+
console.log('Error:', error);
1820+
assert(false);
1821+
done();
1822+
});
1823+
transactionHttp.announce(signedTransaction);
1824+
});
1825+
});
1826+
17641827
describe('transactions', () => {
17651828
it('should call transactions successfully', (done) => {
17661829
accountHttp.transactions(account.publicAccount).subscribe((transactions) => {

src/infrastructure/builders/AggregateTransaction.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export class AggregateTransaction extends VerifiableTransaction {
5656
return signedTransaction;
5757
}
5858

59-
signTransactionGivenSignatures(initializer, cosignedSignedTransactions, generationHash, signSchema) {
59+
signTransactionGivenSignatures(initializer, cosignedSignedTransactions, generationHash, signSchema = SignSchema.SHA3) {
6060
const signedTransaction = this.signTransaction(initializer, generationHash, signSchema);
6161
cosignedSignedTransactions.forEach((cosignedTransaction) => {
6262
signedTransaction.payload = signedTransaction.payload + cosignedTransaction.signer + cosignedTransaction.signature;

src/model/account/Account.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,21 @@ export class Account {
171171
return transaction.signTransactionWithCosignatories(this, cosignatories, generationHash, signSchema);
172172
}
173173

174+
/**
175+
* Sign transaction with cosignatories collected from cosigned transactions and creating a new SignedTransaction
176+
* For off chain Aggregated Complete Transaction co-signing.
177+
* @param initiatorAccount - Initiator account
178+
* @param {CosignatureSignedTransaction[]} cosignatureSignedTransactions - Array of cosigned transaction
179+
* @param generationHash - Network generation hash hex
180+
* @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3)
181+
* @return {SignedTransaction}
182+
*/
183+
public signTransactionGivenSignatures(transaction: AggregateTransaction,
184+
cosignatureSignedTransactions: CosignatureSignedTransaction[],
185+
generationHash: string,
186+
signSchema: SignSchema = SignSchema.SHA3): SignedTransaction {
187+
return transaction.signTransactionGivenSignatures(this, cosignatureSignedTransactions, generationHash, signSchema);
188+
}
174189
/**
175190
* Sign aggregate signature transaction
176191
* @param cosignatureTransaction - The aggregate signature transaction.

src/model/transaction/CosignatureTransaction.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@
1515
*/
1616

1717
import { SignSchema } from '../../core/crypto';
18+
import { Convert } from '../../core/format/Convert';
1819
import {CosignatureTransaction as CosignaturetransactionLibrary} from '../../infrastructure/builders/CosignatureTransaction';
20+
import { VerifiableTransaction } from '../../infrastructure/builders/VerifiableTransaction';
1921
import {Account} from '../account/Account';
2022
import {AggregateTransaction} from './AggregateTransaction';
2123
import {CosignatureSignedTransaction} from './CosignatureSignedTransaction';
22-
import { VerifiableTransaction } from '../../infrastructure/builders/VerifiableTransaction';
2324

2425
/**
2526
* Cosignature transaction is used to sign an aggregate transactions with missing cosignatures.
@@ -52,16 +53,20 @@ export class CosignatureTransaction {
5253
* Creating a new CosignatureSignedTransaction
5354
* @param account - The signing account
5455
* @param payload - off transaction payload (aggregated transaction is unannounced)
55-
* @param gernationHash - Network generation hash
56+
* @param generationHash - Network generation hash
57+
* @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3)
5658
* @returns {CosignatureSignedTransaction}
5759
*/
58-
public static signTransactionPayload(account: Account, payload: string, gernationHash: string): CosignatureSignedTransaction {
60+
public static signTransactionPayload(account: Account,
61+
payload: string,
62+
generationHash: string,
63+
signSchema: SignSchema = SignSchema.SHA3): CosignatureSignedTransaction {
5964
/**
6065
* For aggregated complete transaction, cosignatories are gathered off chain announced.
6166
*/
62-
const transactionHash = VerifiableTransaction.createTransactionHash(payload, gernationHash);
67+
const transactionHash = VerifiableTransaction.createTransactionHash(payload, Array.from(Convert.hexToUint8(generationHash)));
6368
const aggregateSignatureTransaction = new CosignaturetransactionLibrary(transactionHash);
64-
const signedTransactionRaw = aggregateSignatureTransaction.signCosignatoriesTransaction(account);
69+
const signedTransactionRaw = aggregateSignatureTransaction.signCosignatoriesTransaction(account, signSchema);
6570
return new CosignatureSignedTransaction(signedTransactionRaw.parentHash,
6671
signedTransactionRaw.signature,
6772
signedTransactionRaw.signer);
@@ -81,4 +86,4 @@ export class CosignatureTransaction {
8186
signedTransactionRaw.signature,
8287
signedTransactionRaw.signer);
8388
}
84-
}
89+
}

test/model/transaction/AggregateTransaction.spec.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ describe('AggregateTransaction', () => {
389389

390390
it('Should create signed transaction with cosignatories - Aggregated Complete', () => {
391391
/**
392-
* https://github.com/nemtech/nem2-sdk-typescript-javascript/issues/112
392+
* @see https://github.com/nemtech/nem2-sdk-typescript-javascript/issues/112
393393
*/
394394
const accountAlice = TestingAccount;
395395
const accountBob = CosignatoryAccount;
@@ -411,22 +411,24 @@ describe('AggregateTransaction', () => {
411411
PlainMessage.create('c to a'),
412412
NetworkType.MIJIN_TEST);
413413

414-
// 01. Alice creates the aggregated tx and serialize it, Then payload send to Bob & Carol
415-
const aggregateTransactionPayload = AggregateTransaction.createComplete(
414+
// 01. Alice creates the aggregated tx and sign it, Then payload send to Bob & Carol
415+
const aggregateTransaction = AggregateTransaction.createComplete(
416416
Deadline.create(),
417417
[
418418
AtoBTx.toAggregate(accountAlice.publicAccount),
419419
BtoATx.toAggregate(accountBob.publicAccount),
420420
CtoATx.toAggregate(accountCarol.publicAccount)],
421421
NetworkType.MIJIN_TEST,
422422
[],
423-
).serialize();
423+
);
424+
425+
const aliceSignedTransaction = aggregateTransaction.signWith(accountAlice, generationHash);
424426

425427
// 02.1 Bob cosigns the tx and sends it back to Alice
426-
const signedTxBob = CosignatureTransaction.signTransactionPayload(accountBob, aggregateTransactionPayload, generationHash);
428+
const signedTxBob = CosignatureTransaction.signTransactionPayload(accountBob, aliceSignedTransaction.payload, generationHash);
427429

428430
// 02.2 Carol cosigns the tx and sends it back to Alice
429-
const signedTxCarol = CosignatureTransaction.signTransactionPayload(accountCarol, aggregateTransactionPayload, generationHash);
431+
const signedTxCarol = CosignatureTransaction.signTransactionPayload(accountCarol, aliceSignedTransaction.payload, generationHash);
430432

431433
// 03. Alice collects the cosignatures, recreate, sign, and announces the transaction
432434

@@ -436,14 +438,20 @@ describe('AggregateTransaction', () => {
436438
new CosignatureSignedTransaction(signedTxCarol.parentHash, signedTxCarol.signature, signedTxCarol.signer),
437439
];
438440

439-
const recreatedTx = TransactionMapping.createFromPayload(aggregateTransactionPayload) as AggregateTransaction;
441+
const recreatedTx = TransactionMapping.createFromPayload(aliceSignedTransaction.payload) as AggregateTransaction;
440442

441443
const signedTransaction = recreatedTx.signTransactionGivenSignatures(accountAlice, cosignatureSignedTransactions, generationHash);
442444

443445
expect(signedTransaction.type).to.be.equal(TransactionType.AGGREGATE_COMPLETE);
444446
expect(signedTransaction.signer).to.be.equal(accountAlice.publicKey);
445447
expect(signedTransaction.payload.indexOf(accountBob.publicKey) > -1).to.be.true;
446448
expect(signedTransaction.payload.indexOf(accountCarol.publicKey) > -1).to.be.true;
449+
450+
// To make sure that the new cosign method returns the same payload & hash as standard cosigning
451+
const standardCosignedTransaction = aggregateTransaction
452+
.signTransactionWithCosignatories(accountAlice, [accountBob, accountCarol], generationHash);
453+
expect(standardCosignedTransaction.payload).to.be.equal(signedTransaction.payload);
454+
expect(standardCosignedTransaction.hash).to.be.equal(signedTransaction.hash);
447455
});
448456

449457
describe('size', () => {

0 commit comments

Comments
 (0)