Skip to content
This repository has been archived by the owner on Jun 7, 2019. It is now read-only.

Commit

Permalink
Merge branch '1.0.0' into 542-getTransactionBytes_expand_testsuite
Browse files Browse the repository at this point in the history
  • Loading branch information
Tobias Schwarz committed Mar 1, 2018
2 parents ad2874f + 794a7d4 commit 2d8e7fe
Show file tree
Hide file tree
Showing 15 changed files with 1,759 additions and 4,024 deletions.
5,555 changes: 1,548 additions & 4,007 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
"version": "0.4.5",
"description": "JavaScript library for sending Lisk transactions from the client or server",
"main": "./dist-node/index.js",
"engines": {
"node": ">=6.3 <=9.5",
"npm": ">=3 <=5"
},
"scripts": {
"prestart": "./bin/prestart.sh",
"start": "./bin/start.sh",
Expand Down
3 changes: 3 additions & 0 deletions src/constants/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ export const SSL_PORT = '443';

export const GET = 'GET';
export const POST = 'POST';

// Largest possible address. Derived from bignum.fromBuffer(Buffer.from(new Array(8).fill(255))).
export const MAX_ADDRESS_NUMBER = '18446744073709551615';
15 changes: 14 additions & 1 deletion src/cryptography/convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,20 @@ export const bufferToBigNumberString = bigNumberBuffer =>

export const bufferToHex = buffer => naclInstance.to_hex(buffer);

export const hexToBuffer = hex => Buffer.from(hex, 'hex');
const hexRegex = /^[0-9a-f]+/i;
export const hexToBuffer = hex => {
if (typeof hex !== 'string') {
throw new TypeError('Argument must be a string.');
}
const matchedHex = (hex.match(hexRegex) || [])[0];
if (!matchedHex || matchedHex.length !== hex.length) {
throw new TypeError('Argument must be a valid hex string.');
}
if (matchedHex.length % 2 !== 0) {
throw new TypeError('Argument must have a valid length of hex string.');
}
return Buffer.from(matchedHex, 'hex');
};

export const getFirstEightBytesReversed = publicKeyBytes =>
Buffer.from(publicKeyBytes)
Expand Down
3 changes: 0 additions & 3 deletions src/cryptography/encrypt.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,6 @@ const encryptAES256GCMWithPassword = (plainText, password) => {

const getTagBuffer = tag => {
const tagBuffer = hexToBuffer(tag);
if (bufferToHex(tagBuffer) !== tag) {
throw new Error('Tag must be a hex string.');
}
if (tagBuffer.length !== 16) {
throw new Error('Tag must be 16 bytes.');
}
Expand Down
4 changes: 2 additions & 2 deletions src/transactions/utils/getTransactionBytes.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export const getAssetDataForRegisterSecondSignatureTransaction = ({
}) => {
checkRequiredFields(['publicKey'], signature);
const { publicKey } = signature;
return Buffer.from(publicKey, 'hex');
return cryptography.hexToBuffer(publicKey);
};

export const getAssetDataForRegisterDelegateTransaction = ({ delegate }) => {
Expand Down Expand Up @@ -150,7 +150,7 @@ export const checkTransaction = transaction => {
};

const getTransactionBytes = transaction => {
checkTransaction(transaction);
checkTransaction(transaction);

const {
type,
Expand Down
1 change: 1 addition & 0 deletions src/transactions/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ export {
validatePublicKey,
validatePublicKeys,
validateKeysgroup,
validateAddress,
} from './validation';
export { default as wrapTransactionCreator } from './wrapTransactionCreator';
32 changes: 27 additions & 5 deletions src/transactions/utils/validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,17 @@
* Removal or modification of this copyright notice is prohibited.
*
*/
import { bufferToHex, hexToBuffer } from 'cryptography/convert';
import bignum from 'browserify-bignum';
import { hexToBuffer } from 'cryptography/convert';
import { MAX_ADDRESS_NUMBER } from 'constants';

export const validatePublicKey = publicKey => {
const publicKeyBuffer = hexToBuffer(publicKey);
if (bufferToHex(publicKeyBuffer) !== publicKey) {
throw new Error('Public key must be a valid hex string.');
}
if (publicKeyBuffer.length !== 32) {
throw new Error(
`Public key ${publicKey} length differs from the expected 32 bytes for a public key.`,
);
}

return true;
};

Expand All @@ -47,3 +45,27 @@ export const validateKeysgroup = keysgroup => {
}
return validatePublicKeys(keysgroup);
};

export const validateAddress = address => {
if (address.length < 2 || address.length > 22) {
throw new Error(
'Address length does not match requirements. Expected between 2 and 22 characters.',
);
}

if (address[address.length - 1] !== 'L') {
throw new Error(
'Address format does not match requirements. Expected "L" at the end.',
);
}

const addressAsBignum = bignum(address.slice(0, -1));

if (addressAsBignum.cmp(bignum(MAX_ADDRESS_NUMBER)) > 0) {
throw new Error(
'Address format does not match requirements. Address out of maximum range.',
);
}

return true;
};
5 changes: 5 additions & 0 deletions test/constants/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
EPOCH_TIME,
EPOCH_TIME_SECONDS,
EPOCH_TIME_MILLISECONDS,
MAX_ADDRESS_NUMBER,
} from 'constants';

describe('constants', () => {
Expand Down Expand Up @@ -80,4 +81,8 @@ describe('constants', () => {
it('EPOCH_TIME_MILLISECONDS should be an integer', () => {
return EPOCH_TIME_MILLISECONDS.should.be.an.integer();
});

it('MAX_ADDRESS_NUMBER should be a string', () => {
return MAX_ADDRESS_NUMBER.should.be.type('string');
});
});
42 changes: 42 additions & 0 deletions test/cryptography/convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,48 @@ describe('convert', () => {
const buffer = hexToBuffer(defaultHex);
return buffer.should.be.eql(defaultBuffer);
});

it('should throw TypeError with number', () => {
return hexToBuffer
.bind(null, 123)
.should.throw(TypeError, { message: 'Argument must be a string.' });
});

it('should throw TypeError with object', () => {
return hexToBuffer
.bind(null, {})
.should.throw(TypeError, { message: 'Argument must be a string.' });
});

it('should throw TypeError with non hex string', () => {
return hexToBuffer.bind(null, 'yKJj').should.throw(TypeError, {
message: 'Argument must be a valid hex string.',
});
});

it('should throw TypeError with partially correct hex string', () => {
return hexToBuffer.bind(null, 'Abxzzzz').should.throw(TypeError, {
message: 'Argument must be a valid hex string.',
});
});

it('should throw TypeError with odd number of string with partially correct hex string', () => {
return hexToBuffer.bind(null, 'Abxzzab').should.throw(TypeError, {
message: 'Argument must be a valid hex string.',
});
});

it('should throw TypeError with odd number hex string with invalid hex', () => {
return hexToBuffer.bind(null, '123xxxx').should.throw(TypeError, {
message: 'Argument must be a valid hex string.',
});
});

it('should throw TypeError with odd number of hex string', () => {
return hexToBuffer.bind(null, 'c3a5c3a4c3b6a').should.throw(TypeError, {
message: 'Argument must have a valid length of hex string.',
});
});
});

describe('#getFirstEightBytesReversed', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/cryptography/encrypt.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ describe('encrypt', () => {
)}gg`;
return decryptPassphraseWithPassword
.bind(null, cipherIvSaltTagAndVersion, defaultPassword)
.should.throw('Tag must be a hex string.');
.should.throw('Argument must be a valid hex string.');
});

it('should inform the user if the tag has been altered', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/transactions/3_castVotes.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ describe('#castVotes transaction', () => {
unvotes: unvotePublicKeys,
votes: [plusPrependedPublicKey],
})
.should.throw('Invalid hex string');
.should.throw('Argument must be a valid hex string.');
});
});

Expand Down
2 changes: 1 addition & 1 deletion test/transactions/4_registerMultisignatureAccount.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ describe('#registerMultisignatureAccount transaction', () => {
lifetime,
minimum,
})
.should.throw('Invalid hex string');
.should.throw('Argument must be a valid hex string.');
});
});

Expand Down
50 changes: 50 additions & 0 deletions test/transactions/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,37 @@
*
*/
import {
checkPublicKeysForDuplicates,
getAddressAndPublicKeyFromRecipientData,
getTimeFromBlockchainEpoch,
getTimeWithOffset,
getTransactionBytes,
getTransactionHash,
getTransactionId,
prepareTransaction,
prependMinusToPublicKeys,
prependPlusToPublicKeys,
signRawTransaction,
signTransaction,
multiSignTransaction,
verifyTransaction,
validateAddress,
validateKeysgroup,
validatePublicKey,
validatePublicKeys,
wrapTransactionCreator,
} from 'transactions/utils';

describe('transaction utils', () => {
describe('exports', () => {
it('should have checkPublicKeysForDuplicates', () => {
return checkPublicKeysForDuplicates.should.be.type('function');
});

it('should have getAddressAndPublicKeyFromRecipientData', () => {
return getAddressAndPublicKeyFromRecipientData.should.be.type('function');
});

it('should have getTimeFromBlockchainEpoch', () => {
return getTimeFromBlockchainEpoch.should.be.type('function');
});
Expand All @@ -50,6 +68,18 @@ describe('transaction utils', () => {
return prepareTransaction.should.be.type('function');
});

it('should have prependMinusToPublicKeys', () => {
return prependMinusToPublicKeys.should.be.type('function');
});

it('should have prependPlusToPublicKeys', () => {
return prependPlusToPublicKeys.should.be.type('function');
});

it('should have signRawTransaction', () => {
return signRawTransaction.should.be.type('function');
});

it('should have signTransaction', () => {
return signTransaction.should.be.type('function');
});
Expand All @@ -61,5 +91,25 @@ describe('transaction utils', () => {
it('should have verifyTransaction', () => {
return verifyTransaction.should.be.type('function');
});

it('should have validateAddress', () => {
return validateAddress.should.be.type('function');
});

it('should have validateKeysgroup', () => {
return validateKeysgroup.should.be.type('function');
});

it('should have validatePublicKey', () => {
return validatePublicKey.should.be.type('function');
});

it('should have validatePublicKeys', () => {
return validatePublicKeys.should.be.type('function');
});

it('should have wrapTransactionCreator', () => {
return wrapTransactionCreator.should.be.type('function');
});
});
});
63 changes: 60 additions & 3 deletions test/transactions/utils/validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
validatePublicKey,
validatePublicKeys,
validateKeysgroup,
validateAddress,
} from 'transactions/utils/validation';

describe('public key validation', () => {
Expand All @@ -28,7 +29,7 @@ describe('public key validation', () => {
it('should throw an error', () => {
return validatePublicKey
.bind(null, invalidHexPublicKey)
.should.throw('Invalid hex string');
.should.throw('Argument must have a valid length of hex string.');
});
});

Expand All @@ -38,7 +39,7 @@ describe('public key validation', () => {
it('should throw an error', () => {
return validatePublicKey
.bind(null, invalidHexPublicKey)
.should.throw('Public key must be a valid hex string.');
.should.throw('Argument must be a valid hex string.');
});
});

Expand Down Expand Up @@ -94,7 +95,7 @@ describe('public key validation', () => {
it('should throw an error', () => {
return validatePublicKeys
.bind(null, publicKeys)
.should.throw('Invalid hex string');
.should.throw('Argument must have a valid length of hex string.');
});
});

Expand Down Expand Up @@ -186,4 +187,60 @@ describe('public key validation', () => {
});
});
});

describe('#validateAddress', () => {
describe('Given valid addresses', () => {
const addresses = [
'13133549779353512613L',
'18446744073709551615L',
'1L',
];

it('should return true', () => {
return addresses.forEach(address => {
return validateAddress(address).should.be.true();
});
});
});

describe('Given an address that is too short', () => {
const address = 'L';
const error =
'Address length does not match requirements. Expected between 2 and 22 characters.';

it('should throw', () => {
return validateAddress.bind(null, address).should.throw(error);
});
});

describe('Given an address that is too long', () => {
const address = '12345678901234567890123L';
const error =
'Address length does not match requirements. Expected between 2 and 22 characters.';

it('should throw', () => {
return validateAddress.bind(null, address).should.throw(error);
});
});

describe('Given an address without L at the end', () => {
const address = '1234567890';
const error =
'Address format does not match requirements. Expected "L" at the end.';

it('should throw', () => {
return validateAddress.bind(null, address).should.throw(error);
});
});

describe('Given an address that is out of range', () => {
const address = '18446744073709551616L';
const error =
'Address format does not match requirements. Address out of maximum range.';

it('should throw', () => {
return validateAddress.bind(null, address).should.throw(error);
});
});
});
});

0 comments on commit 2d8e7fe

Please sign in to comment.