Skip to content

Commit 6a01621

Browse files
committed
Added check in validate cosignatories for
modify multisig account (removal)
1 parent df799f6 commit 6a01621

File tree

2 files changed

+52
-4
lines changed

2 files changed

+52
-4
lines changed

src/service/AggregatedTransactionService.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ import { TransactionMapping } from '../core/utils/TransactionMapping';
2020
import { AccountHttp } from '../infrastructure/AccountHttp';
2121
import { MultisigAccountGraphInfo } from '../model/account/MultisigAccountGraphInfo';
2222
import { AggregateTransaction } from '../model/transaction/AggregateTransaction';
23+
import { InnerTransaction } from '../model/transaction/InnerTransaction';
24+
import { ModifyMultisigAccountTransaction } from '../model/transaction/ModifyMultisigAccountTransaction';
25+
import { MultisigCosignatoryModificationType } from '../model/transaction/MultisigCosignatoryModificationType';
2326
import { SignedTransaction } from '../model/transaction/SignedTransaction';
27+
import { TransactionType } from '../model/transaction/TransactionType';
2428

2529
/**
2630
* Aggregated Transaction service
@@ -58,7 +62,7 @@ export class AggregatedTransactionService {
5862
mergeMap((_) => _.minApproval !== 0 && _.minRemoval !== 0 ?
5963
this.accountHttp.getMultisigAccountGraphInfo(_.account.address)
6064
.pipe(
61-
map((graphInfo) => this.validateCosignatories(graphInfo, signers)),
65+
map((graphInfo) => this.validateCosignatories(graphInfo, signers, innerTransaction)),
6266
) : observableOf(true),
6367
),
6468
),
@@ -70,21 +74,37 @@ export class AggregatedTransactionService {
7074
* Validate cosignatories against multisig Account(s)
7175
* @param graphInfo - multisig account graph info
7276
* @param cosignatories - array of cosignatories extracted from aggregated transaction
77+
* @param innerTransaction - the inner transaction of the aggregated transaction
7378
* @returns {boolean}
7479
*/
75-
private validateCosignatories(graphInfo: MultisigAccountGraphInfo, cosignatories: string[]): boolean {
80+
private validateCosignatories(graphInfo: MultisigAccountGraphInfo,
81+
cosignatories: string[],
82+
innerTransaction: InnerTransaction): boolean {
7683
/**
7784
* Validate cosignatories from bottom level to top
7885
*/
7986
const sortedKeys = Array.from(graphInfo.multisigAccounts.keys()).sort((a, b) => b - a);
8087
const cosignatoriesReceived = cosignatories;
8188
let validationResult = true;
8289

90+
let isMultisigRemoval = false;
91+
92+
/**
93+
* Check inner transaction. If remove cosigner from multisig account,
94+
* use minRemoval instead of minApproval for cosignatories validation.
95+
*/
96+
if (innerTransaction.type === TransactionType.MODIFY_MULTISIG_ACCOUNT) {
97+
if ((innerTransaction as ModifyMultisigAccountTransaction).modifications
98+
.find((modification) => modification.type === MultisigCosignatoryModificationType.Remove) !== undefined) {
99+
isMultisigRemoval = true;
100+
}
101+
}
102+
83103
sortedKeys.forEach((key) => {
84104
const multisigInfo = graphInfo.multisigAccounts.get(key);
85105
if (multisigInfo && validationResult) {
86106
multisigInfo.forEach((multisig) => {
87-
if (multisig.minApproval >= 1) {
107+
if (multisig.minApproval >= 1 && multisig.minRemoval) { // To make sure it is multisig account
88108
const matchedCosignatories = this.compareArrays(cosignatoriesReceived,
89109
multisig.cosignatories.map((cosig) => cosig.publicKey));
90110

@@ -93,7 +113,8 @@ export class AggregatedTransactionService {
93113
* into the received signatories array for next level validation.
94114
* Otherwise return validation failed.
95115
*/
96-
if (matchedCosignatories.length >= multisig.minApproval) {
116+
if ((matchedCosignatories.length >= multisig.minApproval && !isMultisigRemoval) ||
117+
(matchedCosignatories.length >= multisig.minRemoval && isMultisigRemoval)) {
97118
if (cosignatoriesReceived.indexOf(multisig.account.publicKey) === -1) {
98119
cosignatoriesReceived.push(multisig.account.publicKey);
99120
}

test/service/AggregatedTransactionService.spec.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ import { MultisigAccountInfo } from '../../src/model/account/MultisigAccountInfo
2626
import {NetworkType} from '../../src/model/blockchain/NetworkType';
2727
import { AggregateTransaction } from '../../src/model/transaction/AggregateTransaction';
2828
import { Deadline } from '../../src/model/transaction/Deadline';
29+
import { ModifyMultisigAccountTransaction } from '../../src/model/transaction/ModifyMultisigAccountTransaction';
30+
import { MultisigCosignatoryModification } from '../../src/model/transaction/MultisigCosignatoryModification';
31+
import { MultisigCosignatoryModificationType } from '../../src/model/transaction/MultisigCosignatoryModificationType';
2932
import { PlainMessage } from '../../src/model/transaction/PlainMessage';
3033
import { TransferTransaction } from '../../src/model/transaction/TransferTransaction';
3134
import { AggregatedTransactionService } from '../../src/service/AggregatedTransactionService';
@@ -177,6 +180,30 @@ describe('AggregatedTransactionService', () => {
177180
});
178181
});
179182

183+
it('should use minRemoval for multisig account validation if inner transaction is modify multisig remove', () => {
184+
const modifyMultisigTransaction = ModifyMultisigAccountTransaction.create(
185+
Deadline.create(1, ChronoUnit.HOURS),
186+
1,
187+
1,
188+
[new MultisigCosignatoryModification(
189+
MultisigCosignatoryModificationType.Remove,
190+
account1.publicAccount,
191+
)],
192+
NetworkType.MIJIN_TEST,
193+
);
194+
195+
const aggregateTransaction = AggregateTransaction.createComplete(
196+
Deadline.create(),
197+
[modifyMultisigTransaction.toAggregate(multisig2.publicAccount)],
198+
NetworkType.MIJIN_TEST,
199+
[]);
200+
201+
const signedTransaction = aggregateTransaction.signWith(account2);
202+
aggregatedTransactionService.isComplete(signedTransaction).toPromise().then((isComplete) => {
203+
expect(isComplete).to.be.true;
204+
});
205+
});
206+
180207
it('should return correct isComplete status for aggregated complete transaction - none multisig', () => {
181208
const transferTransaction = TransferTransaction.create(
182209
Deadline.create(1, ChronoUnit.HOURS),

0 commit comments

Comments
 (0)