-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Segregated Witness Support - WIP #520
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
bitcoin.js | ||
coverage | ||
node_modules | ||
|
||
_dev.*.js | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,30 +6,54 @@ var types = require('./types') | |
|
||
function fromBase58Check (address) { | ||
var payload = bs58check.decode(address) | ||
if (payload.length < 21) throw new TypeError(address + ' is too short') | ||
if (payload.length > 21) throw new TypeError(address + ' is too long') | ||
|
||
var version = payload[0] | ||
var hash = payload.slice(1) | ||
var segWitVersion | ||
var segWitPadding | ||
|
||
return { hash: hash, version: version } | ||
if (hash.length === 22 || hash.length === 34) { | ||
segWitVersion = hash.readUInt8(0) | ||
segWitPadding = hash.readUInt8(1) | ||
hash = hash.slice(2) | ||
|
||
if (segWitVersion > 16 || segWitPadding !== 0) { | ||
throw new Error(address + ' has the length of a segWit address, but is not a valid segWit address') | ||
} | ||
} else if (hash.length > 20) throw new Error(address + ' is too long') | ||
else if (hash.length < 20) throw new Error(address + ' is too short') | ||
|
||
return { hash: hash, version: version, segWitVersion: segWitVersion } | ||
} | ||
|
||
function fromOutputScript (scriptPubKey, network) { | ||
network = network || networks.bitcoin | ||
|
||
if (bscript.isPubKeyHashOutput(scriptPubKey)) return toBase58Check(bscript.compile(scriptPubKey).slice(3, 23), network.pubKeyHash) | ||
if (bscript.isScriptHashOutput(scriptPubKey)) return toBase58Check(bscript.compile(scriptPubKey).slice(2, 22), network.scriptHash) | ||
if (bscript.isSegWitPubKeyHashOutput(scriptPubKey)) return toBase58Check(bscript.compile(scriptPubKey).slice(2, 22), network.segWitPubKeyHash, 0) | ||
if (bscript.isSegWitScriptHashOutput(scriptPubKey)) return toBase58Check(bscript.compile(scriptPubKey).slice(2, 34), network.segWitScriptHash, 0) | ||
|
||
throw new Error(bscript.toASM(scriptPubKey) + ' has no matching Address') | ||
} | ||
|
||
function toBase58Check (hash, version) { | ||
typeforce(types.tuple(types.Hash160bit, types.UInt8), arguments) | ||
function toBase58Check (hash, version, segWitVersion) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It'd be great if we can split out all the address based changes to another PR There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They shelved that proposal until later - pending feedback/proposals from wallet developers IIRC |
||
var payload | ||
var isSegWit = typeof segWitVersion !== 'undefined' | ||
|
||
var payload = new Buffer(21) | ||
payload.writeUInt8(version, 0) | ||
hash.copy(payload, 1) | ||
typeforce(types.tuple((isSegWit ? types.oneOf(types.Hash160bit, types.Hash256bit) : types.Hash160bit), types.UInt8, types.maybe(types.UInt8)), arguments) | ||
|
||
if (isSegWit) { | ||
payload = new Buffer(3 + hash.length) // dynamic size based on hash because of difference between P2WPKH and P2WSH | ||
payload.writeUInt8(version, 0) | ||
payload.writeUInt8(segWitVersion, 1) | ||
payload.writeUInt8(0, 2) // padding byte to make pretty prefixes | ||
hash.copy(payload, 3) | ||
} else { | ||
payload = new Buffer(21) | ||
payload.writeUInt8(version, 0) | ||
hash.copy(payload, 1) | ||
} | ||
|
||
return bs58check.encode(payload) | ||
} | ||
|
@@ -38,8 +62,23 @@ function toOutputScript (address, network) { | |
network = network || networks.bitcoin | ||
|
||
var decode = fromBase58Check(address) | ||
|
||
if (decode.version === network.pubKeyHash) return bscript.pubKeyHashOutput(decode.hash) | ||
if (decode.version === network.scriptHash) return bscript.scriptHashOutput(decode.hash) | ||
if (decode.version === network.segWitPubKeyHash) { | ||
if (decode.segWitVersion === 0) { | ||
if (decode.hash.length === 20) { | ||
return bscript.segWitPubKeyHashOutput(decode.hash) | ||
} | ||
} | ||
} | ||
if (decode.version === network.segWitScriptHash) { | ||
if (decode.segWitVersion === 0) { | ||
if (decode.hash.length === 32) { | ||
return bscript.segWitScriptHashOutput(decode.hash) | ||
} | ||
} | ||
} | ||
|
||
throw new Error(address + ' has no matching Script') | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
var bufferutils = require('./bufferutils') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd rather opt for something like |
||
var typeforce = require('typeforce') | ||
var types = require('./types') | ||
|
||
var BufferWriter = function (length) { | ||
typeforce(types.tuple(types.Number), arguments) | ||
this.buffer = new Buffer(length) | ||
this.offset = 0 | ||
} | ||
|
||
BufferWriter.prototype.writeSlice = function (slice) { | ||
slice.copy(this.buffer, this.offset) | ||
this.offset += slice.length | ||
|
||
return this | ||
} | ||
|
||
BufferWriter.prototype.writeSliceWithVarInt = function (script) { | ||
this.writeVarInt(script.length) | ||
this.writeSlice(script) | ||
|
||
return this | ||
} | ||
|
||
BufferWriter.prototype.writeScript = BufferWriter.prototype.writeSliceWithVarInt | ||
|
||
BufferWriter.prototype.writeInt = function (i) { | ||
this.buffer.writeUInt8(i, this.offset) | ||
this.offset += 1 | ||
|
||
return this | ||
} | ||
|
||
BufferWriter.prototype.writeUInt64 = function (i) { | ||
bufferutils.writeUInt64LE(this.buffer, i, this.offset) | ||
this.offset += 8 | ||
|
||
return this | ||
} | ||
|
||
BufferWriter.prototype.writeUInt32 = function (i) { | ||
this.buffer.writeUInt32LE(i, this.offset) | ||
this.offset += 4 | ||
|
||
return this | ||
} | ||
|
||
BufferWriter.prototype.writeVarInt = function (i) { | ||
var n = bufferutils.writeVarInt(this.buffer, i, this.offset) | ||
this.offset += n | ||
|
||
return this | ||
} | ||
|
||
module.exports = BufferWriter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hope you don't mind, but this makes it easy to keep debug files around
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What debug files?