tendermint
Version:
A light client which talks to your Tendermint node over RPC
381 lines (316 loc) • 10.6 kB
JavaScript
;
var struct = require('varstruct');
var Int64LE = struct.Int64LE;
var _require = require('./varint.js'),
VarInt = _require.VarInt,
UVarInt = _require.UVarInt;
var VarString = struct.VarString(UVarInt);
var VarBuffer = struct.VarBuffer(UVarInt);
var VarHexBuffer = {
decode: function decode() {
throw Error('Decode not implemented');
},
encode: function encode(value, buffer, offset) {
value = Buffer.from(value, 'hex');
var bytes = VarBuffer.encode(value, buffer, offset);
VarHexBuffer.encode.bytes = VarBuffer.encode.bytes;
return bytes;
},
encodingLength: function encodingLength(value) {
var length = value.length / 2;
return length + UVarInt.encodingLength(length);
}
};
var Time = {
encode: function encode(value, buffer) {
var offset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
if (value[value.length - 1] !== 'Z') {
throw Error('Timestamp must be UTC timezone');
}
var length = Time.encodingLength(value);
buffer = buffer || Buffer.alloc(length);
var _Time$getComponents = Time.getComponents(value),
seconds = _Time$getComponents.seconds,
nanoseconds = _Time$getComponents.nanoseconds;
// seconds field
if (seconds) {
buffer[offset] = 0x08;
UVarInt.encode(seconds, buffer, offset + 1);
offset += UVarInt.encode.bytes + 1;
}
// nanoseconds field
if (nanoseconds) {
buffer[offset] = 0x10;
UVarInt.encode(nanoseconds, buffer, offset + 1);
}
Time.encode.bytes = length;
return buffer;
},
encodingLength: function encodingLength(value) {
var _Time$getComponents2 = Time.getComponents(value),
seconds = _Time$getComponents2.seconds,
nanoseconds = _Time$getComponents2.nanoseconds;
var length = 0;
if (seconds) {
length += 1 + UVarInt.encodingLength(seconds);
}
if (nanoseconds) {
length += 1 + UVarInt.encodingLength(nanoseconds);
}
return length;
},
getComponents: function getComponents(value) {
var millis = new Date(value).getTime();
var seconds = Math.floor(millis / 1000);
// ghetto, we're pulling the nanoseconds from the string
var withoutZone = value.slice(0, -1);
var nanosStr = withoutZone.split('.')[1] || '';
var nanoseconds = Number(nanosStr.padEnd(9, '0'));
return { seconds: seconds, nanoseconds: nanoseconds };
}
};
var BlockID = {
encode: function encode(value, buffer) {
var offset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
var length = BlockID.encodingLength(value);
buffer = buffer || Buffer.alloc(length);
// TODO: actually do amino encoding stuff
// hash field
if (value.hash) {
var hash = Buffer.from(value.hash, 'hex');
buffer[offset + 0] = 0x0a;
buffer[offset + 1] = hash.length;
hash.copy(buffer, offset + 2);
offset += hash.length + 2;
}
// block parts
if (value.parts && value.parts.hash) {
var partsHash = Buffer.from(value.parts.hash, 'hex');
buffer[offset] = 0x12;
buffer[offset + 1] = partsHash.length + 4;
buffer[offset + 2] = 0x08;
buffer[offset + 3] = value.parts.total;
buffer[offset + 4] = 0x12;
buffer[offset + 5] = partsHash.length;
partsHash.copy(buffer, offset + 6);
offset += partsHash.length + 4;
}
CanonicalBlockID.encode.bytes = length;
return buffer;
},
encodingLength: function encodingLength(value) {
var length = 0;
if (value.hash) length += value.hash.length / 2 + 2;
if (value.parts && value.parts.hash) {
length += value.parts.hash.length / 2 + 6;
}
return length;
}
};
var CanonicalBlockID = {
encode: function encode(value, buffer) {
var offset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
var length = CanonicalBlockID.encodingLength(value);
buffer = buffer || Buffer.alloc(length);
// TODO: actually do amino encoding stuff
// hash field
var hash = Buffer.from(value.hash, 'hex');
buffer[offset + 0] = 0x0a;
buffer[offset + 1] = hash.length;
hash.copy(buffer, offset + 2);
offset += hash.length + 2;
// block parts
var partsHash = Buffer.from(value.parts.hash, 'hex');
buffer[offset] = 0x12;
buffer[offset + 1] = partsHash.length + 4;
buffer[offset + 2] = 0x0a;
buffer[offset + 3] = partsHash.length;
partsHash.copy(buffer, offset + 4);
offset += partsHash.length + 4;
buffer[offset] = 0x10;
buffer[offset + 1] = value.parts.total;
CanonicalBlockID.encode.bytes = length;
return buffer;
},
encodingLength: function encodingLength(value) {
return value.hash.length / 2 + value.parts.hash.length / 2 + 8;
}
};
var TreeHashInput = struct([{ name: 'left', type: VarBuffer }, { name: 'right', type: VarBuffer }]);
// TODO: support secp keys (separate prefix)
var pubkeyAminoPrefix = Buffer.from('1624DE6420', 'hex');
var PubKey = {
decode: function decode(buffer) {
var start = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : buffer.length;
throw Error('Decode not implemented');
},
encode: function encode(pub, buffer) {
var offset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
var length = PubKey.encodingLength(pub);
buffer = buffer || Buffer.alloc(length);
if (pub == null) {
buffer[offset] = 0;
} else {
pubkeyAminoPrefix.copy(buffer, offset);
Buffer.from(pub.value, 'base64').copy(buffer, offset + pubkeyAminoPrefix.length);
}
PubKey.encode.bytes = length;
return buffer;
},
encodingLength: function encodingLength(pub) {
if (pub == null) return 1;
return 37;
}
};
var ValidatorHashInput = {
decode: function decode(buffer) {
var start = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : buffer.length;
throw Error('Decode not implemented');
},
encode: function encode(validator) {
var length = ValidatorHashInput.encodingLength(validator);
var buffer = Buffer.alloc(length);
// pubkey field
buffer[0] = 0x0a;
buffer[1] = 0x25;
PubKey.encode(validator.pub_key, buffer, 2);
// TODO: handle pubkeys of different length
// voting power field
buffer[39] = 0x10;
UVarInt.encode(validator.voting_power, buffer, 40);
ValidatorHashInput.encode.bytes = length;
return buffer;
},
encodingLength: function encodingLength(validator) {
return 40 + UVarInt.encodingLength(validator.voting_power);
}
};
var CanonicalVote = {
decode: function decode(buffer) {
var start = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : buffer.length;
throw Error('Decode not implemented');
},
encode: function encode(vote) {
var length = CanonicalVote.encodingLength(vote);
var buffer = Buffer.alloc(length);
var offset = 0;
// type field
if (Number(vote.type)) {
buffer[offset] = 0x08;
buffer.writeUInt8(vote.type, offset + 1);
offset += 2;
}
// height field
if (Number(vote.height)) {
buffer[offset] = 0x11;
Int64LE.encode(vote.height, buffer, offset + 1);
offset += 9;
}
// round field
if (Number(vote.round)) {
buffer[offset] = 0x19;
Int64LE.encode(vote.round, buffer, offset + 1);
offset += 9;
}
// block_id field
if (vote.block_id && vote.block_id.hash) {
buffer[offset] = 0x22;
CanonicalBlockID.encode(vote.block_id, buffer, offset + 2);
buffer[offset + 1] = CanonicalBlockID.encode.bytes;
offset += CanonicalBlockID.encode.bytes + 2;
}
// time field
buffer[offset] = 0x2a;
Time.encode(vote.timestamp, buffer, offset + 2);
buffer[offset + 1] = Time.encode.bytes;
offset += Time.encode.bytes + 2;
// chain_id field
buffer[offset] = 0x32;
buffer.writeUInt8(vote.chain_id.length, offset + 1);
Buffer.from(vote.chain_id).copy(buffer, offset + 2);
CanonicalVote.encode.bytes = length;
return buffer;
},
encodingLength: function encodingLength(vote) {
var length = 0;
// type field
if (Number(vote.type)) {
length += 2;
}
// height field
if (Number(vote.height)) {
length += 9;
}
// round field
if (Number(vote.round)) {
length += 9;
}
// block_id field
if (vote.block_id && vote.block_id.hash) {
length += CanonicalBlockID.encodingLength(vote.block_id) + 2;
}
// time field
length += Time.encodingLength(vote.timestamp) + 2;
// chain_id field
length += vote.chain_id.length + 2;
return length;
}
};
var Version = {
decode: function decode(buffer) {
var start = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : buffer.length;
throw Error('Decode not implemented');
},
encode: function encode(version) {
var length = Version.encodingLength(version);
var buffer = Buffer.alloc(length);
var offset = 0;
var block = Number(version.block);
var app = Number(version.app);
// block field
if (block) {
buffer[offset] = 0x08;
UVarInt.encode(version.block, buffer, offset + 1);
offset += UVarInt.encode.bytes + 1;
}
// app field
if (app) {
buffer[offset] = 0x10;
UVarInt.encode(version.app, buffer, offset + 1);
}
CanonicalVote.encode.bytes = length;
return buffer;
},
encodingLength: function encodingLength(version) {
var block = Number(version.block);
var app = Number(version.app);
var length = 0;
if (block) {
length += UVarInt.encodingLength(version.block) + 1;
}
if (app) {
length += UVarInt.encodingLength(version.app) + 1;
}
return length;
}
};
module.exports = {
VarInt: VarInt,
UVarInt: UVarInt,
VarString: VarString,
VarBuffer: VarBuffer,
VarHexBuffer: VarHexBuffer,
Time: Time,
BlockID: BlockID,
CanonicalBlockID: CanonicalBlockID,
TreeHashInput: TreeHashInput,
ValidatorHashInput: ValidatorHashInput,
PubKey: PubKey,
Int64LE: Int64LE,
CanonicalVote: CanonicalVote,
Version: Version
};