Skip to content

Commit 4b01819

Browse files
committed
update
1 parent 5ab3a88 commit 4b01819

File tree

1 file changed

+287
-1
lines changed

1 file changed

+287
-1
lines changed

packages/neuron-wallet/tests/services/tx/transaction-sender.test.ts

Lines changed: 287 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -873,7 +873,7 @@ describe('TransactionSender Test', () => {
873873
})
874874
})
875875

876-
describe('#signMultisig', () => {
876+
describe('#signLegacyMultisig', () => {
877877
const transactionObject = {
878878
version: '0x0',
879879
cellDeps: [
@@ -1158,5 +1158,291 @@ describe('TransactionSender Test', () => {
11581158
)
11591159
})
11601160
})
1161+
1162+
describe('#signMultisig', () => {
1163+
const transactionObject = {
1164+
version: '0x0',
1165+
cellDeps: [
1166+
CellDep.fromObject({
1167+
outPoint: OutPoint.fromObject({
1168+
txHash: '0x0d9c4af3dd158d6359c9d25d0a600f1dd20b86072b85a095e7bc70c34509b73d',
1169+
index: '0x0',
1170+
}),
1171+
depType: 'depGroup' as DepType,
1172+
}),
1173+
],
1174+
headerDeps: [],
1175+
inputs: [
1176+
Input.fromObject({
1177+
previousOutput: OutPoint.fromObject({
1178+
txHash: '0x1879851943fa686af29bed5c95acd566d0244e7b3ca89cf7c435622a5a5b4cb3',
1179+
index: '0x0',
1180+
}),
1181+
since: '0x0',
1182+
lock: Script.fromObject({
1183+
args: '',
1184+
codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH,
1185+
hashType: SystemScriptInfo.MULTI_SIGN_HASH_TYPE,
1186+
}),
1187+
}),
1188+
],
1189+
outputs: [
1190+
Output.fromObject({
1191+
capacity: '0x174876e800',
1192+
lock: Script.fromObject({
1193+
codeHash: '0x36c971b8d41fbd94aabca77dc75e826729ac98447b46f91e00796155dddb0d29',
1194+
args: '0xe2193df51d78411601796b35b17b4f8f2cd85bd0',
1195+
hashType: 'type' as ScriptHashType,
1196+
}),
1197+
type: null,
1198+
}),
1199+
Output.fromObject({
1200+
capacity: '0x12319d9962f4',
1201+
lock: Script.fromObject({
1202+
codeHash: '0x36c971b8d41fbd94aabca77dc75e826729ac98447b46f91e00796155dddb0d29',
1203+
args: '0x36c329ed630d6ce750712a477543672adab57f4c',
1204+
hashType: 'type' as ScriptHashType,
1205+
}),
1206+
type: null,
1207+
}),
1208+
],
1209+
outputsData: ['0x', '0x'],
1210+
witnesses: [],
1211+
hash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a86579f1',
1212+
}
1213+
1214+
const createMultisigConfig = (r: number, m: number, addresses: string[]): [string, MultisigConfigModel] => {
1215+
const blake160s = addresses.map(v => addressToScript(v).args)
1216+
const multiArgs = Multisig.hash(blake160s, r, m, addresses.length)
1217+
return [
1218+
multiArgs,
1219+
MultisigConfigModel.fromObject({
1220+
walletId: fakeWallet.id,
1221+
r,
1222+
m,
1223+
n: addresses.length,
1224+
blake160s: addresses.map(v => addressToScript(v).args),
1225+
lockCodeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH,
1226+
}),
1227+
]
1228+
}
1229+
1230+
it('m is 1', async () => {
1231+
const addresses = [
1232+
'ckt1qyq89x5ggpt0a5epm2k2gyxeffwkgfdxeg0s543mh4',
1233+
'ckt1qyqql0vgjyxjxjxknkj6nq8jxa485xsyl66sy7c5f6',
1234+
]
1235+
const [multiArgs, multisigConfig] = createMultisigConfig(1, 1, addresses)
1236+
const addr = {
1237+
walletId: fakeWallet.id,
1238+
path: `m/44'/309'/0'/0/0`,
1239+
blake160: addressToScript(addresses[0]).args,
1240+
version: 'testnet',
1241+
}
1242+
1243+
const mockGAI = jest.fn()
1244+
mockGAI.mockReturnValueOnce([addr])
1245+
transactionSender.getAddressInfos = mockGAI.bind(transactionSender)
1246+
const tx = Transaction.fromObject(transactionObject)
1247+
tx.inputs[0]!.setLock(
1248+
SystemScriptInfo.generateMultiSignScript(multiArgs, SystemScriptInfo.MULTI_SIGN_CODE_HASH)
1249+
)
1250+
const res = await transactionSender.signMultisig(fakeWallet.id, tx, '1234', [multisigConfig])
1251+
expect(res.witnesses[0]).toBe(
1252+
'0x810000001000000081000000810000006d00000000010102729a884056fed321daaca410d94a5d6425a6ca1f0fbd88910d2348d69da5a980f2376a7a1a04feb56b75ef075f1cb4a3e681846c7d8c6ad1575dc5889a2685df215dc566c346757d6d3d46b4201b38f55f87d381fc65e074c1292145fedda1e6d179e6b1052194e200'
1253+
)
1254+
})
1255+
1256+
describe('m is 2', () => {
1257+
const addresses = [
1258+
'ckt1qyq89x5ggpt0a5epm2k2gyxeffwkgfdxeg0s543mh4',
1259+
'ckt1qyqql0vgjyxjxjxknkj6nq8jxa485xsyl66sy7c5f6',
1260+
'ckt1qyqt9wqszk2lurw7h86wrt826cg8zx2f0lnq6e4vpl',
1261+
]
1262+
const [multiArgs, multisigConfig] = createMultisigConfig(1, 2, addresses)
1263+
const addr = {
1264+
walletId: fakeWallet.id,
1265+
path: `m/44'/309'/0'/0/0`,
1266+
blake160: '',
1267+
version: 'testnet',
1268+
}
1269+
1270+
const mockGAI = jest.fn()
1271+
mockGAI.mockReturnValue(
1272+
[addr, addr, addr].map((v, idx) => ({ ...v, blake160: addressToScript(addresses[idx]).args }))
1273+
)
1274+
let tx = Transaction.fromObject(transactionObject)
1275+
it('first sign', async () => {
1276+
const getAddressInfos = transactionSender.getAddressInfos
1277+
transactionSender.getAddressInfos = mockGAI.bind(transactionSender)
1278+
tx.inputs[0]!.setLock(
1279+
SystemScriptInfo.generateMultiSignScript(multiArgs, SystemScriptInfo.MULTI_SIGN_CODE_HASH)
1280+
)
1281+
tx = await transactionSender.signMultisig(fakeWallet.id, tx, '1234', [multisigConfig])
1282+
const lock = (tx.witnesses[0] as WitnessArgs).lock!
1283+
const serializedMultiSign: string = Multisig.serialize(
1284+
addresses.map(v => addressToScript(v).args),
1285+
1,
1286+
2,
1287+
3
1288+
)
1289+
expect(lock.startsWith(serializedMultiSign)).toBeTruthy()
1290+
transactionSender.getAddressInfos = getAddressInfos
1291+
})
1292+
it('second sign', async () => {
1293+
const getAddressInfos = transactionSender.getAddressInfos
1294+
transactionSender.getAddressInfos = mockGAI.bind(transactionSender)
1295+
const res = await transactionSender.signMultisig(fakeWallet.id, tx, '1234', [multisigConfig])
1296+
expect(res.witnesses[0]).toBe(
1297+
'0xd600000010000000d6000000d6000000c200000000010203729a884056fed321daaca410d94a5d6425a6ca1f0fbd88910d2348d69da5a980f2376a7a1a04feb5b2b8101595fe0ddeb9f4e1acead6107119497fe622bca1e7a693dec7beaf28fdde42c60adc1ba0c4e4279bd1b252d6dbf297eb222775697d59f6f14be56411ebe8b1d38e2646410e7d6a77a417f3b54e67fb86e90122bca1e7a693dec7beaf28fdde42c60adc1ba0c4e4279bd1b252d6dbf297eb222775697d59f6f14be56411ebe8b1d38e2646410e7d6a77a417f3b54e67fb86e901'
1298+
)
1299+
transactionSender.getAddressInfos = getAddressInfos
1300+
})
1301+
})
1302+
1303+
it('no matched multisig config, ignore and continue', async () => {
1304+
const showMessageBoxMock = jest
1305+
.spyOn(dialog, 'showMessageBox')
1306+
.mockImplementation(() => Promise.resolve({ response: 1, checkboxChecked: true }))
1307+
mockGAI.mockReturnValueOnce([{ path: '' }])
1308+
transactionSender.getAddressInfos = mockGAI.bind(transactionSender)
1309+
const tx = Transaction.fromObject(transactionObject)
1310+
await expect(transactionSender.signMultisig(fakeWallet.id, tx, '1234', [])).resolves.not.toThrow()
1311+
expect(showMessageBoxMock).toHaveBeenCalled()
1312+
})
1313+
1314+
it('no matched multisig config, throw exception', async () => {
1315+
const showMessageBoxMock = jest
1316+
.spyOn(dialog, 'showMessageBox')
1317+
.mockImplementation(() => Promise.resolve({ response: 0, checkboxChecked: false }))
1318+
mockGAI.mockReturnValueOnce([{ path: '' }])
1319+
transactionSender.getAddressInfos = mockGAI.bind(transactionSender)
1320+
const tx = Transaction.fromObject(transactionObject)
1321+
await expect(transactionSender.signMultisig(fakeWallet.id, tx, '1234', [])).rejects.toThrowError(
1322+
new MultisigConfigNeedError()
1323+
)
1324+
expect(showMessageBoxMock).toHaveBeenCalled()
1325+
})
1326+
1327+
it('throw exception no matched multisig config addresses', async () => {
1328+
const addresses = [
1329+
'ckt1qyq89x5ggpt0a5epm2k2gyxeffwkgfdxeg0s543mh4',
1330+
'ckt1qyqql0vgjyxjxjxknkj6nq8jxa485xsyl66sy7c5f6',
1331+
]
1332+
const noMatchAddress = 'ckt1qyqf5v66n4vrxu75kks2ku06g7trnkdwt52s8000ee'
1333+
const [multiArgs, multisigConfig] = createMultisigConfig(1, 1, addresses)
1334+
const addr = {
1335+
walletId: fakeWallet.id,
1336+
address: noMatchAddress,
1337+
blake160: addressToScript(noMatchAddress).args,
1338+
version: 'testnet',
1339+
}
1340+
1341+
const mockGAI = jest.fn()
1342+
mockGAI.mockReturnValueOnce([addr])
1343+
transactionSender.getAddressInfos = mockGAI.bind(transactionSender)
1344+
1345+
const tx = Transaction.fromObject(transactionObject)
1346+
tx.inputs[0]!.setLock(
1347+
SystemScriptInfo.generateMultiSignScript(multiArgs, SystemScriptInfo.MULTI_SIGN_CODE_HASH)
1348+
)
1349+
await expect(transactionSender.signMultisig(fakeWallet.id, tx, '1234', [multisigConfig])).rejects.toThrow(
1350+
new NoMatchAddressForSign()
1351+
)
1352+
})
1353+
1354+
describe('sign with hard wallet', () => {
1355+
beforeEach(() => {
1356+
stubbedGetWallet.mockReturnValue({
1357+
...fakeWallet,
1358+
isHardware() {
1359+
return true
1360+
},
1361+
})
1362+
})
1363+
1364+
it('m is 1', async () => {
1365+
const witnessLock = '0'.repeat(130)
1366+
stubbedHardWalletGetCurrent.mockReturnValueOnce({
1367+
signTransaction: jest.fn().mockResolvedValueOnce(witnessLock),
1368+
})
1369+
const addresses = [
1370+
'ckt1qyq89x5ggpt0a5epm2k2gyxeffwkgfdxeg0s543mh4',
1371+
'ckt1qyqql0vgjyxjxjxknkj6nq8jxa485xsyl66sy7c5f6',
1372+
]
1373+
const [multiArgs, multisigConfig] = createMultisigConfig(1, 1, addresses)
1374+
const addr = {
1375+
walletId: fakeWallet.id,
1376+
path: `m/44'/309'/0'/0/0`,
1377+
blake160: addressToScript(addresses[0]).args,
1378+
version: 'testnet',
1379+
}
1380+
1381+
const mockGAI = jest.fn()
1382+
mockGAI.mockReturnValueOnce([addr])
1383+
transactionSender.getAddressInfos = mockGAI.bind(transactionSender)
1384+
const tx = Transaction.fromObject(transactionObject)
1385+
tx.inputs[0]!.setLock(
1386+
SystemScriptInfo.generateMultiSignScript(multiArgs, SystemScriptInfo.MULTI_SIGN_CODE_HASH)
1387+
)
1388+
const res = await transactionSender.signMultisig(fakeWallet.id, tx, '1234', [multisigConfig])
1389+
const expectedValue = serializeWitnessArgs({
1390+
inputType: undefined,
1391+
outputType: undefined,
1392+
lock:
1393+
Multisig.serialize(
1394+
addresses.map(v => addressToScript(v).args),
1395+
1,
1396+
1,
1397+
2
1398+
) + witnessLock,
1399+
})
1400+
expect(res.witnesses[0]).toBe(expectedValue)
1401+
})
1402+
})
1403+
1404+
it(`input cell's length is 2`, async () => {
1405+
const addresses = [
1406+
'ckt1qyq89x5ggpt0a5epm2k2gyxeffwkgfdxeg0s543mh4',
1407+
'ckt1qyqql0vgjyxjxjxknkj6nq8jxa485xsyl66sy7c5f6',
1408+
]
1409+
const [multiArgs, multisigConfig] = createMultisigConfig(1, 1, addresses)
1410+
const addr = {
1411+
walletId: fakeWallet.id,
1412+
path: `m/44'/309'/0'/0/0`,
1413+
blake160: addressToScript(addresses[0]).args,
1414+
version: 'testnet',
1415+
}
1416+
1417+
const mockGAI = jest.fn()
1418+
mockGAI.mockReturnValueOnce([addr])
1419+
transactionSender.getAddressInfos = mockGAI.bind(transactionSender)
1420+
const tx = Transaction.fromObject(transactionObject)
1421+
tx.inputs[0]!.setLock(
1422+
SystemScriptInfo.generateMultiSignScript(multiArgs, SystemScriptInfo.MULTI_SIGN_CODE_HASH)
1423+
)
1424+
tx.inputs.push(
1425+
Input.fromObject({
1426+
previousOutput: OutPoint.fromObject({
1427+
txHash: '0x1879851943fa686af29bed5c95acd566d0244e7b3ca89cf7c435622a5a5b4cb3',
1428+
index: '0x0',
1429+
}),
1430+
since: '0x0',
1431+
lock: Script.fromObject({
1432+
args: multiArgs,
1433+
codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH,
1434+
hashType: SystemScriptInfo.MULTI_SIGN_HASH_TYPE,
1435+
}),
1436+
})
1437+
)
1438+
tx.witnesses = ['0x', '0x']
1439+
const res = await transactionSender.signMultisig(fakeWallet.id, tx, '1234', [multisigConfig])
1440+
expect(res.witnesses).toHaveLength(2)
1441+
expect(res.witnesses[1]).toBe('0x')
1442+
expect(res.witnesses[0]).toBe(
1443+
'0x810000001000000081000000810000006d00000000010102729a884056fed321daaca410d94a5d6425a6ca1f0fbd88910d2348d69da5a980f2376a7a1a04feb5ffd5e0f69af2c2f1e2b1f687f9be8e758ae93ba8a8f5178cfaccb947865192f03899004fe92c9f27446bbf4dc86ba5088c55a2df969e1b1c9f9ab43c00c6443c01'
1444+
)
1445+
})
1446+
})
11611447
})
11621448
})

0 commit comments

Comments
 (0)