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

Add multiple node.js version support - Closes #561 #562

Merged
merged 8 commits into from
Mar 1, 2018

Conversation

shuse2
Copy link
Contributor

@shuse2 shuse2 commented Feb 14, 2018

Closes #561

Description

  • Changed hexToBuffer behavior to mimic node version >= 8 in all versions.
  • Changed Buffer.from to use hexToBuffer

Note

Run test against

  • v6.12.3
  • v7.10.1
  • v8.9.4
  • v9.5.0

Changes

  • Update all direct usage of Buffer.from(hex, 'hex')
  • Buffer.from(hex, 'hex') should throw Type error if first argument is not string
  • Buffer.from(hex, 'hex') should ignore invalid hex string

package.json Outdated
@@ -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 <=9",
"npm": "=>3 <=5"
Copy link

@AndrewBarba AndrewBarba Feb 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small typo =>3 should be >=3

Copy link
Contributor

@willclarktech willclarktech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests fail on Node.js v6.0.0. I couldn't complete installation on Node.js v8.0.0.

Found some remaining Buffer.froms which should be updated in src:

▶ grep -R -n Buffer.from src
src/crypto/convert.js:37:	return Buffer.from(matchedHex.slice(0, evenLength).join(''), 'hex');
...
src/transactions/utils/getTransactionBytes.js:184:		? Buffer.from(transaction.signature, 'hex')

Additionally there are Buffer.from(xxx, 'hex') cases in test. Maybe we should also be using our function there?

@@ -24,7 +24,18 @@ export const bufferToBigNumberString = bigNumberBuffer =>

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

export const hexToBuffer = hex => Buffer.from(hex, 'hex');
const hexRegex = /([0-9]|[a-f])/gim;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really want multiline?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This regex gives odd behaviour.

> Buffer.from('abhcd', 'hex')
// Node 6: throws 'Invalid hex string'
<Buffer ab> // Node 8
> hexToBuffer('abhcd')
<Buffer abcd>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will be changed to take only first part =)

it('should create even numbered Buffer from odd number hex string', () => {
const buffer = hexToBuffer('c3a5c3a4c3b6a');
return buffer.should.be.eql(Buffer.from('c3a5c3a4c3b6', 'hex'));
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a test case where there's a non-hex character in the middle of hex characters.

@@ -65,6 +65,22 @@ describe('convert', () => {
const buffer = hexToBuffer(defaultHex);
return buffer.should.be.eql(defaultBuffer);
});
it('should create empty Buffer from non-string', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it? Node 6 and 8 both throw errors if you use a number for example.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will be changed to throw type error if it's not string

@shuse2
Copy link
Contributor Author

shuse2 commented Feb 15, 2018

I think the Buffer.from used in the test is the controlled variable, which shouldn't throw error, so not really necessary to change there

@shuse2
Copy link
Contributor Author

shuse2 commented Feb 15, 2018

Until node v6.3.0, createCipheriv with "aes-256-gcm" did not allow IV to be longer than 12 bytes.
but changed in
nodejs/node#6376
In our code, we use 16 bytes, so changed engine to start from 6.3

@willclarktech
Copy link
Contributor

Whoops, sorry just realised one of my Buffer.from finds in src was for the hexToBuffer function which obviously needs to remain.

Copy link
Contributor

@willclarktech willclarktech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still need to consider npm. I get an installation failure with npm v5.0.0.

@@ -24,7 +24,18 @@ export const bufferToBigNumberString = bigNumberBuffer =>

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

export const hexToBuffer = hex => Buffer.from(hex, 'hex');
const hexRegex = /^([0-9]|[a-f])+/gi;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make this regex as simple as possible. Does the following work?

const hexRegex = /^[0-9a-f]+/i;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think global key is not needed but ^([0-9]|[a-f]) this is more readable isn't it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, a capturing group which never gets used is confusing.

package.json Outdated
@@ -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",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should put an upper bound on the latest version of 9 that we've tested.

const hexRegex = /^([0-9]|[a-f])+/gi;
export const hexToBuffer = hex => {
if (typeof hex !== 'string') {
throw new TypeError('argument must be string');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Argument must be a string

throw new TypeError('argument must be string');
}
const matchedHex = hex.match(hexRegex) || [];
if (matchedHex.length === 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just this?

const matchedHex = hex.match(hexRegex);
if (!matchedHex) {
    return Buffer.alloc(0);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the following code, it uses first element like matchedHex[0], so I think it would be better to check length here already

it('should create even numbered Buffer from odd number hex string', () => {
const buffer = hexToBuffer('c3a5c3a4c3b6a');
return buffer.should.be.eql(Buffer.from('c3a5c3a4c3b6', 'hex'));
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would also be good to have a test case with a valid odd-numbered hex string followed by non-hex. Eg. 123xxx and/or 123x.

@shuse2
Copy link
Contributor Author

shuse2 commented Feb 16, 2018

I get an installation failure with npm v5.0.0.

this was solved by install without cache.

willclarktech
willclarktech previously approved these changes Feb 16, 2018
@shuse2 shuse2 force-pushed the 561-support_multiple_node_version branch 2 times, most recently from fee66fb to 11e2f25 Compare February 16, 2018 17:04
@@ -65,6 +65,36 @@ describe('convert', () => {
const buffer = hexToBuffer(defaultHex);
return buffer.should.be.eql(defaultBuffer);
});
it('should throw TypeError with number', () => {
return (() => hexToBuffer(123)).should.throw(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer hexToBuffer.bind(null, 123).should.throw syntax.

@@ -65,6 +65,36 @@ describe('convert', () => {
const buffer = hexToBuffer(defaultHex);
return buffer.should.be.eql(defaultBuffer);
});
it('should throw TypeError with number', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer an empty line between its.

@@ -65,6 +65,36 @@ describe('convert', () => {
const buffer = hexToBuffer(defaultHex);
return buffer.should.be.eql(defaultBuffer);
});
it('should throw TypeError with number', () => {
return (() => hexToBuffer(123)).should.throw(
new TypeError('argument must be string'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test gives false positives: the message is wrong here.

willclarktech
willclarktech previously approved these changes Feb 22, 2018
Copy link
Contributor

@willclarktech willclarktech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would like some more extensive testing on different versions, but this looks good to me. 👍

@@ -24,7 +24,18 @@ 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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

return Buffer.alloc(0);
}
const evenLength = Math.floor(matchedHex.length / 2) * 2;
return Buffer.from(matchedHex.slice(0, evenLength), 'hex');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it is better to return a sliced element here rather than throwing an error in case it is not even?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same applies to non-hex strings

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think main reason not to throw an error for non-even input is because node 8 is not behaving like that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, for the non-hex string, node 8 ignores the non hex string, and create the buffer from whatever it can from the front.

> process.version
'v8.9.4'
> Buffer.from('abcde', 'hex');
<Buffer ab cd>
> Buffer.from('abcdzz123', 'hex');
<Buffer ab cd>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But this is our opportunity to make the behaviour we actually want.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nodejs/node#12012 (comment)
I think main thing is that parallel behavior with base64 and coherent eror handlings of various things it can happen

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually the sentiment seems to be like "you can do validation on your side if you want" on the node side of things: nodejs/node#8569

And in my opinion I would prefer to have an error thrown.

@toschdev toschdev merged commit 794a7d4 into 1.0.0 Mar 1, 2018
@toschdev toschdev deleted the 561-support_multiple_node_version branch March 1, 2018 08:32
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants