UNPKG

digibyte

Version:

A pure and powerful JavaScript DigiByte library.

126 lines (116 loc) 5.47 kB
'use strict'; var $ = require('../util/preconditions'); var assetUtils = require('../util/assets'); var IssueFlagsEncoder = require('./issueflagsencoder.js'); var PaymentEncoder = require('./paymentencoder'); var sffc = require('sffc-encoder'); var OP_CODES = [ new Buffer([0x00]), // wild-card to be defined new Buffer([0x01]), // All Hashes in OP_RETURN - Pay-to-PubkeyHash new Buffer([0x02]), // SHA2 in Pay-to-Script-Hash multi-sig output (1 out of 2) new Buffer([0x03]), // All Hashes in Pay-to-Script-Hash multi-sig outputs (1 out of 3) new Buffer([0x04]), // Low security issue no SHA2 for torrent data. SHA1 is always inside OP_RETURN in this case. new Buffer([0x05]), // No rules, no torrent, no meta data ( no one may add rules in the future, anyone can add metadata ) new Buffer([0x06]) // No meta data (anyone can add rules and/or metadata in the future) ]; function IssuanceEncoder(params) { if (!(this instanceof IssuanceEncoder)) { return new IssuanceEncoder(params); } if(params) { this.amount = params.amount; this.lockStatus = params.lockStatus; this.divisibility = params.divisibility; this.aggregationPolicy = params.aggregationPolicy; this.protocol = params.protocol; this.version = params.version; this.payments = params.payments || []; this.torrentHash = params.torrentHash; this.sha2 = params.sha2; this.payments = params.payments; this.noRules = params.noRules; } } IssuanceEncoder.prototype.encode = function(byteSize) { $.checkState(this.amount, 'Amount must be set'); $.checkState(this.lockStatus, 'lockStatus must be set'); $.checkState(this.aggregationPolicy, 'aggregationPolicy must be set'); $.checkState(this.protocol, 'protocol must be set'); $.checkState(this.version, 'version must be set'); var opcode; var hash = new Buffer(0); var protocolBuf = new Buffer(assetUtils.padLeadingZeros(this.protocol.toString(16), 2), 'hex'); var versionBuf = new Buffer([this.version]); var issueHeader = Buffer.concat([protocolBuf, versionBuf]); var amount = sffc.encode(this.amount); var payments = new Buffer(0); if (this.payments) { var bulkEncoder = new PaymentEncoder(); payments = bulkEncoder.encodeBulk(this.payments); } var issueFlagsByte = new IssueFlagsEncoder({ divisibility: this.divisibility, lockStatus: this.lockStatus, aggregationPolicy: this.aggregationPolicy }).encode(); var issueTail = Buffer.concat([amount, payments, issueFlagsByte]); var issueByteSize = issueHeader.length + issueTail.length + 1; if (issueByteSize > byteSize) throw new Error('Data code is bigger then the allowed byte size'); if (!this.sha2) { if (this.torrentHash) { if (issueByteSize + this.torrentHash.length > byteSize) throw new Error('Can\'t fit Torrent Hash in byte size'); return { codeBuffer: Buffer.concat([issueHeader, OP_CODES[4], this.torrentHash, issueTail]), leftover: [] }; } opcode = this.noRules ? OP_CODES[5] : OP_CODES[6]; return { codeBuffer: Buffer.concat([issueHeader, opcode, hash, issueTail]), leftover: [] }; } if (!this.torrentHash) throw new Error('Torrent Hash is missing'); var leftover = [this.torrentHash, this.sha2]; opcode = OP_CODES[3]; issueByteSize = issueByteSize + this.torrentHash.length; if (issueByteSize <= byteSize) { hash = Buffer.concat([hash, leftover.shift()]); opcode = OP_CODES[2]; issueByteSize = issueByteSize + this.sha2.length; } if (issueByteSize <= byteSize) { hash = Buffer.concat([hash, leftover.shift()]); opcode = OP_CODES[1]; } return { codeBuffer: Buffer.concat([issueHeader, opcode, hash, issueTail]), leftover: leftover }; } IssuanceEncoder.prototype.decode = function(op_code_buffer) { var data = {}; if (!Buffer.isBuffer(op_code_buffer)) { op_code_buffer = new Buffer(op_code_buffer, 'hex'); } var byteSize = op_code_buffer.length; var lastByte = op_code_buffer.slice(-1); var issueTail = new IssueFlagsEncoder().decode(assetUtils.consumer(lastByte)); data.divisibility = issueTail.divisibility; data.lockStatus = issueTail.lockStatus; data.aggregationPolicy = issueTail.aggregationPolicy; var consume = assetUtils.consumer(op_code_buffer.slice(0, byteSize - 1)); data.protocol = parseInt(consume(2).toString('hex'), 16); data.version = parseInt(consume(1).toString('hex'), 16); data.multiSig = []; var opcode = consume(1); if (opcode[0] === OP_CODES[1][0]) { data.torrentHash = consume(20); data.sha2 = consume(32); } else if (opcode[0] === OP_CODES[2][0]) { data.torrentHash = consume(20); data.multiSig.push({'index': 1, 'hashType': 'sha2'}); } else if (opcode[0] === OP_CODES[3][0]) { data.multiSig.push({'index': 1, 'hashType': 'sha2'}); data.multiSig.push({'index': 2, 'hashType': 'torrentHash'}); } else if (opcode[0] === OP_CODES[4][0]) { data.torrentHash = consume(20); } else if (opcode[0] === OP_CODES[5][0]) { data.noRules = true; } else if (opcode[0] === OP_CODES[6][0]) { data.noRules = false; } else { throw new Error('Unrecognized Code'); } data.amount = assetUtils.decodeAmountByVersion(data.version, consume, data.divisibility); data.payments = new PaymentEncoder().decodeBulk(consume); return new IssuanceEncoder(data); } module.exports = IssuanceEncoder;