more json improvements.

This commit is contained in:
Christopher Jeffrey 2016-02-23 02:27:10 -08:00
parent 003330e678
commit e5de8db660
10 changed files with 281 additions and 136 deletions

View File

@ -22,8 +22,10 @@ function Block(data, subtype) {
if (!(this instanceof Block))
return new Block(data, subtype);
assert(typeof data.hash !== 'string');
this.type = 'block';
this.subtype = subtype;
this.subtype = subtype || data.subtype;
this.version = data.version;
this.prevBlock = utils.toHex(data.prevBlock);
this.merkleRoot = utils.toHex(data.merkleRoot);
@ -480,6 +482,51 @@ Block.prototype.inspect = function inspect() {
};
Block.prototype.toJSON = function toJSON() {
var json = {
type: 'block',
subtype: this.subtype,
height: this.height,
network: this.network,
relayedBy: this.relayedBy,
hash: utils.revHex(this.hash('hex')),
version: this.version,
prevBlock: utils.revHex(this.prevBlock),
merkleRoot: utils.revHex(this.merkleRoot),
ts: this.ts,
bits: this.bits,
nonce: this.nonce,
totalTX: this.totalTX,
txs: this.txs.map(function(tx) {
return tx.toJSON();
})
};
if (this.subtype === 'headers')
return json;
if (this.subtype === 'merkleblock') {
json.hashes = this.hashes;
json.flags = this.flags;
return json;
}
return json;
};
Block._fromJSON = function _fromJSON(json) {
json.prevBlock = utils.revHex(json.prevBlock);
json.merkleRoot = utils.revHex(json.merkleRoot);
json.txs = json.txs.map(function(tx) {
return bcoin.tx._fromJSON(tx);
});
return json;
};
Block.fromJSON = function fromJSON(json) {
return new Block(Block._fromJSON(json), json.subtype);
};
Block.prototype.toCompact = function toCompact() {
return {
type: 'block',
subtype: this.subtype,
@ -493,8 +540,8 @@ Block.prototype.toJSON = function toJSON() {
};
};
Block.fromJSON = function fromJSON(json) {
var raw, parser, data, block;
Block._fromCompact = function _fromCompact(json) {
var raw, parser, data;
assert.equal(json.type, 'block');
@ -502,53 +549,22 @@ Block.fromJSON = function fromJSON(json) {
parser = new bcoin.protocol.parser();
if (json.subtype === 'merkleblock')
if (json.subtype === 'headers')
data = parser.parseHeaders(raw);
else if (json.subtype === 'merkleblock')
data = parser.parseMerkleBlock(raw);
else if (json.subtype === 'block' || json.subtype === 'header')
else
data = parser.parseBlock(raw);
data.height = json.height;
data.network = json.network;
data.relayedBy = json.relayedBy;
block = new Block(data, json.subtype);
block._hash = json.hash;
return block;
return data;
};
Block.prototype.toFullJSON = function toFullJSON() {
return {
type: 'block',
subtype: this.subtype,
height: this.height,
network: this.network,
relayedBy: this.relayedBy,
hash: utils.revHex(this.hash('hex')),
version: this.version,
prevBlock: utils.revHex(this.prevBlock),
merkleRoot: utils.revHex(this.merkleRoot),
ts: this.ts,
bits: this.bits,
nonce: this.nonce,
txs: this.txs.map(function(tx) {
return tx.toFullJSON();
})
};
};
Block.fromFullJSON = function fromFullJSON(json) {
json.prevBlock = utils.revHex(json.prevBlock);
json.merkleRoot = utils.revHex(json.merkleRoot);
json.txs = json.txs.map(function(tx) {
tx = bcoin.tx.fromFullJSON(tx);
tx.ts = block.ts;
tx.block = block.hash('hex');
tx.height = block.height;
return tx;
});
return new Block(json, json.subtype);
Block.fromCompact = function fromCompact(json) {
return new Block(Block._fromCompact(json), json.subtype);
};
Block.prototype.toRaw = function toRaw(enc) {
@ -556,7 +572,7 @@ Block.prototype.toRaw = function toRaw(enc) {
assert(this.subtype === 'block');
data = new Buffer(this.render());
data = this.render();
if (enc === 'hex')
data = utils.toHex(data);
@ -564,13 +580,17 @@ Block.prototype.toRaw = function toRaw(enc) {
return data;
};
Block.fromRaw = function fromRaw(data, enc) {
Block._fromRaw = function _fromRaw(data, enc) {
var parser = new bcoin.protocol.parser();
if (enc === 'hex')
data = new Buffer(data, 'hex');
return new Block(parser.parseBlock(data), 'block');
return parser.parseBlock(data);
};
Block.fromRaw = function fromRaw(data, enc) {
return new Block(Block._fromRaw(data), 'block');
};
/**

View File

@ -40,6 +40,7 @@ function Coin(tx, index) {
this.spent = false;
} else {
options = tx;
assert(typeof options.script !== 'string');
this.version = options.version;
this.height = options.height;
this.value = options.value;
@ -119,32 +120,6 @@ Coin.prototype.__defineGetter__('age', function() {
});
Coin.prototype.toJSON = function toJSON() {
return {
version: this.version,
height: this.height,
value: utils.btc(this.value),
script: utils.toHex(bcoin.script.encode(this.script)),
hash: this.hash,
index: this.index,
spent: this.spent,
address: this.getAddress()
};
};
Coin.fromJSON = function fromJSON(json) {
return new Coin({
version: json.version,
height: json.height,
value: utils.satoshi(json.value),
script: bcoin.script.decode(new Buffer(json.script, 'hex')),
hash: json.hash,
index: json.index,
spent: json.spent,
address: json.address
});
};
Coin.prototype.toFullJSON = function toFullJSON() {
return {
version: this.version,
height: this.height,
@ -152,22 +127,39 @@ Coin.prototype.toFullJSON = function toFullJSON() {
script: utils.toHex(bcoin.script.encode(this.script)),
hash: utils.revHex(this.hash),
index: this.index,
spent: this.spent,
address: this.getAddress()
spent: this.spent
};
};
Coin.fromFullJSON = function fromFullJSON(json) {
return new Coin({
Coin._fromJSON = function _fromJSON(json) {
return {
version: json.version,
height: json.height,
value: utils.satoshi(json.value),
script: bcoin.script.decode(new Buffer(json.script, 'hex')),
hash: utils.revHex(json.hash),
index: json.index,
spent: json.spent,
address: json.address
});
spent: json.spent
};
};
Coin.fromJSON = function fromJSON(json) {
return new Coin(Coin._fromJSON(json));
};
Coin.prototype.toCompact = function toCompact() {
return {
type: 'coin',
coin: this.toRaw('hex')
};
};
Coin._fromCompact = function _fromCompact(json) {
return Coin._fromRaw(json.coin, 'hex');
};
Coin.fromCompact = function fromCompact(json) {
return new Coin(Coin._fromCompact(json));
};
Coin.prototype.toRaw = function toRaw(enc) {
@ -179,13 +171,19 @@ Coin.prototype.toRaw = function toRaw(enc) {
return data;
};
Coin.fromRaw = function fromRaw(data, enc) {
Coin._fromRaw = function _fromRaw(data, enc) {
var parser = new bcoin.protocol.parser();
if (enc === 'hex')
data = new Buffer(data, 'hex');
data = parser.parseCoin(data, true);
return new Coin(data);
return data;
};
Coin.fromRaw = function fromRaw(data, enc) {
return new Coin(Coin._fromRaw(data, enc));
};
/**

View File

@ -871,7 +871,7 @@ HDPrivateKey.prototype.toJSON = function toJSON(passphrase) {
return json;
};
HDPrivateKey.fromJSON = function fromJSON(json, passphrase) {
HDPrivateKey._fromJSON = function _fromJSON(json, passphrase) {
assert.equal(json.v, 1);
assert.equal(json.name, 'hdkey');
@ -879,23 +879,47 @@ HDPrivateKey.fromJSON = function fromJSON(json, passphrase) {
throw new Error('Cannot decrypt address');
if (json.mnemonic) {
return new HDPrivateKey({
seed: new HDSeed({
return {
seed: {
mnemonic: json.encrypted
? utils.decrypt(json.mnemonic, passphrase)
: json.mnemonic,
passphrase: json.encrypted
? utils.decrypt(json.passphrase, passphrase)
: json.passphrase
})
}
};
}
if (json.xprivkey) {
return {
xprivkey: json.encrypted
? utils.decrypt(json.xprivkey, passphrase)
: json.xprivkey
};
}
if (json.xpubkey) {
return {
xpubkey: json.xpubkey
};
}
assert(false);
};
HDPrivateKey.fromJSON = function fromJSON(json, passphrase) {
json = HDPrivateKey._fromJSON(json, passphrase);
if (json.seed) {
return new HDPrivateKey({
seed: new HDSeed(json.seed)
});
}
if (json.xprivkey) {
return new HDPrivateKey({
xkey: json.encrypted
? utils.decrypt(json.xprivkey, passphrase)
: json.xprivkey
xkey: json.xprivkey
});
}
@ -904,8 +928,6 @@ HDPrivateKey.fromJSON = function fromJSON(json, passphrase) {
xkey: json.xpubkey
});
}
assert(false);
};
/**

View File

@ -106,7 +106,7 @@ HTTPServer.prototype._init = function _init() {
return next(err);
if (!tx)
return send(404);
send(200, tx.toFullJSON());
send(200, tx.toJSON());
});
});
@ -118,7 +118,7 @@ HTTPServer.prototype._init = function _init() {
return next(err);
if (!txs.length)
return send(404);
send(200, txs.map(function(tx) { return tx.toFullJSON(); }));
send(200, txs.map(function(tx) { return tx.toJSON(); }));
});
});
@ -129,7 +129,7 @@ HTTPServer.prototype._init = function _init() {
return next(err);
if (!txs.length)
return send(404);
send(200, txs.map(function(tx) { return tx.toFullJSON(); }));
send(200, txs.map(function(tx) { return tx.toJSON(); }));
});
});
@ -147,7 +147,7 @@ HTTPServer.prototype._init = function _init() {
return next(err);
if (!block)
return send(404);
send(200, block.toFullJSON());
send(200, block.toJSON());
});
});

View File

@ -20,6 +20,8 @@ function Input(options) {
if (!(this instanceof Input))
return new Input(options);
assert(typeof options.script !== 'string');
prevout = options.prevout || options.out;
this.prevout = {
@ -365,28 +367,71 @@ Input.prototype.inspect = function inspect() {
};
};
Input.prototype.toFullJSON = function toFullJSON() {
Input.prototype.toJSON = function toJSON() {
return {
prevout: {
hash: utils.revHex(this.prevout.hash),
index: this.prevout.index
},
output: this.output ? this.output.toFullJSON() : null,
output: this.output ? this.output.toJSON() : null,
script: utils.toHex(bcoin.script.encode(this.script)),
sequence: this.sequence
};
};
Input.fromFullJSON = function fromFullJSON(json) {
return new Input({
Input._fromJSON = function _fromJSON(json) {
return {
prevout: {
hash: utils.revHex(json.prevout.hash),
index: json.prevout.index
},
output: json.output ? bcoin.coin.fromFullJSON(json.output) : null,
output: json.output ? bcoin.coin._fromJSON(json.output) : null,
script: bcoin.script.decode(new Buffer(json.script, 'hex')),
sequence: json.sequence
});
};
};
Input.fromJSON = function fromJSON(json) {
return new Input(Input._fromJSON(json));
};
Input.prototype.toCompact = function toCompact() {
return {
type: 'input',
input: this.toRaw('hex')
};
};
Input._fromCompact = function _fromCompact(json) {
return Input._fromRaw(json.input, 'hex');
};
Input.fromCompact = function fromCompact(json) {
return new Input(Input._fromCompact(json));
};
Input.prototype.toRaw = function toRaw(enc) {
var data = bcoin.protocol.framer.input(this);
if (enc === 'hex')
data = utils.toHex(data);
return data;
};
Input._fromRaw = function _fromRaw(data, enc) {
var parser = new bcoin.protocol.parser();
if (enc === 'hex')
data = new Buffer(data, 'hex');
data = parser.parseInput(data);
return data;
};
Input.fromRaw = function fromRaw(data, enc) {
return new Input(Input._fromRaw(data, enc));
};
/**

View File

@ -161,7 +161,7 @@ KeyPair.toSecret = function toSecret(privateKey, compressed) {
return utils.toBase58(buf);
};
KeyPair.fromSecret = function fromSecret(privateKey) {
KeyPair._fromSecret = function _fromSecret(privateKey) {
var key, compressed;
key = utils.fromBase58(privateKey);
@ -178,10 +178,14 @@ KeyPair.fromSecret = function fromSecret(privateKey) {
compressed = false;
}
return new KeyPair({
return {
privateKey: privateKey,
compressed: compressed
});
};
};
KeyPair.fromSecret = function fromSecret(privateKey) {
return new KeyPair(KeyPair._fromSecret(privateKey));
};
KeyPair.verify = function verify(msg, sig, key) {
@ -215,7 +219,7 @@ KeyPair.prototype.toJSON = function toJSON(passphrase) {
return json;
};
KeyPair.fromJSON = function fromJSON(json, passphrase) {
KeyPair._fromJSON = function _fromJSON(json, passphrase) {
var privateKey, publicKey, compressed;
assert.equal(json.v, 1);
@ -228,21 +232,25 @@ KeyPair.fromJSON = function fromJSON(json, passphrase) {
privateKey = json.privateKey;
if (json.encrypted)
privateKey = utils.decrypt(privateKey, passphrase);
return KeyPair.fromSecret(privateKey);
return KeyPair._fromSecret(privateKey);
}
if (json.publicKey) {
publicKey = utils.fromBase58(json.publicKey);
compressed = publicKey[0] !== 0x04;
return new KeyPair({
return {
publicKey: publicKey,
compressed: compressed
});
};
}
assert(false);
};
KeyPair.fromJSON = function fromJSON(json, passphrase) {
return new KeyPair(KeyPair._fromJSON(json, passphrase));
};
/**
* Expose
*/

View File

@ -20,6 +20,8 @@ function Output(options) {
if (!(this instanceof Output))
return new Output(options);
assert(typeof options.script !== 'string');
value = options.value;
if (typeof value === 'number' && (value | 0) === value)
@ -259,18 +261,61 @@ Output.prototype.inspect = function inspect() {
};
};
Output.prototype.toFullJSON = function toFullJSON() {
Output.prototype.toJSON = function toJSON() {
return {
value: utils.btc(this.value),
script: utils.toHex(bcoin.script.encode(this.script))
};
};
Output.fromFullJSON = function fromFullJSON(json) {
return new Output({
Output._fromJSON = function _fromJSON(json) {
return {
value: utils.satoshi(json.value),
script: bcoin.script.decode(new Buffer(json.script, 'hex'))
});
};
};
Output.fromJSON = function fromJSON(json) {
return new Output(Output._fromJSON(json));
};
Output.prototype.toCompact = function toCompact() {
return {
type: 'output',
output: this.toRaw('hex')
};
};
Output._fromCompact = function _fromCompact(json) {
return Output._fromRaw(json.output, 'hex');
};
Output.fromCompact = function fromCompact(json) {
return new Output(Output._fromCompact(json));
};
Output.prototype.toRaw = function toRaw(enc) {
var data = bcoin.protocol.framer.output(this);
if (enc === 'hex')
data = utils.toHex(data);
return data;
};
Output._fromRaw = function _fromRaw(data, enc) {
var parser = new bcoin.protocol.parser();
if (enc === 'hex')
data = new Buffer(data, 'hex');
data = parser.parseOutput(data);
return data;
};
Output.fromRaw = function fromRaw(data, enc) {
return new Output(Output._fromRaw(data, enc));
};
/**

View File

@ -22,6 +22,8 @@ function TX(data, block) {
if (!data)
data = {};
assert(typeof data.hash !== 'string');
this.type = 'tx';
this.version = data.version || 1;
this.inputs = [];
@ -1799,7 +1801,7 @@ TX.prototype.inspect = function inspect() {
return copy;
};
TX.prototype.toJSON = function toJSON(coins) {
TX.prototype.toCompact = function toCompact(coins) {
return {
type: 'tx',
block: this.block,
@ -1816,7 +1818,7 @@ TX.prototype.toJSON = function toJSON(coins) {
};
};
TX.fromJSON = function fromJSON(json) {
TX._fromCompact = function _fromCompact(json) {
var raw, data, tx;
assert.equal(json.type, 'tx');
@ -1832,21 +1834,23 @@ TX.fromJSON = function fromJSON(json) {
data.relayedBy = json.relayedBy;
data.changeIndex = json.changeIndex;
tx = new TX(data);
if (json.coins) {
json.coins.forEach(function(output, i) {
if (!output)
return;
tx.inputs[i].output = bcoin.coin.fromRaw(output, 'hex');
data.inputs[i].output = bcoin.coin._fromRaw(output, 'hex');
});
}
return tx;
return data;
};
TX.prototype.toFullJSON = function toFullJSON() {
TX.fromCompact = function fromCompact(json) {
return new TX(TX._fromCompact(json));
};
TX.prototype.toJSON = function toJSON() {
return {
type: 'tx',
hash: utils.revHex(this.hash('hex')),
@ -1859,17 +1863,17 @@ TX.prototype.toFullJSON = function toFullJSON() {
changeIndex: this.changeIndex,
version: this.version,
inputs: this.inputs.map(function(input) {
return input.toFullJSON();
return input.toJSON();
}),
outputs: this.outputs.map(function(output) {
return output.toFullJSON();
return output.toJSON();
}),
locktime: this.locktime
};
};
TX.fromFullJSON = function fromFullJSON(json) {
return new TX({
TX._fromJSON = function fromJSON(json) {
return {
block: json.block ? utils.revHex(json.block) : null,
height: json.height,
ts: json.ts,
@ -1879,22 +1883,21 @@ TX.fromFullJSON = function fromFullJSON(json) {
changeIndex: json.changeIndex,
version: json.version,
inputs: json.inputs.map(function(input) {
return bcoin.input.fromFullJSON(input);
return bcoin.input._fromJSON(input);
}),
outputs: json.outputs.map(function(output) {
return bcoin.output.fromFullJSON(output);
return bcoin.output._fromJSON(output);
}),
locktime: json.locktime
});
};
};
TX.fromJSON = function fromJSON(json) {
return new TX(TX._fromJSON(json));
};
TX.prototype.toRaw = function toRaw(enc) {
var data;
if (this.isStatic() && this._raw)
data = this._raw;
else
data = new Buffer(this.render());
var data = this.render();
if (enc === 'hex')
data = utils.toHex(data);
@ -1902,13 +1905,17 @@ TX.prototype.toRaw = function toRaw(enc) {
return data;
};
TX.fromRaw = function fromRaw(data, enc) {
TX._fromRaw = function _fromRaw(data, enc) {
var parser = new bcoin.protocol.parser();
if (enc === 'hex')
data = new Buffer(data, 'hex');
return new bcoin.tx(parser.parseTX(data));
return parser.parseTX(data);
};
TX.fromRaw = function fromRaw(data, enc) {
return new bcoin.tx(TX._fromRaw(data, enc));
};
/**

View File

@ -871,7 +871,7 @@ Wallet.prototype.toJSON = function toJSON(noPool) {
}),
balance: utils.btc(this.getBalance()),
txs: noPool ? [] : this.tx.getAll().map(function(tx) {
return tx.toJSON();
return tx.toCompact();
})
};
};
@ -899,7 +899,7 @@ Wallet._fromJSON = function _fromJSON(json, passphrase) {
addressMap: json.addressMap,
keys: json.keys,
txs: json.txs.map(function(json) {
return bcoin.tx.fromJSON(json);
return bcoin.tx.fromCompact(json);
})
};
};

View File

@ -26,7 +26,7 @@ describe('Block', function() {
'33825657ba32afe269819f01993bd77baba86379043168c94845d32370e53562' ],
flags: [ 245, 90, 0 ]
}, 'merkleblock');
var raw = block.toJSON().block;
var raw = block.toCompact().block;
it('should parse partial merkle tree', function() {
assert(block.verify());
@ -50,10 +50,10 @@ describe('Block', function() {
});
it('should be jsonified and unjsonified and still verify', function() {
var json = block.toJSON();
var json = block.toCompact();
assert.equal(json.subtype, 'merkleblock');
assert.equal(typeof json.block, 'string');
var b = bcoin.block(bcoin.block.fromJSON(json), json.subtype);
var b = bcoin.block.fromCompact(json);
assert.equal(bcoin.utils.toHex(b.render()), json.block);
assert(b.verify());
});