Skip to content
Snippets Groups Projects
Commit a707ccc5 authored by Cédric Moreau's avatar Cédric Moreau
Browse files

[fix] #905 Have a maximum length for outputs

parent ee360e55
No related branches found
No related tags found
No related merge requests found
...@@ -32,6 +32,7 @@ const IPV4_REGEXP = /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0 ...@@ -32,6 +32,7 @@ const IPV4_REGEXP = /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0
const IPV6_REGEXP = /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b).){3}(b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b))|(([0-9A-Fa-f]{1,4}:){0,5}:((b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b).){3}(b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b))|(::([0-9A-Fa-f]{1,4}:){0,5}((b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b).){3}(b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/; const IPV6_REGEXP = /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b).){3}(b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b))|(([0-9A-Fa-f]{1,4}:){0,5}:((b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b).){3}(b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b))|(::([0-9A-Fa-f]{1,4}:){0,5}((b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b).){3}(b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/;
const MAXIMUM_LEN_OF_COMPACT_TX = 100; const MAXIMUM_LEN_OF_COMPACT_TX = 100;
const MAXIMUM_LEN_OF_OUTPUT = 2000;
module.exports = { module.exports = {
...@@ -91,7 +92,8 @@ module.exports = { ...@@ -91,7 +92,8 @@ module.exports = {
BLOCK_ALREADY_PROCESSED: { httpCode: 400, uerr: { ucode: 2028, message: 'Already processed' }}, BLOCK_ALREADY_PROCESSED: { httpCode: 400, uerr: { ucode: 2028, message: 'Already processed' }},
TOO_OLD_MEMBERSHIP: { httpCode: 400, uerr: { ucode: 2029, message: "Too old membership." }}, TOO_OLD_MEMBERSHIP: { httpCode: 400, uerr: { ucode: 2029, message: "Too old membership." }},
TX_ALREADY_PROCESSED: { httpCode: 400, uerr: { ucode: 2030, message: "Transaction already processed" }}, TX_ALREADY_PROCESSED: { httpCode: 400, uerr: { ucode: 2030, message: "Transaction already processed" }},
A_MORE_RECENT_MEMBERSHIP_EXISTS: { httpCode: 400, uerr: { ucode: 2031, message: "A more recent membership already exists" }} A_MORE_RECENT_MEMBERSHIP_EXISTS: { httpCode: 400, uerr: { ucode: 2031, message: "A more recent membership already exists" }},
MAXIMUM_LEN_OF_OUTPUT: { httpCode: 400, uerr: { ucode: 2032, message: 'A transaction output has a maximum size of ' + MAXIMUM_LEN_OF_OUTPUT + ' characters' }}
}, },
DEBUG: { DEBUG: {
...@@ -309,6 +311,7 @@ module.exports = { ...@@ -309,6 +311,7 @@ module.exports = {
SANDBOX_SIZE_MEMBERSHIPS: 200, SANDBOX_SIZE_MEMBERSHIPS: 200,
MAXIMUM_LEN_OF_COMPACT_TX: MAXIMUM_LEN_OF_COMPACT_TX, MAXIMUM_LEN_OF_COMPACT_TX: MAXIMUM_LEN_OF_COMPACT_TX,
MAXIMUM_LEN_OF_OUTPUT: MAXIMUM_LEN_OF_OUTPUT,
CURRENT_BLOCK_CACHE_DURATION: 10 * 1000, // 30 seconds CURRENT_BLOCK_CACHE_DURATION: 10 * 1000, // 30 seconds
CORES_MAXIMUM_USE_IN_PARALLEL: 8, // For more cores, we need to use a better PoW synchronization algorithm CORES_MAXIMUM_USE_IN_PARALLEL: 8, // For more cores, we need to use a better PoW synchronization algorithm
......
...@@ -112,6 +112,8 @@ Transaction.statics.outputStr2Obj = (outputStr) => { ...@@ -112,6 +112,8 @@ Transaction.statics.outputStr2Obj = (outputStr) => {
}; };
}; };
Transaction.statics.outputObj2Str = (o) => [o.amount, o.base, o.conditions].join(':')
Transaction.statics.setRecipients = (txs) => { Transaction.statics.setRecipients = (txs) => {
// Each transaction must have a good "recipients" field for future searchs // Each transaction must have a good "recipients" field for future searchs
txs.forEach((tx) => tx.recipients = Transaction.statics.outputs2recipients(tx)); txs.forEach((tx) => tx.recipients = Transaction.statics.outputs2recipients(tx));
......
...@@ -300,6 +300,15 @@ rules.FUNCTIONS = { ...@@ -300,6 +300,15 @@ rules.FUNCTIONS = {
throw constants.ERRORS.A_TRANSACTION_HAS_A_MAX_SIZE; throw constants.ERRORS.A_TRANSACTION_HAS_A_MAX_SIZE;
} }
} }
// Check rule against each output of each transaction
for (const tx of txs) {
for (const output of tx.outputs) {
const out = typeof output === 'string' ? output : Transaction.statics.outputObj2Str(output)
if (out.length > constants.MAXIMUM_LEN_OF_OUTPUT) {
throw constants.ERRORS.MAXIMUM_LEN_OF_OUTPUT
}
}
}
return true; return true;
}), }),
......
...@@ -3589,6 +3589,41 @@ module.exports = { ...@@ -3589,6 +3589,41 @@ module.exports = {
"Nonce: 0\n" + "Nonce: 0\n" +
"kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n", "kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n",
OUTPUT_TOO_LONG:
"Version: 10\n" +
"Type: Block\n" +
"Currency: test_net\n" +
"Number: 33520\n" +
"PoWMin: 77\n" +
"Time: 1472124036\n" +
"MedianTime: 1472124036\n" +
"UnitBase: 3\n" +
"Issuer: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk\n" +
"IssuersFrame: 52\n" +
"IssuersFrameVar: -2\n" +
"DifferentIssuersCount: 9\n" +
"PreviousHash: 00001E78E26DD813024EEFBC8F5C50BBA8B30DD1DB5C4F492D9606EE12C06BB4\n" +
"PreviousIssuer: 5ocqzyDMMWf1V8bsoNhWb1iNwax1e9M7VTUN6navs8of\n" +
"MembersCount: 128\n" +
"Identities:\n" +
"Joiners:\n" +
"Actives:\n" +
"Leavers:\n" +
"Revoked:\n" +
"Excluded:\n" +
"Certifications:\n" +
"Transactions:\n" +
"TX:10:1:1:1:1:0:0\n" +
"33518-00001D9E2EA1F967667528817FAF17ECBACE6150EBB875A2196B4457C0366D2A\n" +
"HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk\n" +
"60:3:T:2A74F44780925586EA4C01BEE9DA5042FE8BDB0FB0506B9D69990750B555AC91:15\n" +
"0:SIG(0)\n" +
"60:3:(SIG(EA7Dsw39ShZg4SpURsrgMaMqrweJPUFPYHwZA8e92e3D) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4)|| XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4))\n" +
"ue7NjWPfPXxPNqvlGgr/K4jZjyHlUdYVl6dq+RXJ5RMuu8xBoo6bKhTKOyz/vXZz2clnwV/FqPDdDsWImxCmAg==\n" +
"InnerHash: 1C9EF3BCCBB14DA060F172855D18F7D979FBA752E55BB288E253806E4980E5AC\n" +
"Nonce: 0\n" +
"kNsKdC8eH0d4zdHh1djyMzRXjFrwk3Bc3M8wo4DV/7clE9J66K/U0FljyS79SI78ZZUPaVmrImKJ9SNiubCiBg==\n",
TRANSACTION_WRONG_TRANSFORM: TRANSACTION_WRONG_TRANSFORM:
"Version: 10\n" + "Version: 10\n" +
"Type: Block\n" + "Type: Block\n" +
......
...@@ -70,6 +70,7 @@ describe("Block local coherence", function(){ ...@@ -70,6 +70,7 @@ describe("Block local coherence", function(){
it('Block cannot contain transactions with wrong base transformation', test(rules.LOCAL.checkTxAmounts, blocks.TRANSACTION_WRONG_TRANSFORM, 'Transaction output base amount does not equal previous base deltas')); it('Block cannot contain transactions with wrong base transformation', test(rules.LOCAL.checkTxAmounts, blocks.TRANSACTION_WRONG_TRANSFORM, 'Transaction output base amount does not equal previous base deltas'));
it('Block cannot contain transactions with unexisting lower base in sources', test(rules.LOCAL.checkTxAmounts, blocks.TRANSACTION_WRONG_TRANSFORM_LOW_BASE, 'Transaction output base amount does not equal previous base deltas')); it('Block cannot contain transactions with unexisting lower base in sources', test(rules.LOCAL.checkTxAmounts, blocks.TRANSACTION_WRONG_TRANSFORM_LOW_BASE, 'Transaction output base amount does not equal previous base deltas'));
it('Block cannot contain transactions with more than 100 lines', test(rules.LOCAL.checkTxLen, blocks.TRANSACTION_TOO_LONG, 'A transaction has a maximum size of 100 lines')); it('Block cannot contain transactions with more than 100 lines', test(rules.LOCAL.checkTxLen, blocks.TRANSACTION_TOO_LONG, 'A transaction has a maximum size of 100 lines'));
it('Block cannot contain transactions with a too large output', test(rules.LOCAL.checkTxLen, blocks.OUTPUT_TOO_LONG, 'A transaction output has a maximum size of 2000 characters'));
it('Block cannot be refused with a good V3 transaction', test(rules.LOCAL.checkTxAmounts, blocks.TRANSACTION_V3_GOOD_AMOUNTS)); it('Block cannot be refused with a good V3 transaction', test(rules.LOCAL.checkTxAmounts, blocks.TRANSACTION_V3_GOOD_AMOUNTS));
it('Block cannot contain transactions with wrong signatures', test(rules.LOCAL.checkTxSignature, blocks.TRANSACTION_WITH_WRONG_SIGNATURES, 'Signature from a transaction must match')); it('Block cannot contain transactions with wrong signatures', test(rules.LOCAL.checkTxSignature, blocks.TRANSACTION_WITH_WRONG_SIGNATURES, 'Signature from a transaction must match'));
}); });
...@@ -87,6 +88,7 @@ function test (rule, raw, expectedMessage) { ...@@ -87,6 +88,7 @@ function test (rule, raw, expectedMessage) {
throw 'Test should have thrown an error'; throw 'Test should have thrown an error';
} }
} catch (e) { } catch (e) {
console.error(e.stack || e);
if (!expectedMessage) { if (!expectedMessage) {
console.error(e.stack || e); console.error(e.stack || e);
} }
......
"use strict"; "use strict";
const unlock = require('../../app/lib/ucp/txunlock'); const unlock = require('../../app/lib/ucp/txunlock');
const should = require('should');
describe('Grammar', () => { describe('Grammar', () => {
...@@ -64,5 +65,6 @@ describe('Grammar', () => { ...@@ -64,5 +65,6 @@ describe('Grammar', () => {
unlock('SIG(' + k1 + ') && XHX(' + Ha + ') || XHX(' + Hz + ')', [{ pubkey: k1, sigOK: false },'a','a']).should.equal(false); unlock('SIG(' + k1 + ') && XHX(' + Ha + ') || XHX(' + Hz + ')', [{ pubkey: k1, sigOK: false },'a','a']).should.equal(false);
unlock('SIG(' + k1 + ') && XHX(' + Ha + ') || XHX(' + Hz + ')', [{ pubkey: k1, sigOK: false },'a','z']).should.equal(true); unlock('SIG(' + k1 + ') && XHX(' + Ha + ') || XHX(' + Hz + ')', [{ pubkey: k1, sigOK: false },'a','z']).should.equal(true);
unlock('SIG(' + k1 + ') && XHX(' + Ha + ') || XHX(' + Hz + ')', [{ pubkey: k1, sigOK: false },'z','z']).should.equal(true); unlock('SIG(' + k1 + ') && XHX(' + Ha + ') || XHX(' + Hz + ')', [{ pubkey: k1, sigOK: false },'z','z']).should.equal(true);
unlock('(SIG(EA7Dsw39ShZg4SpURsrgMaMqrweJPUFPYHwZA8e92e3D) || XHX(03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4))', [{ pubkey: k1, sigOK: false },'1234']).should.equal(true);
}); });
}); });
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment