mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-19 18:45:52 +00:00
Add multi-sign test
This commit is contained in:
378
test/multi-sign-test.js
Normal file
378
test/multi-sign-test.js
Normal file
@@ -0,0 +1,378 @@
|
||||
let assert = require('assert');
|
||||
let _ = require('lodash');
|
||||
let async = require('async');
|
||||
let testutils = require('./testutils');
|
||||
let config = testutils.init_config();
|
||||
let accounts = require('./testconfig').accounts;
|
||||
let Amount = require('ripple-lib').Amount;
|
||||
let Transaction = require('ripple-lib').Transaction;
|
||||
|
||||
suite('MultiSign', function() {
|
||||
let $ = {};
|
||||
let opts = {};
|
||||
|
||||
setup(function(done) {
|
||||
testutils.build_setup(opts).call($, done);
|
||||
});
|
||||
|
||||
setup(function(done) {
|
||||
$.remote.local_signing = false;
|
||||
testutils.create_accounts(
|
||||
$.remote,
|
||||
'root',
|
||||
Amount.from_human('1000 XRP'),
|
||||
['alice', 'bob', 'carol'],
|
||||
done);
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
testutils.build_teardown().call($, done);
|
||||
});
|
||||
|
||||
function getAliceSequence(callback) {
|
||||
return $.remote.account('alice')._transactionManager._nextSequence;
|
||||
}
|
||||
|
||||
test('remote signing', function(done) {
|
||||
async.series([
|
||||
function(callback) {
|
||||
let tx = $.remote.createTransaction('SignerListSet', {
|
||||
account: accounts.alice.account,
|
||||
signers: [
|
||||
{account: accounts.bob.account, weight: 1},
|
||||
{account: accounts.carol.account, weight: 2 }
|
||||
],
|
||||
signerQuorum: 3
|
||||
});
|
||||
|
||||
testutils.submit_transaction(tx, callback);
|
||||
},
|
||||
|
||||
function(callback) {
|
||||
let tx = $.remote.createTransaction('AccountSet', {account: accounts.alice.account});
|
||||
tx.setFee(100);
|
||||
tx.setSequence(getAliceSequence());
|
||||
tx.setLastLedgerSequenceOffset(5);
|
||||
|
||||
let mTx = Transaction.from_json(tx.getMultiSigningJson());
|
||||
|
||||
[accounts.bob, accounts.carol].forEach(account => {
|
||||
let signer = mTx.multiSign( account.account, account.secret);
|
||||
assert(signer.Account);
|
||||
assert(signer.SigningPubKey);
|
||||
assert(signer.TxnSignature);
|
||||
|
||||
tx.addMultiSigner(signer);
|
||||
});
|
||||
|
||||
tx.once('submitted', function(res) {
|
||||
assert.strictEqual(res.engine_result, 'tesSUCCESS');
|
||||
assert.deepEqual(res.tx_json.Signers, tx.getMultiSigners());
|
||||
callback();
|
||||
});
|
||||
|
||||
tx.submit();
|
||||
}
|
||||
], done);
|
||||
});
|
||||
|
||||
test('local signing', function(done) {
|
||||
$.remote.local_signing = true;
|
||||
|
||||
async.series([
|
||||
function(callback) {
|
||||
let tx = $.remote.createTransaction('SignerListSet', {
|
||||
account: accounts.alice.account,
|
||||
signers: [
|
||||
{account: accounts.bob.account, weight: 1},
|
||||
{account: accounts.carol.account, weight: 2 }
|
||||
],
|
||||
signerQuorum: 3
|
||||
});
|
||||
|
||||
testutils.submit_transaction(tx, callback);
|
||||
},
|
||||
|
||||
function(callback) {
|
||||
let tx = $.remote.createTransaction('AccountSet', {account: accounts.alice.account});
|
||||
tx.setFee(100);
|
||||
tx.setSequence(getAliceSequence());
|
||||
tx.setLastLedgerSequenceOffset(5);
|
||||
|
||||
let mTx = Transaction.from_json(tx.getMultiSigningJson());
|
||||
|
||||
[accounts.bob, accounts.carol].forEach(account => {
|
||||
let signer = mTx.multiSign( account.account, account.secret);
|
||||
assert(signer.Account);
|
||||
assert(signer.SigningPubKey);
|
||||
assert(signer.TxnSignature);
|
||||
|
||||
tx.addMultiSigner(signer);
|
||||
});
|
||||
|
||||
tx.once('submitted', function(res) {
|
||||
assert.strictEqual(res.engine_result, 'tesSUCCESS');
|
||||
assert.deepEqual(res.tx_json.Signers, tx.getMultiSigners());
|
||||
callback();
|
||||
});
|
||||
|
||||
tx.submit();
|
||||
}
|
||||
], done);
|
||||
});
|
||||
|
||||
test('No multi-signers specified for account', function(done) {
|
||||
async.series([
|
||||
function(callback) {
|
||||
let tx = $.remote.createTransaction('AccountSet', {account: accounts.alice.account});
|
||||
tx.setFee(100);
|
||||
tx.setSequence(getAliceSequence());
|
||||
tx.setLastLedgerSequenceOffset(5);
|
||||
|
||||
let mTx = Transaction.from_json(tx.getMultiSigningJson());
|
||||
|
||||
let signer = mTx.multiSign(accounts.bob.account, accounts.bob.secret);
|
||||
assert(signer.Account);
|
||||
assert(signer.SigningPubKey);
|
||||
assert(signer.TxnSignature);
|
||||
|
||||
tx.addMultiSigner(signer);
|
||||
|
||||
tx.once('submitted', function(res) {
|
||||
assert.strictEqual(res.engine_result, 'tefNOT_MULTI_SIGNING');
|
||||
callback();
|
||||
});
|
||||
|
||||
tx.submit();
|
||||
}
|
||||
], done);
|
||||
});
|
||||
|
||||
test('Attempt to use unspecified signer', function(done) {
|
||||
async.series([
|
||||
function(callback) {
|
||||
let tx = $.remote.createTransaction('SignerListSet', {
|
||||
account: accounts.alice.account,
|
||||
signers: [
|
||||
{account: accounts.bob.account, weight: 1},
|
||||
],
|
||||
signerQuorum: 1
|
||||
});
|
||||
|
||||
testutils.submit_transaction(tx, callback);
|
||||
},
|
||||
|
||||
function(callback) {
|
||||
let tx = $.remote.createTransaction('AccountSet', {account: accounts.alice.account});
|
||||
tx.setFee(100);
|
||||
tx.setSequence(getAliceSequence());
|
||||
tx.setLastLedgerSequenceOffset(5);
|
||||
|
||||
let mTx = Transaction.from_json(tx.getMultiSigningJson());
|
||||
|
||||
let signer = mTx.multiSign(accounts.carol.account, accounts.carol.secret);
|
||||
assert(signer.Account);
|
||||
assert(signer.SigningPubKey);
|
||||
assert(signer.TxnSignature);
|
||||
|
||||
tx.addMultiSigner(signer);
|
||||
|
||||
tx.once('submitted', function(res) {
|
||||
assert.strictEqual(res.engine_result, 'tefBAD_SIGNATURE');
|
||||
callback();
|
||||
});
|
||||
|
||||
tx.submit();
|
||||
}
|
||||
], done);
|
||||
});
|
||||
|
||||
test('Unmet quorum', function(done) {
|
||||
async.series([
|
||||
function(callback) {
|
||||
let tx = $.remote.createTransaction('SignerListSet', {
|
||||
account: accounts.alice.account,
|
||||
signers: [
|
||||
{account: accounts.bob.account, weight: 1},
|
||||
{account: accounts.carol.account, weight: 1}
|
||||
],
|
||||
signerQuorum: 2
|
||||
});
|
||||
|
||||
testutils.submit_transaction(tx, callback);
|
||||
},
|
||||
|
||||
function(callback) {
|
||||
let tx = $.remote.createTransaction('AccountSet', {account: accounts.alice.account});
|
||||
tx.setFee(100);
|
||||
tx.setSequence(getAliceSequence());
|
||||
tx.setLastLedgerSequenceOffset(5);
|
||||
|
||||
let mTx = Transaction.from_json(tx.getMultiSigningJson());
|
||||
|
||||
let signer = mTx.multiSign(accounts.bob.account, accounts.bob.secret);
|
||||
assert(signer.Account);
|
||||
assert(signer.SigningPubKey);
|
||||
assert(signer.TxnSignature);
|
||||
|
||||
tx.addMultiSigner(signer);
|
||||
|
||||
tx.once('submitted', function(res) {
|
||||
assert.strictEqual(res.engine_result, 'tefBAD_QUORUM');
|
||||
callback();
|
||||
});
|
||||
|
||||
tx.submit();
|
||||
}
|
||||
], done);
|
||||
});
|
||||
|
||||
test('Unreachable quorum', function(done) {
|
||||
async.series([
|
||||
function(callback) {
|
||||
let tx = $.remote.createTransaction('SignerListSet', {
|
||||
account: accounts.alice.account,
|
||||
signers: [
|
||||
{account: accounts.bob.account, weight: 1},
|
||||
],
|
||||
signerQuorum: 2
|
||||
});
|
||||
|
||||
tx.once('submitted', function(res) {
|
||||
assert.strictEqual(res.engine_result, 'temBAD_QUORUM');
|
||||
callback();
|
||||
});
|
||||
tx.submit();
|
||||
},
|
||||
], done);
|
||||
});
|
||||
|
||||
test('Invalid signature -- modified tx_json', function(done) {
|
||||
async.series([
|
||||
function(callback) {
|
||||
let tx = $.remote.createTransaction('SignerListSet', {
|
||||
account: accounts.alice.account,
|
||||
signers: [
|
||||
{account: accounts.bob.account, weight: 1},
|
||||
],
|
||||
signerQuorum: 1
|
||||
});
|
||||
|
||||
testutils.submit_transaction(tx, callback);
|
||||
},
|
||||
|
||||
function(callback) {
|
||||
let tx = $.remote.createTransaction('AccountSet', {account: accounts.alice.account});
|
||||
tx.setFee(100);
|
||||
tx.setSequence(getAliceSequence());
|
||||
tx.setLastLedgerSequenceOffset(5);
|
||||
|
||||
let mTx = Transaction.from_json(tx.getMultiSigningJson());
|
||||
// Tamper with transaction data prior to multi-signing
|
||||
mTx.setSequence(getAliceSequence() + 1);
|
||||
|
||||
let signer = mTx.multiSign(accounts.bob.account, accounts.bob.secret);
|
||||
assert(signer.Account);
|
||||
assert(signer.SigningPubKey);
|
||||
assert(signer.TxnSignature);
|
||||
|
||||
tx.addMultiSigner(signer);
|
||||
|
||||
tx.once('submitted', function(res) {
|
||||
assert(res.error)
|
||||
assert.strictEqual(res.remote.error_message, 'Invalid signature.')
|
||||
callback();
|
||||
});
|
||||
|
||||
tx.submit();
|
||||
}
|
||||
], done);
|
||||
});
|
||||
|
||||
test('Invalid signature -- malformed signer', function(done) {
|
||||
async.series([
|
||||
function(callback) {
|
||||
let tx = $.remote.createTransaction('SignerListSet', {
|
||||
account: accounts.alice.account,
|
||||
signers: [
|
||||
{account: accounts.bob.account, weight: 1},
|
||||
],
|
||||
signerQuorum: 1
|
||||
});
|
||||
|
||||
testutils.submit_transaction(tx, callback);
|
||||
},
|
||||
|
||||
function(callback) {
|
||||
let tx = $.remote.createTransaction('AccountSet', {account: accounts.alice.account});
|
||||
tx.setFee(100);
|
||||
tx.setSequence(getAliceSequence());
|
||||
tx.setLastLedgerSequenceOffset(5);
|
||||
|
||||
let mTx = Transaction.from_json(tx.getMultiSigningJson());
|
||||
|
||||
let signer = mTx.multiSign(accounts.bob.account, accounts.bob.secret);
|
||||
// Tamper with signer after multi-signing
|
||||
signer.Account = accounts.carol.account;
|
||||
|
||||
assert(signer.Account);
|
||||
assert(signer.SigningPubKey);
|
||||
assert(signer.TxnSignature);
|
||||
|
||||
tx.addMultiSigner(signer);
|
||||
|
||||
tx.once('submitted', function(res) {
|
||||
assert(res.error)
|
||||
assert.strictEqual(res.remote.error_message, 'Invalid signature.')
|
||||
callback();
|
||||
});
|
||||
|
||||
tx.submit();
|
||||
}
|
||||
], done);
|
||||
});
|
||||
|
||||
test('Invalid signature -- SigningPubKey non-empty', function(done) {
|
||||
async.series([
|
||||
function(callback) {
|
||||
let tx = $.remote.createTransaction('SignerListSet', {
|
||||
account: accounts.alice.account,
|
||||
signers: [
|
||||
{account: accounts.bob.account, weight: 1},
|
||||
],
|
||||
signerQuorum: 1
|
||||
});
|
||||
|
||||
testutils.submit_transaction(tx, callback);
|
||||
},
|
||||
|
||||
function(callback) {
|
||||
let tx = $.remote.createTransaction('AccountSet', {account: accounts.alice.account});
|
||||
tx.setFee(100);
|
||||
tx.setSequence(getAliceSequence());
|
||||
tx.setLastLedgerSequenceOffset(5);
|
||||
|
||||
let mTx = Transaction.from_json(tx.getMultiSigningJson());
|
||||
|
||||
let signer = mTx.multiSign(accounts.bob.account, accounts.bob.secret);
|
||||
assert(signer.Account);
|
||||
assert(signer.SigningPubKey);
|
||||
assert(signer.TxnSignature);
|
||||
|
||||
tx.addMultiSigner(signer);
|
||||
|
||||
tx.once('presubmit', function(res) {
|
||||
// SigningPubKey must be empty
|
||||
tx.setSigningPubKey(tx.getSigningPubKey());
|
||||
});
|
||||
tx.once('submitted', function(res) {
|
||||
assert(res.error);
|
||||
assert.strictEqual(res.remote.error, 'invalidParams');
|
||||
callback();
|
||||
});
|
||||
|
||||
tx.submit();
|
||||
}
|
||||
], done);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user