Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

script_number: add impl/tests #516

Merged
merged 5 commits into from
Jan 5, 2016
Merged

script_number: add impl/tests #516

merged 5 commits into from
Jan 5, 2016

Conversation

dcousens
Copy link
Contributor

@dcousens dcousens commented Jan 4, 2016

@jprichardson in working on the spend example for #511 (which I now regret merging without it), I've realised we didn't have a CScriptNum equivalent for script numbers encoded in a stack.

@dcousens dcousens added this to the 2.2.0 milestone Jan 4, 2016
@@ -0,0 +1,225 @@
[
Copy link
Contributor Author

Choose a reason for hiding this comment

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

These fixtures are generated from bitcoin core.
@jprichardson any ideas on how we could increase transparency over this?

A link to a gist that will likely disappear soon isn't great.

@dcousens
Copy link
Contributor Author

dcousens commented Jan 4, 2016

@jprichardson thoughts on bitcoin.script.number.[encode/decode]? See 29a1a83

}

var result

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 couldn't go with the basic for loop construction (as done by bitcoin/bitcoin) here simply because we only have 32-bit integers.

Copy link
Member

Choose a reason for hiding this comment

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

Not sure on 100%, but should work

var result
for (var i = 0; i < length; ++i) {
  result += buffers[i] * Math.pow(2, 8 * 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.

Suffers rounding errors, I tried that initially

Copy link
Member

Choose a reason for hiding this comment

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

How it's possible? Number have 53 bit precision, there only 40 bits.
Can you paste example that give rounding errors?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@fanatid never mind, works fine, will have a look at it again tomorrow.
To avoid the 40-bit special case entirely, I'd need a non-integer/no-bitshifts etc equivalent of the negative handling code (aka, -result on 0x80).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@fanatid I'm thinking when I was testing it, there was other issues that gave me the wrong impression. You are certainly correct that there should not have been issues.

@dcousens
Copy link
Contributor Author

dcousens commented Jan 4, 2016

I'll merge this tomorrow after I add the missing tests for exceptional cases and run a full 1:1 value matching over the 2**32 value space against bitcoin/bitcoin.
Its small enough, so no reason why not. Hopefully the fixtures already cover all the interesting cases anyway.

result |= buffer[i] << (8 * i)
}

if (buffer[length - 1] & 0x80) return -(result & ~(0x80 << (8 * (length - 1))))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@fanatid if you have any ideas on how to apply this to the 40-bit case, then I'll go ahead and generalize the entire thing (yay).

I can add you as a contributor if you want to push to this branch 👍
For me, its sleep time. Will check back in the morning.

Copy link
Member

Choose a reason for hiding this comment

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

I think it should be fine:

if (buffer[length - 1] & 0x80) return -((result / Math.pow(2, 8 * (length - 1) - 1)) | 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.

| 0 will force it to 32-bits again, won't work with 40-bit.
Also, this doesn't work at all anyway, was it meant to be just a drop-in replacement?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@fanatid got the last statement with:

  var b = buffer[length - 1]
  if (b & 0x80) {
    result -= b * Math.pow(2, 8 * (length - 1))

    return -((b & ~0x80) * Math.pow(2, 8 * (length - 1)) + result)
  }

Not really worth it though, the readability is marginal and the performance is almost 50% worse.
With the current code, the difference between when bit-wise operators are OK and the 40-bit special case is explicit.

Copy link
Member

Choose a reason for hiding this comment

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

Agree, bitwise is more readable.

dcousens added a commit that referenced this pull request Jan 5, 2016
script_number: add impl/tests
@dcousens dcousens merged commit 531e624 into master Jan 5, 2016
@dcousens dcousens deleted the scrnum branch January 5, 2016 03:20
@@ -372,6 +372,8 @@ module.exports = {
fromASM: fromASM,
toASM: toASM,

number: require('./script_number'),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jprichardson not going to release this publicly till I get an ACK from you on this (or at least one more contributor)

@jprichardson
Copy link
Member

ACK. Nicely done! Any reasons why you want this in the core repo and not a separate package?

@dcousens
Copy link
Contributor Author

dcousens commented Jan 6, 2016

@jprichardson not specifically, however it does coincide with the idea of being a core-primitive.
I'm not opposed to simply exposing it in this repository however?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants