From 95e0e5a4f7825c81f30af765307d6d4ea513464d Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 05:26:13 -0300 Subject: [PATCH 01/21] remove unneeded files --- lib/strategies/base.js | 300 ------------------------- lib/strategies/disk.js | 142 ------------ lib/strategies/historic.js | 435 ------------------------------------- lib/strategies/peer.js | 150 ------------- ws/index.js | 73 ------- 5 files changed, 1100 deletions(-) delete mode 100644 lib/strategies/base.js delete mode 100644 lib/strategies/disk.js delete mode 100644 lib/strategies/historic.js delete mode 100644 lib/strategies/peer.js delete mode 100644 ws/index.js diff --git a/lib/strategies/base.js b/lib/strategies/base.js deleted file mode 100644 index 36b0fa7d..00000000 --- a/lib/strategies/base.js +++ /dev/null @@ -1,300 +0,0 @@ -'use strict'; - -var imports = require('soop').imports(); - -var config = imports.config || require('../config/config'); -var bitcore = require('bitcore'); -var networks = bitcore.networks; -var async = require('async'); - -var logger = require('./logger').logger; -var d = logger.log; -var info = logger.info; - - - -var syncId = 0; - -function Sync(opts) { - this.id = syncId++; - this.opts = opts || {}; - this.bDb = require('./BlockDb').default(); - this.txDb = require('./TransactionDb').default(); - this.network = config.network === 'testnet' ? networks.testnet : networks.livenet; - this.cachedLastHash = null; -} - -Sync.prototype.close = function(cb) { - var self = this; - self.txDb.close(function() { - self.bDb.close(cb); - }); -}; - - -Sync.prototype.destroy = function(next) { - var self = this; - async.series([ - - function(b) { - self.bDb.drop(b); - }, - function(b) { - self.txDb.drop(b); - }, - ], next); -}; - -/* - * Arrives a NEW block, which is the new TIP - * - * Case 0) Simple case - * A-B-C-D-E(TIP)-NEW - * - * Case 1) - * A-B-C-D-E(TIP) - * \ - * NEW - * - * 1) Declare D-E orphans (and possible invalidate TXs on them) - * - * Case 2) - * A-B-C-D-E(TIP) - * \ - * F-G-NEW - * 1) Set F-G as connected (mark TXs as valid) - * 2) Set new heights in F-G-NEW - * 3) Declare D-E orphans (and possible invalidate TXs on them) - * - * - * Case 3) - * - * A-B-C-D-E(TIP) ... NEW - * - * NEW is ignored (if allowReorgs is false) - * - * - */ - -Sync.prototype.storeTipBlock = function(b, allowReorgs, cb) { - - if (typeof allowReorgs === 'function') { - cb = allowReorgs; - allowReorgs = true; - } - if (!b) return cb(); - var self = this; - - if ( self.storingBlock ) { - logger.debug('Storing a block already. Delaying storeTipBlock with:' + - b.hash); - return setTimeout( function() { - logger.debug('Retrying storeTipBlock with: ' + b.hash); - self.storeTipBlock(b,allowReorgs,cb); - }, 1000); - } - - self.storingBlock=1; - var oldTip, oldNext, oldHeight, needReorg = false, height = -1; - var newPrev = b.previousblockhash; - async.series([ - - // This seems unnecesary. - // function(c) { - // // TODO? remove this check? - // self.bDb.has(b.hash, function(err, val) { - // return c(err || - // (val ? new Error('WARN: Ignoring already existing block:' + b.hash) : null)); - // }); - // }, - function(c) { - if (!allowReorgs || newPrev === self.cachedLastHash) return c(); - self.bDb.has(newPrev, function(err, val) { - // Genesis? no problem - if (!val && newPrev.match(/^0+$/)) return c(); - return c(err || - (!val ? new Error('NEED_SYNC Ignoring block with non existing prev:' + b.hash) : null)); - }); - }, - function(c) { - if (!allowReorgs) return c(); - self.bDb.getTip(function(err, hash, h) { - oldTip = hash; - oldHeight = hash ? (h || 0) : -1 - if (oldTip && newPrev !== oldTip) { - needReorg = true; - logger.debug('REORG Triggered, tip mismatch'); - } - return c(); - }); - }, - - function(c) { - if (!needReorg) return c(); - self.bDb.getNext(newPrev, function(err, val) { - if (err) return c(err); - oldNext = val; - return c(); - }); - }, - function(c) { - if (!allowReorgs) return c(); - if (needReorg) { - info('NEW TIP: %s NEED REORG (old tip: %s #%d)', b.hash, oldTip, oldHeight); - self.processReorg(oldTip, oldNext, newPrev, oldHeight, function(err, h) { - if (err) throw err; - - height = h; - return c(); - }); - } - else { - height = oldHeight + 1; - return c(); - } - }, - function(c) { - self.cachedLastHash = b.hash; // just for speed up. - self.bDb.add(b, height, c); - }, - function(c) { - if (!allowReorgs) return c(); - self.bDb.setTip(b.hash, height, function(err) { - return c(err); - }); - }, - function(c) { - self.bDb.setNext(newPrev, b.hash, function(err) { - return c(err); - }); - } - - ], - function(err) { - if (err && err.toString().match(/WARN/)) { - err = null; - } - self.storingBlock=0; - return cb(err, height); - }); -}; - -Sync.prototype.processReorg = function(oldTip, oldNext, newPrev, oldHeight, cb) { - var self = this; - - var orphanizeFrom, newHeight; - - async.series([ - - function(c) { - self.bDb.getHeight(newPrev, function(err, height) { - if (!height) { - // Case 3 + allowReorgs = true - return c(new Error('Could not found block:' + newPrev)); - } - if (height<0) return c(); - - newHeight = height + 1; - info('Reorg Case 1) OldNext: %s NewHeight: %d', oldNext, newHeight); - orphanizeFrom = oldNext; - return c(err); - }); - }, - function(c) { - if (orphanizeFrom) return c(); - - info('Reorg Case 2)'); - self.setBranchConnectedBackwards(newPrev, function(err, yHash, newYHashNext, height) { - if (err) return c(err); - newHeight = height; - self.bDb.getNext(yHash, function(err, yHashNext) { - // Connect the new branch, and orphanize the old one. - orphanizeFrom = yHashNext; - self.bDb.setNext(yHash, newYHashNext, function(err) { - return c(err); - }); - }); - }); - }, - function(c) { - if (!orphanizeFrom) return c(); - self._setBranchOrphan(orphanizeFrom, function(err) { - return c(err); - }); - }, - ], - function(err) { - return cb(err, newHeight); - }); -}; - -Sync.prototype._setBranchOrphan = function(fromHash, cb) { - var self = this, - hashInterator = fromHash; - - async.whilst( - function() { - return hashInterator; - }, - function(c) { - self.bDb.setBlockNotMain(hashInterator, function(err) { - if (err) return cb(err); - self.bDb.getNext(hashInterator, function(err, val) { - hashInterator = val; - return c(err); - }); - }); - }, cb); -}; - -Sync.prototype.setBranchConnectedBackwards = function(fromHash, cb) { - //console.log('[Sync.js.219:setBranchConnectedBackwards:]',fromHash); //TODO - var self = this, - hashInterator = fromHash, - lastHash = fromHash, - yHeight, - branch = []; - - async.doWhilst( - function(c) { - branch.unshift(hashInterator); - - self.bDb.getPrev(hashInterator, function(err, val) { - if (err) return c(err); - lastHash = hashInterator; - hashInterator = val; - self.bDb.getHeight(hashInterator, function(err, height) { - yHeight = height; - return c(); - }); - }); - }, - function() { - return hashInterator && yHeight<=0; - }, - function() { - info('\tFound yBlock: %s #%d', hashInterator, yHeight); - var heightIter = yHeight + 1; - var hashIter; - async.whilst( - function() { - hashIter = branch.shift(); - return hashIter; - }, - function(c) { - self.bDb.setBlockMain(hashIter, heightIter++, c); - }, - function(err) { - return cb(err, hashInterator, lastHash, heightIter); - }); - }); -}; - - -//Store unconfirmed TXs -Sync.prototype.storeTx = function(tx, cb) { - this.txDb.add(tx, cb); -}; - - -module.exports = require('soop')(Sync); diff --git a/lib/strategies/disk.js b/lib/strategies/disk.js deleted file mode 100644 index 3c698246..00000000 --- a/lib/strategies/disk.js +++ /dev/null @@ -1,142 +0,0 @@ -'use strict'; -var bitcore = require('bitcore'), - Block = bitcore.Block, - networks = bitcore.networks, - Parser = bitcore.BinaryParser, - fs = require('fs'), - Buffer = bitcore.Buffer, - glob = require('glob'), - async = require('async'); - -function BlockExtractor(dataDir, network) { - var path = dataDir + '/blocks/blk*.dat'; - - this.dataDir = dataDir; - this.files = glob.sync(path); - this.nfiles = this.files.length; - - if (this.nfiles === 0) - throw new Error('Could not find block files at: ' + path); - - this.currentFileIndex = 0; - this.isCurrentRead = false; - this.currentBuffer = null; - this.currentParser = null; - this.network = network === 'testnet' ? networks.testnet: networks.livenet; - this.magic = this.network.magic.toString('hex'); -} - -BlockExtractor.prototype.currentFile = function() { - return this.files[this.currentFileIndex]; -}; - - -BlockExtractor.prototype.nextFile = function() { - if (this.currentFileIndex < 0) return false; - - var ret = true; - - this.isCurrentRead = false; - this.currentBuffer = null; - this.currentParser = null; - - if (this.currentFileIndex < this.nfiles - 1) { - this.currentFileIndex++; - } - else { - this.currentFileIndex=-1; - ret = false; - } - return ret; -}; - -BlockExtractor.prototype.readCurrentFileSync = function() { - if (this.currentFileIndex < 0 || this.isCurrentRead) return; - - this.isCurrentRead = true; - - var fname = this.currentFile(); - if (!fname) return; - - - var stats = fs.statSync(fname); - - var size = stats.size; - - console.log('Reading Blockfile %s [%d MB]', - fname, parseInt(size/1024/1024)); - - var fd = fs.openSync(fname, 'r'); - - var buffer = new Buffer(size); - - fs.readSync(fd, buffer, 0, size, 0); - - this.currentBuffer = buffer; - this.currentParser = new Parser(buffer); -}; - - - - -BlockExtractor.prototype._getMagic = function() { - if (!this.currentParser) - return null; - - var byte0 = this.currentParser ? this.currentParser.buffer(1).toString('hex') : null; - - - - // Grab 3 bytes from block without removing them - var p = this.currentParser.pos; - var bytes123 = this.currentParser.subject.toString('hex',p,p+3); - var magic = byte0 + bytes123; - - if (magic !=='00000000' && magic !== this.magic) { - if(this.errorCount++ > 4) - throw new Error('CRITICAL ERROR: Magic number mismatch: ' + - magic + '!=' + this.magic); - magic=null; - } - - if (magic==='00000000') - magic =null; - - return magic; -}; - -BlockExtractor.prototype.getNextBlock = function(cb) { - var b; - var magic; - var isFinished = 0; - - while(!magic && !isFinished) { - this.readCurrentFileSync(); - magic= this._getMagic(); - - if (!this.currentParser || this.currentParser.eof() ) { - - if (this.nextFile()) { - console.log('Moving forward to file:' + this.currentFile() ); - magic = null; - } else { - console.log('Finished all files'); - isFinished = 1; - } - } - } - if (isFinished) - return cb(); - - // Remove 3 bytes from magic and spacer - this.currentParser.buffer(3+4); - - b = new Block(); - b.parse(this.currentParser); - b.getHash(); - this.errorCount=0; - return cb(null,b); -}; - -module.exports = require('soop')(BlockExtractor); - diff --git a/lib/strategies/historic.js b/lib/strategies/historic.js deleted file mode 100644 index 4ee57bab..00000000 --- a/lib/strategies/historic.js +++ /dev/null @@ -1,435 +0,0 @@ -'use strict'; - -var imports = require('soop').imports(); -var util = require('util'); -var async = require('async'); - -var bitcore = require('bitcore'); -var networks = bitcore.networks; -var config = imports.config || require('../config/config'); -var Sync = require('./Sync'); -var sockets = require('../app/controllers/socket.js'); -var BlockExtractor = require('./BlockExtractor.js'); -var buffertools = require('buffertools'); -var bitcoreUtil = bitcore.util; -var logger = require('./logger').logger; -var info = logger.info; -var error = logger.error; -var PERCENTAGE_TO_START_FROM_RPC = 0.96; - -var BAD_GEN_ERROR = 'Bad genesis block. Network mismatch between bitcore-node and bitcoind? bitcore-node is configured for:'; -var BAD_GEN_ERROR_DB = 'Bad genesis block. Network mismatch between bitcore-node and levelDB? bitcore-node is configured for:'; - -function HistoricSync(opts) { - opts = opts || {}; - this.shouldBroadcast = opts.shouldBroadcastSync; - - this.network = config.network === 'testnet' ? networks.testnet: networks.livenet; - - var genesisHashReversed = new Buffer(32); - this.network.genesisBlock.hash.copy(genesisHashReversed); - buffertools.reverse(genesisHashReversed); - this.genesis = genesisHashReversed.toString('hex'); - - var bitcore = require('bitcore'); - var RpcClient = bitcore.RpcClient; - - this.rpc = new RpcClient(config.bitcoind); - this.sync = new Sync(opts); - this.height =0; -} - -HistoricSync.prototype.showProgress = function() { - var self = this; - - if ( self.status ==='syncing' && - ( self.height ) % self.step !== 1) return; - - if (self.error) - error(self.error); - - else { - self.updatePercentage(); - info(util.format('status: [%d%%]', self.syncPercentage)); - } - if (self.shouldBroadcast) { - sockets.broadcastSyncInfo(self.info()); - } - // - // if (self.syncPercentage > 10) { - // process.exit(-1); - // } -}; - - -HistoricSync.prototype.setError = function(err) { - var self = this; - self.error = err.message?err.message:err.toString(); - self.status='error'; - self.showProgress(); - return err; -}; - - - -HistoricSync.prototype.close = function() { - this.sync.close(); -}; - - -HistoricSync.prototype.info = function() { - this.updatePercentage(); - return { - status: this.status, - blockChainHeight: this.blockChainHeight, - syncPercentage: this.syncPercentage, - height: this.height, - syncTipHash: this.sync.tip, - error: this.error, - type: this.type, - startTs: this.startTs, - endTs: this.endTs, - }; -}; - -HistoricSync.prototype.updatePercentage = function() { - var r = this.height / this.blockChainHeight; - this.syncPercentage = parseFloat(100 * r).toFixed(3); - if (this.syncPercentage > 100) this.syncPercentage = 100; -}; - -HistoricSync.prototype.getBlockFromRPC = function(cb) { - var self = this; - - if (!self.currentRpcHash) return cb(); - - var blockInfo; - self.rpc.getBlock(self.currentRpcHash, function(err, ret) { - if (err) return cb(err); - if (ret) { - blockInfo = ret.result; - // this is to match block retreived from file - if (blockInfo.hash === self.genesis) - blockInfo.previousblockhash = - self.network.genesisBlock.prev_hash.toString('hex'); - - self.currentRpcHash = blockInfo.nextblockhash; - } - else { - blockInfo = null; - } - return cb(null, blockInfo); - }); -}; - -HistoricSync.prototype.getStandardizedBlock = function(b) { - var self = this; - - var block = { - hash: bitcoreUtil.formatHashFull(b.getHash()), - previousblockhash: bitcoreUtil.formatHashFull(b.prev_hash), - time: b.timestamp, - }; - var isCoinBase = 1; - block.tx = b.txs.map(function(tx){ - var ret = self.sync.txDb.getStandardizedTx(tx, b.timestamp, isCoinBase); - isCoinBase=0; - return ret; - }); - return block; -}; - -HistoricSync.prototype.getBlockFromFile = function(cb) { - var self = this; - - var blockInfo; - - //get Info - self.blockExtractor.getNextBlock(function(err, b) { - if (err || ! b) return cb(err); - blockInfo = self.getStandardizedBlock(b); - self.sync.bDb.setLastFileIndex(self.blockExtractor.currentFileIndex, function(err) { - return cb(err,blockInfo); - }); - }); -}; - -HistoricSync.prototype.updateBlockChainHeight = function(cb) { - var self = this; - - self.rpc.getBlockCount(function(err, res) { - self.blockChainHeight = res.result; - return cb(err); - }); -}; - - -HistoricSync.prototype.checkNetworkSettings = function(next) { - var self = this; - - self.hasGenesis = false; - - // check network config - self.rpc.getBlockHash(0, function(err, res){ - if (!err && ( res && res.result !== self.genesis)) { - err = new Error(BAD_GEN_ERROR + config.network); - } - if (err) return next(err); - self.sync.bDb.has(self.genesis, function(err, b) { - if (!err && ( res && res.result !== self.genesis)) { - err = new Error(BAD_GEN_ERROR_DB + config.network); - } - self.hasGenesis = b?true:false; - return next(err); - }); - }); -}; - -HistoricSync.prototype.updateStartBlock = function(opts, next) { - var self = this; - - self.startBlock = self.genesis; - - if (opts.startAt) { - self.sync.bDb.fromHashWithInfo(opts.startAt, function(err, bi) { - var blockInfo = bi ? bi.info : {}; - if (blockInfo.height) { - self.startBlock = opts.startAt; - self.height = blockInfo.height; - info('Resuming sync from block: %s #%d',opts.startAt, self.height); - return next(err); - } - }); - } - else { - self.sync.bDb.getTip(function(err,tip, height) { - if (!tip) return next(); - - var blockInfo; - var oldtip; - - //check that the tip is still on the mainchain - async.doWhilst( - function(cb) { - self.sync.bDb.fromHashWithInfo(tip, function(err, bi) { - blockInfo = bi ? bi.info : {}; - if (oldtip) - self.sync.bDb.setBlockNotMain(oldtip, cb); - else - return cb(); - }); - }, - function(err) { - if (err) return next(err); - var ret = false; - - var d = Math.abs(height-blockInfo.height); - if (d>6) { - error('Previous Tip block tip height differs by %d. Please delete and resync (-D)',d); - process.exit(1); - } - if ( self.blockChainHeight === blockInfo.height || - blockInfo.confirmations > 0) { - ret = false; - } - else { - oldtip = tip; - if (!tip) - throw new Error('Previous blockchain tip was not found on bitcoind. Please reset bitcore-node DB. Tip was:'+tip) - tip = blockInfo.previousblockhash; - info('Previous TIP is now orphan. Back to:' + tip); - ret = true; - } - return ret; - }, - function(err) { - self.startBlock = tip; - self.height = height; - info('Resuming sync from block: %s #%d',tip,height); - return next(err); - } - ); - }); - } -}; - -HistoricSync.prototype.prepareFileSync = function(opts, next) { - var self = this; - - if ( opts.forceRPC || !config.bitcoind.dataDir || - self.height > self.blockChainHeight * PERCENTAGE_TO_START_FROM_RPC) return next(); - - - try { - self.blockExtractor = new BlockExtractor(config.bitcoind.dataDir, config.network); - } catch (e) { - info(e.message + '. Disabling file sync.'); - return next(); - } - - self.getFn = self.getBlockFromFile; - self.allowReorgs = true; - self.sync.bDb.getLastFileIndex(function(err, idx) { - - if (opts.forceStartFile) - self.blockExtractor.currentFileIndex = opts.forceStartFile; - else if (idx) self.blockExtractor.currentFileIndex = idx; - - var h = self.genesis; - - info('Seeking file to:' + self.startBlock); - //forward till startBlock - async.whilst( - function() { - return h !== self.startBlock; - }, - function (w_cb) { - self.getBlockFromFile(function(err,b) { - if (!b) return w_cb('Could not find block ' + self.startBlock); - h=b.hash; - setImmediate(function(){ - return w_cb(err); - }); - }); - }, function(err){ - console.log('\tFOUND Starting Block!'); - - // TODO SET HEIGHT - return next(err); - }); - }); -}; - -//NOP -HistoricSync.prototype.prepareRpcSync = function(opts, next) { - var self = this; - - if (self.blockExtractor) return next(); - self.getFn = self.getBlockFromRPC; - self.allowReorgs = true; - self.currentRpcHash = self.startBlock; - return next(); -}; - -HistoricSync.prototype.showSyncStartMessage = function() { - var self = this; - - info('Got ' + self.height + - ' blocks in current DB, out of ' + self.blockChainHeight + ' block at bitcoind'); - - if (self.blockExtractor) { - info('bitcoind dataDir configured...importing blocks from .dat files'); - info('First file index: ' + self.blockExtractor.currentFileIndex); - } - else { - info('syncing from RPC (slow)'); - } - - info('Starting from: ', self.startBlock); - self.showProgress(); -}; - - -HistoricSync.prototype.setupSyncStatus = function() { - var self = this; - - var step = parseInt( (self.blockChainHeight - self.height) / 1000); - if (step < 10) step = 10; - - self.step = step; - self.type = self.blockExtractor?'from .dat Files':'from RPC calls'; - self.status = 'syncing'; - self.startTs = Date.now(); - self.endTs = null; - this.error = null; - this.syncPercentage = 0; -}; - -HistoricSync.prototype.checkDBVersion = function(cb) { - this.sync.txDb.checkVersion02(function(isOk){ - if (!isOk) { - console.log('\n#############################\n\n ## bitcore-node API DB is older that v0.2. Please resync using:\n $ util/sync.js -D\n More information at bitcore-node API\'s Readme.md'); - process.exit(1); - } - // Add more test here in future changes. - return cb(); - }); -}; - - -HistoricSync.prototype.prepareToSync = function(opts, next) { - var self = this; - - self.status = 'starting'; - async.series([ - function(s_c) { - self.checkDBVersion(s_c); - }, - function(s_c) { - self.checkNetworkSettings(s_c); - }, - function(s_c) { - self.updateBlockChainHeight(s_c); - }, - function(s_c) { - self.updateStartBlock(opts,s_c); - }, - function(s_c) { - self.prepareFileSync(opts, s_c); - }, - function(s_c) { - self.prepareRpcSync(opts, s_c); - }, - ], - function(err) { - if (err) return(self.setError(err)); - - self.showSyncStartMessage(); - self.setupSyncStatus(); - return next(); - }); -}; - - -HistoricSync.prototype.start = function(opts, next) { - var self = this; - - if (self.status==='starting' || self.status==='syncing') { - error('## Wont start to sync while status is %s', self.status); - return next(); - } - - self.prepareToSync(opts, function(err) { - if (err) return next(self.setError(err)); - - async.whilst( - function() { - self.showProgress(); - return self.status === 'syncing'; - }, - function (w_cb) { - self.getFn(function(err,blockInfo) { - if (err) return w_cb(self.setError(err)); - - if (blockInfo && blockInfo.hash && (!opts.stopAt || opts.stopAt !== blockInfo.hash)) { - self.sync.storeTipBlock(blockInfo, self.allowReorgs, function(err, height) { - if (err) return w_cb(self.setError(err)); - if (height>=0) self.height=height; - setImmediate(function(){ - return w_cb(err); - }); - }); - } - else { - self.endTs = Date.now(); - self.status = 'finished'; - var info = self.info(); - logger.debug('Done Syncing blockchain', info.type, 'to height', info.height); - return w_cb(err); - } - }); - }, next); - }); -}; - -module.exports = require('soop')(HistoricSync); diff --git a/lib/strategies/peer.js b/lib/strategies/peer.js deleted file mode 100644 index d3e8d7c5..00000000 --- a/lib/strategies/peer.js +++ /dev/null @@ -1,150 +0,0 @@ -'use strict'; -var fs = require('fs'); -var bitcore = require('bitcore'); -var bitcoreUtil = bitcore.util; -var Sync = require('./Sync'); -var Peer = bitcore.Peer; -var PeerManager = bitcore.PeerManager; -var config = require('../config/config'); -var networks = bitcore.networks; -var sockets = require('../app/controllers/socket.js'); - -var peerdb_fn = 'peerdb.json'; - -function PeerSync(opts) { - opts = opts|| {}; - this.shouldBroadcast = opts.shouldBroadcast; - this.connected = false; - this.peerdb = undefined; - this.allowReorgs = false; - var pmConfig = { - network: config.network - }; - this.peerman = new PeerManager(pmConfig); - this.load_peers(); - this.sync = new Sync(opts); - this.verbose = opts.verbose || false; -} - -PeerSync.prototype.log = function() { - if (this.verbose) console.log(arguments); -}; - -PeerSync.prototype.load_peers = function() { - this.peerdb = [{ - ipv4: config.bitcoind.p2pHost, - port: config.bitcoind.p2pPort - }]; - - fs.writeFileSync(peerdb_fn, JSON.stringify(this.peerdb)); -}; - -PeerSync.prototype.info = function() { - return { - connected: this.connected, - host: this.peerdb[0].ipv4, - port: this.peerdb[0].port - }; -}; - -PeerSync.prototype.handleInv = function(info) { - var invs = info.message.invs; - info.conn.sendGetData(invs); -}; - -PeerSync.prototype._broadcastAddr = function(txid, addrs) { - if (addrs) { - for(var ii in addrs){ - sockets.broadcastAddressTx(txid, ii); - } - } -}; - - -PeerSync.prototype.handleTx = function(info) { - var self =this; - var tx = this.sync.txDb.getStandardizedTx(info.message.tx); - self.log('[p2p_sync] Handle tx: ' + tx.txid); - tx.time = tx.time || Math.round(new Date().getTime() / 1000); - - this.sync.storeTx(tx, function(err, relatedAddrs) { - if (err) { - self.log('[p2p_sync] Error in handle TX: ' + JSON.stringify(err)); - } - else if (self.shouldBroadcast) { - sockets.broadcastTx(tx); - self._broadcastAddr(tx.txid, relatedAddrs); - } - }); -}; - - -PeerSync.prototype.handleBlock = function(info) { - var self = this; - var block = info.message.block; - var blockHash = bitcoreUtil.formatHashFull(block.calcHash()); - self.log('[p2p_sync] Handle block: %s (allowReorgs: %s)', blockHash, self.allowReorgs); - - var tx_hashes = block.txs.map(function(tx) { - return bitcoreUtil.formatHashFull(tx.hash); - }); - - self.sync.storeTipBlock({ - 'hash': blockHash, - 'tx': tx_hashes, - 'previousblockhash': bitcoreUtil.formatHashFull(block.prev_hash), - }, self.allowReorgs, function(err, height) { - if (err && err.message.match(/NEED_SYNC/) && self.historicSync) { - self.log('[p2p_sync] Orphan block received. Triggering sync'); - self.historicSync.start({forceRPC:1}, function(){ - self.log('[p2p_sync] Done resync.'); - }); - } - else if (err) { - self.log('[p2p_sync] Error in handle Block: ', err); - } - else { - if (self.shouldBroadcast) { - sockets.broadcastBlock(blockHash); - // broadcasting address here is a bad idea. listening to new block - // should be enoght - } - } - }); -}; - -PeerSync.prototype.handleConnected = function(data) { - var peerman = data.pm; - var peers_n = peerman.peers.length; - this.log('[p2p_sync] Connected to ' + peers_n + ' peer' + (peers_n !== 1 ? 's' : '')); -}; - -PeerSync.prototype.run = function() { - var self = this; - - this.peerdb.forEach(function(datum) { - var peer = new Peer(datum.ipv4, datum.port); - self.peerman.addPeer(peer); - }); - - this.peerman.on('connection', function(conn) { - self.connected = true; - conn.on('inv', self.handleInv.bind(self)); - conn.on('block', self.handleBlock.bind(self)); - conn.on('tx', self.handleTx.bind(self)); - }); - this.peerman.on('connect', self.handleConnected.bind(self)); - - this.peerman.on('netDisconnected', function() { - self.connected = false; - }); - - this.peerman.start(); -}; - -PeerSync.prototype.close = function() { - this.sync.close(); -}; - - -module.exports = require('soop')(PeerSync); diff --git a/ws/index.js b/ws/index.js deleted file mode 100644 index de01ba3e..00000000 --- a/ws/index.js +++ /dev/null @@ -1,73 +0,0 @@ -'use strict'; - -// server-side socket behaviour -var ios = null; // io is already taken in express -var util = require('bitcore').util; -var logger = require('../../lib/logger').logger; - -module.exports.init = function(io_ext) { - ios = io_ext; - if (ios) { - // when a new socket connects - ios.sockets.on('connection', function(socket) { - logger.verbose('New connection from ' + socket.id); - // when it subscribes, make it join the according room - socket.on('subscribe', function(topic) { - logger.debug('subscribe to ' + topic); - socket.join(topic); - socket.emit('subscribed'); - }); - - // disconnect handler - socket.on('disconnect', function() { - logger.verbose('disconnected ' + socket.id); - }); - - }); - } - return ios; -}; - -var simpleTx = function(tx) { - return { - txid: tx - }; -}; - -var fullTx = function(tx) { - var t = { - txid: tx.txid, - size: tx.size, - }; - // Outputs - var valueOut = 0; - tx.vout.forEach(function(o) { - valueOut += o.valueSat; - }); - - t.valueOut = (valueOut.toFixed(8) / util.COIN); - return t; -}; - -module.exports.broadcastTx = function(tx) { - if (ios) { - var t = (typeof tx === 'string') ? simpleTx(tx) : fullTx(tx); - ios.sockets.in('inv').emit('tx', t); - } -}; - -module.exports.broadcastBlock = function(block) { - if (ios) - ios.sockets.in('inv').emit('block', block); -}; - -module.exports.broadcastAddressTx = function(txid, address) { - if (ios) { - ios.sockets.in(address).emit(address, txid); - } -}; - -module.exports.broadcastSyncInfo = function(historicSync) { - if (ios) - ios.sockets.in('sync').emit('status', historicSync); -}; From 40307543746dda868f58ce29021fb20f29eac3e9 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 05:33:10 -0300 Subject: [PATCH 02/21] update README --- README.md | 3 ++- test/services/transaction.js | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2d3abb69..ffd552b7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -Bitcore Node + + ======= [![NPM Package](https://img.shields.io/npm/v/bitcore-node.svg?style=flat-square)](https://www.npmjs.org/package/bitcore-node) diff --git a/test/services/transaction.js b/test/services/transaction.js index f8b9c723..3e455834 100644 --- a/test/services/transaction.js +++ b/test/services/transaction.js @@ -5,7 +5,6 @@ var should = require('chai').should(); var Promise = require('bluebird'); var bitcore = require('bitcore'); -var _ = bitcore.deps._; var TransactionService = require('../../lib/services/transaction'); From 3cb035020035b6103cfc98c6268cf4de807b6f57 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 05:34:46 -0300 Subject: [PATCH 03/21] update README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ffd552b7..9faa4189 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ - - + + ======= [![NPM Package](https://img.shields.io/npm/v/bitcore-node.svg?style=flat-square)](https://www.npmjs.org/package/bitcore-node) From c6270a2f4edd553b8b7bc00298d2953cce554559 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 05:35:12 -0300 Subject: [PATCH 04/21] update README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9faa4189..36f7803d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ - - + + ======= [![NPM Package](https://img.shields.io/npm/v/bitcore-node.svg?style=flat-square)](https://www.npmjs.org/package/bitcore-node) From da46c930c37f7442ffbe9c4c368f416e876ac262 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 05:35:33 -0300 Subject: [PATCH 05/21] update README --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 36f7803d..4a83a6af 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ - - + ======= [![NPM Package](https://img.shields.io/npm/v/bitcore-node.svg?style=flat-square)](https://www.npmjs.org/package/bitcore-node) From 8eaee87633c87feafcd6ac912078807167011ef9 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 05:37:03 -0300 Subject: [PATCH 06/21] update README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4a83a6af..88e98beb 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,10 @@ ## Prerequisites -* **bitcoind** - Download and Install [Bitcoin](http://bitcoin.org/en/download) +* **Bitcoin Core** - Download and Install [Bitcoin Core](http://bitcoin.org/en/download) `bitcore-node` needs a *trusted* bitcoind node to run. It will connect to the node -through the RPC API, bitcoin peer-to-peer protocol, and will even read its raw block .dat files for syncing. +through the RPC API and bitcoin peer-to-peer protocol. Configure bitcoind to listen to RPC calls and set `txindex` to true. The easiest way to do this is by copying `./etc/bitcoind/bitcoin.conf` to your From f7582586ba4b53b04d179740d4eeccd5be524c63 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 05:41:52 -0300 Subject: [PATCH 07/21] update README --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 88e98beb..bf069193 100644 --- a/README.md +++ b/README.md @@ -9,15 +9,16 @@ * **Bitcoin Core** - Download and Install [Bitcoin Core](http://bitcoin.org/en/download) -`bitcore-node` needs a *trusted* bitcoind node to run. It will connect to the node +`bitcore-node` needs a trusted Bitcoin Core instance to run. It will connect to it through the RPC API and bitcoin peer-to-peer protocol. -Configure bitcoind to listen to RPC calls and set `txindex` to true. -The easiest way to do this is by copying `./etc/bitcoind/bitcoin.conf` to your +Configure Bitcoin Core to listen to RPC calls and set `txindex` to true. +The easiest way to do this is by copying `./config/bitcoin.conf` to your bitcoin data directory (usually `~/.bitcoin` on Linux, `%appdata%\Bitcoin\` on Windows, or `~/Library/Application Support/Bitcoin` on Mac OS X). -bitcoind must be running and must have finished downloading the blockchain **before** running `bitcore-node`. +Bitcoin Core must be running and fully synced before running `bitcore-node`. We're planning +to remove the need of running Bitcoin Core separately. (More info)[https://github.com/bitpay/bitcore-node/issues/57]. * **Node.js v0.10.x** - Download and Install [Node.js](http://www.nodejs.org/download/). From 80d81a3bb5e323f5a770ba0fa02633fe139bc056 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 06:31:48 -0300 Subject: [PATCH 08/21] refactor final polish --- README.md | 67 ++++++++++++++++++++++++++++++++---------- api/config/default.yml | 18 ------------ api/config/livenet.yml | 16 ---------- api/config/testnet.yml | 16 ---------- api/index.js | 15 ---------- config/default.yml | 32 ++++++++++---------- config/livenet.yml | 28 ++++++++++-------- config/testnet.yml | 28 ++++++++++-------- index.js | 26 ++++++++-------- 9 files changed, 110 insertions(+), 136 deletions(-) delete mode 100644 api/config/default.yml delete mode 100644 api/config/livenet.yml delete mode 100644 api/config/testnet.yml diff --git a/README.md b/README.md index bf069193..d516238b 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,11 @@ ## Prerequisites -* **Bitcoin Core** - Download and Install [Bitcoin Core](http://bitcoin.org/en/download) +* **Node.js v0.10.0-v0.12.x** - Download and Install [Node.js](http://www.nodejs.org/download/). + +* **NPM** - Node.js package manager, should be automatically installed when you get node.js. + +* **Fully-synced Bitcoin Core** - Download and Install [Bitcoin Core](http://bitcoin.org/en/download) `bitcore-node` needs a trusted Bitcoin Core instance to run. It will connect to it through the RPC API and bitcoin peer-to-peer protocol. @@ -18,12 +22,7 @@ bitcoin data directory (usually `~/.bitcoin` on Linux, `%appdata%\Bitcoin\` on W or `~/Library/Application Support/Bitcoin` on Mac OS X). Bitcoin Core must be running and fully synced before running `bitcore-node`. We're planning -to remove the need of running Bitcoin Core separately. (More info)[https://github.com/bitpay/bitcore-node/issues/57]. - - -* **Node.js v0.10.x** - Download and Install [Node.js](http://www.nodejs.org/download/). - -* **NPM** - Node.js package manager, should be automatically installed when you get node.js. +to remove the need of running Bitcoin Core separately. [More info](https://github.com/bitpay/bitcore-node/issues/57). ## Quick Install Check the Prerequisites section above before installing. @@ -38,29 +37,65 @@ to remove the need of running Bitcoin Core separately. (More info)[https://githu Run the main application: - $ node index.js + $ npm start Then open a browser and go to: - http://localhost:3001 + http://localhost:8080 Please note that the app will need to sync its internal database - with the blockchain state, which may take some time. You can check - sync progress at http://localhost:3001/api/sync. + with the blockchain state, which will take some time. You can check + sync progress at http://localhost:8080/v1/node. ## Configuration -`bitcore-node` is configured using [yaml](http://en.wikipedia.org/wiki/YAML) files. The application defaults are in the [config](config/) folder. +`bitcore-node` is configured using [yaml](http://en.wikipedia.org/wiki/YAML) files. +The application defaults are in the [api/config/](api/config/) folder. -Make sure that bitcoind is configured to [accept incoming connections using 'rpcallowip'](https://en.bitcoin.it/wiki/Running_Bitcoin). +To run the app with different configurations, simply do: +```sh +# to start a testnet instance +NODE_ENV=testnet npm start -In case the network is changed (testnet to livenet or vice versa) levelDB database needs to be deleted. This can be performed running: -```util/sync.js -D``` and waiting for `bitcore-node` to synchronize again. Once the database is deleted, the sync.js process can be safely interrupted (CTRL+C) and continued from the synchronization process embedded in main app. +# to start a livenet instance +NODE_ENV=livenet npm start + +# start a custom configuration instance (will usee foo.yml) +NODE_ENV=foo npm start +$ +``` + +A sample configuration file would be: + +``` +# Sample configuration file with defaults for livenet +BitcoreHTTP: + port: 8080 # http api port + logging: true # enables request logging + BitcoreNode: + LevelUp: ./db # path to database location + network: livenet # bitcoin network (livenet, testnet) + NetworkMonitor: + host: localhost # p2p host + port: 8333 # p2p port + RPC: + host: 127.0.0.1 # rpc ip + port: 8332 # rpc port + user: user # rpc username + pass: password # rpc password + protocol: http #http, https + #rejectUnauthorized: false + #disableAgent: true +``` ## Synchronization -The initial synchronization process scans the blockchain from the paired bitcoind server to update addresses and balances. `bitcore-node` needs exactly one trusted bitcoind node to run. This node must have finished downloading the blockchain before running `bitcore-node`. +The initial synchronization process scans the blockchain from the paired +Bitcoin Core node to update addresses and balances. `bitcore-node` needs exactly one +trusted bitcoind node to run. +[There are plans to expand this to more than one](https://github.com/bitpay/bitcore-node/issues/58). +Bitcoin core must have finished downloading the blockchain before running `bitcore-node`. While `bitcore-node` is synchronizing the website can be accessed (the sync process is embedded in the webserver), but there may be missing data or incorrect balances for addresses. The 'sync' status is shown at the `/api/sync` endpoint. diff --git a/api/config/default.yml b/api/config/default.yml deleted file mode 100644 index 690eab04..00000000 --- a/api/config/default.yml +++ /dev/null @@ -1,18 +0,0 @@ -BitcoreHTTP: - port: 8080 - logging: true - BitcoreNode: - LevelUp: ./db - network: livenet - NetworkMonitor: - host: localhost - port: 8333 - Reporter: none # none, simple, matrix - RPC: - user: user - pass: password - protocol: http #http, https - #rejectUnauthorized: false - #disableAgent: true - host: 127.0.0.1 - port: 8332 diff --git a/api/config/livenet.yml b/api/config/livenet.yml deleted file mode 100644 index 9caa99c9..00000000 --- a/api/config/livenet.yml +++ /dev/null @@ -1,16 +0,0 @@ -BitcoreHTTP: - port: 8080 - logging: true - BitcoreNode: - LevelUp: ./db - network: livenet - NetworkMonitor: - host: localhost - port: 8333 - Reporter: none # none, simple, matrix - RPC: - user: user - pass: password - protocol: http - host: 127.0.0.1 - port: 8332 diff --git a/api/config/testnet.yml b/api/config/testnet.yml deleted file mode 100644 index 9b91773b..00000000 --- a/api/config/testnet.yml +++ /dev/null @@ -1,16 +0,0 @@ -BitcoreHTTP: - port: 8080 - logging: true - BitcoreNode: - LevelUp: ./testnet-db - network: testnet - NetworkMonitor: - host: localhost - port: 18333 - Reporter: none # none, simple, matrix - RPC: - user: user - pass: password - protocol: http - host: 127.0.0.1 - port: 18332 diff --git a/api/index.js b/api/index.js index 0d542cc6..c6bf0607 100755 --- a/api/index.js +++ b/api/index.js @@ -1,19 +1,4 @@ 'use strict'; var BitcoreHTTP = require('./lib/http'); -var bitcore = require('bitcore'); - -if (require.main === module) { - var config = require('config'); - var network = config.get('BitcoreHTTP.BitcoreNode').network; - console.log('Starting bitcore-node-http', network, 'network'); - bitcore.Networks.defaultNetwork = bitcore.Networks.get(network); - var http = BitcoreHTTP.create(config.get('BitcoreHTTP')); - http.start() - .catch(function(err) { - http.stop(); - throw err; - }); -} - module.exports = BitcoreHTTP; diff --git a/config/default.yml b/config/default.yml index d7bdb37d..d2fff876 100644 --- a/config/default.yml +++ b/config/default.yml @@ -1,15 +1,17 @@ -BitcoreNode: - LevelUp: ./db - network: livenet - NetworkMonitor: - host: localhost - port: 8333 - Reporter: none # none, simple, matrix - RPC: - user: user - pass: password - protocol: http # http, https - #rejectUnauthorized: false - #disableAgent: true - host: 127.0.0.1 - port: 8332 +BitcoreHTTP: + port: 8080 + logging: true + BitcoreNode: + LevelUp: ./db + network: livenet + NetworkMonitor: + host: localhost + port: 8333 + RPC: + user: user + pass: password + protocol: http #http, https + #rejectUnauthorized: false + #disableAgent: true + host: 127.0.0.1 + port: 8332 diff --git a/config/livenet.yml b/config/livenet.yml index d0285e53..dedca69e 100644 --- a/config/livenet.yml +++ b/config/livenet.yml @@ -1,13 +1,15 @@ -BitcoreNode: - LevelUp: ./db - network: livenet - NetworkMonitor: - host: localhost - port: 8333 - Reporter: none # none, simple, matrix - RPC: - user: user - pass: password - protocol: http - host: 127.0.0.1 - port: 8332 +BitcoreHTTP: + port: 8080 + logging: true + BitcoreNode: + LevelUp: ./db + network: livenet + NetworkMonitor: + host: localhost + port: 8333 + RPC: + user: user + pass: password + protocol: http + host: 127.0.0.1 + port: 8332 diff --git a/config/testnet.yml b/config/testnet.yml index e711c0dc..692485a6 100644 --- a/config/testnet.yml +++ b/config/testnet.yml @@ -1,13 +1,15 @@ -BitcoreNode: - LevelUp: ./testnet-db - network: testnet - NetworkMonitor: - host: localhost - port: 18333 - Reporter: none # none, simple, matrix - RPC: - user: user - pass: password - protocol: http - host: 127.0.0.1 - port: 18332 +BitcoreHTTP: + port: 18080 + logging: true + BitcoreNode: + LevelUp: ./testnet-db + network: testnet + NetworkMonitor: + host: localhost + port: 18333 + RPC: + user: user + pass: password + protocol: http + host: 127.0.0.1 + port: 18332 diff --git a/index.js b/index.js index ae5f102d..f9c06c51 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,7 @@ 'use strict'; var BitcoreNode = require('./lib/node'); -var reporters = require('./lib/reporters'); +var BitcoreHTTP = require('./api/lib/http'); var bitcore = require('bitcore'); var Promise = require('bluebird'); Promise.longStackTraces(); @@ -10,12 +10,12 @@ BitcoreNode.errors = require('./lib/errors'); if (require.main === module) { var config = require('config'); - var network = config.get('BitcoreNode').network; - console.log('Starting bitcore-node', network, 'network'); + var nodeConfig = config.get('BitcoreHTTP.BitcoreNode'); + var httpConfig = config.get('BitcoreHTTP'); + var network = nodeConfig.network; + console.log('Starting bitcore-node-http', network, 'network'); bitcore.Networks.defaultNetwork = bitcore.Networks.get(network); - - var node = BitcoreNode.create(config.get('BitcoreNode')); - node.start(); + var node = BitcoreNode.create(nodeConfig); node.on('error', function(err) { if (err.code === 'ECONNREFUSED') { console.log('Connection to bitcoind failed'); @@ -27,14 +27,12 @@ if (require.main === module) { node.stop(); process.exit(); }); - - var reporterName = config.get('BitcoreNode.Reporter'); - var reporter = reporters[reporterName]; - if (!reporter) { - throw new Error('Unrecognized network reporter: ' + reporterName + - '. Available: ' + Object.keys(reporters)); - } - node.on('Transaction', reporter); + var http = new BitcoreHTTP(node, httpConfig); + http.start() + .catch(function(err) { + http.stop(); + throw err; + }); } module.exports = BitcoreNode; From 88003be14456afb9f45ffa04dfebc07fb220c274 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 06:33:28 -0300 Subject: [PATCH 09/21] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d516238b..b061c042 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ to remove the need of running Bitcoin Core separately. [More info](https://githu Please note that the app will need to sync its internal database with the blockchain state, which will take some time. You can check - sync progress at http://localhost:8080/v1/node. + sync progress at `http://localhost:8080/v1/node`. ## Configuration From fe60c2a920a05952793c5df1f35a18553cc8cb3b Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 06:33:45 -0300 Subject: [PATCH 10/21] readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b061c042..dad99bea 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ NODE_ENV=foo npm start $ ``` -A sample configuration file would be: +A sample configuration file would contain: ``` # Sample configuration file with defaults for livenet From 5a873b3be8e9608b420e7a3ceceeed1634b1eb0b Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 06:59:03 -0300 Subject: [PATCH 11/21] readme --- README.md | 325 +++--------------------------------------------------- index.js | 2 +- 2 files changed, 17 insertions(+), 310 deletions(-) diff --git a/README.md b/README.md index dad99bea..5a92875e 100644 --- a/README.md +++ b/README.md @@ -91,56 +91,30 @@ BitcoreHTTP: ## Synchronization -The initial synchronization process scans the blockchain from the paired -Bitcoin Core node to update addresses and balances. `bitcore-node` needs exactly one -trusted bitcoind node to run. +The initial synchronization process scans the blockchain from Bitcoin Core +to update addresses and balances. `bitcore-node` needs exactly one +trusted bitcoind node to function. [There are plans to expand this to more than one](https://github.com/bitpay/bitcore-node/issues/58). Bitcoin core must have finished downloading the blockchain before running `bitcore-node`. -While `bitcore-node` is synchronizing the website can be accessed (the sync process is embedded in the webserver), but there may be missing data or incorrect balances for addresses. The 'sync' status is shown at the `/api/sync` endpoint. - -The blockchain can be read from bitcoind's raw `.dat` files or RPC interface. -Reading the information from the `.dat` files is much faster so it's the -recommended (and default) alternative. `.dat` files are scanned in the default -location for each platform (for example, `~/.bitcoin` on Linux). In case a -non-standard location is used, it needs to be defined (see the Configuration section). -As of June 2014, using `.dat` files the sync process takes 9 hrs. -for livenet and 30 mins. for testnet. +While `bitcore-node` is synchronizing the web API can be queried +(the sync process is embedded in the webserver), but there will be missing data +and incorrect balances for addresses. The 'sync' status is shown at the `/v1/node` endpoint. While synchronizing the blockchain, `bitcore-node` listens for new blocks and -transactions relayed by the bitcoind node. Those are also stored on `bitcore-node`'s database. -In case `bitcore-node` is shutdown for a period of time, restarting it will trigger -a partial (historic) synchronization of the blockchain. Depending on the size of -that synchronization task, a reverse RPC or forward `.dat` syncing strategy will be used. - -If bitcoind is shutdown, `bitcore-node` needs to be stopped and restarted -once bitcoind is restarted. - -### Syncing old blockchain data manually - - Old blockchain data can be manually synced issuing: - - $ util/sync.js - - Check util/sync.js --help for options, particulary -D to erase the current DB. - - *NOTE*: there is no need to run this manually since the historic synchronization - is built in into the web application. Running `bitcore-node` normally will trigger - the historic sync automatically. +transactions relayed by the bitcoin network. Those are also stored on `bitcore-node`'s database. +In case `bitcore-node` is turned off for a period of time, it will automatically catch up on restart. -### DB storage requirement +### Database -To store the blockchain and address related information, LevelDB is used. -Two DBs are created: txs and blocks. By default these are stored on - - ``~/.bitcore-node/`` - -This can be changed at config/config.js. As of June 2014, storing the livenet blockchain takes ~35GB of disk space (2GB for the testnet). +To store the blockchain and address information indexes, [LevelDB](http://leveldb.org/) is used. +By default these are stored on the project's root folder, under the name `db/` for livenet and +`tesnet-db` for testnet. This can be changed using the configuration files. ## Development -To run `bitcore-node` locally for development with gulp: +To run `bitcore-node` in development: ```$ NODE_ENV=development gulp``` @@ -149,279 +123,12 @@ To run the tests ```$ gulp test``` -## Caching schema - -Since v0.2 a new cache schema has been introduced. Only information from transactions with -BLOCKCHAIN_API_SAFE_CONFIRMATIONS settings will be cached (by default SAFE_CONFIRMATIONS=6). There -are 3 different caches: - * Number of confirmations - * Transaction output spent/unspent status - * scriptPubKey for unspent transactions - -Cache data is only populated on request, i.e., only after accessing the required data for -the first time, the information is cached, there is not pre-caching procedure. To ignore -cache by default, use BLOCKCHAIN_API_IGNORE_CACHE. Also, address related calls support `?noCache=1` -to ignore the cache in a particular API request. - ## API -By default, `bitcore-node` provides a REST API at `/api`, but this prefix is configurable from the var `apiPrefix` in the `config.js` file. +By default, `bitcore-node` provides a REST API at `/v1`. +The end-points are detailed in the following document (please review and comment): -The end-points are: - - -### Block -``` - /api/block/[:hash] - /api/block/00000000a967199a2fad0877433c93df785a8d8ce062e5f9b451cd1397bdbf62 -``` -### Transaction -``` - /api/tx/[:txid] - /api/tx/525de308971eabd941b139f46c7198b5af9479325c2395db7f2fb5ae8562556c -``` -### Address -``` - /api/addr/[:addr][?noTxList=1&noCache=1] - /api/addr/mmvP3mTe53qxHdPqXEvdu8WdC7GfQ2vmx5?noTxList=1 -``` -### Address Properties -``` - /api/addr/[:addr]/balance - /api/addr/[:addr]/totalReceived - /api/addr/[:addr]/totalSent - /api/addr/[:addr]/unconfirmedBalance -``` -The response contains the value in Satoshis. -### Unspent Outputs -``` - /api/addr/[:addr]/utxo[?noCache=1] -``` -Sample return: -``` json -[ - { - address: "n2PuaAguxZqLddRbTnAoAuwKYgN2w2hZk7", - txid: "dbfdc2a0d22a8282c4e7be0452d595695f3a39173bed4f48e590877382b112fc", - vout: 0, - ts: 1401276201, - scriptPubKey: "76a914e50575162795cd77366fb80d728e3216bd52deac88ac", - amount: 0.001, - confirmations: 3 - }, - { - address: "n2PuaAguxZqLddRbTnAoAuwKYgN2w2hZk7", - txid: "e2b82af55d64f12fd0dd075d0922ee7d6a300f58fe60a23cbb5831b31d1d58b4", - vout: 0, - ts: 1401226410, - scriptPubKey: "76a914e50575162795cd77366fb80d728e3216bd52deac88ac", - amount: 0.001, - confirmation: 6 - confirmationsFromCache: true, - } -] -``` -Please note that in case confirmations are cached (which happens by default when the number of confirmations is bigger that BLOCKCHAIN_API_SAFE_CONFIRMATIONS) the response will include the pair confirmationsFromCache:true, and confirmations will equal BLOCKCHAIN_API_SAFE_CONFIRMATIONS. See noCache and BLOCKCHAIN_API_IGNORE_CACHE options for details. - - - -### Unspent Outputs for multiple addresses -GET method: -``` - /api/addrs/[:addrs]/utxo - /api/addrs/2NF2baYuJAkCKo5onjUKEPdARQkZ6SYyKd5,2NAre8sX2povnjy4aeiHKeEh97Qhn97tB1f/utxo -``` - -POST method: -``` - /api/addrs/utxo -``` - -POST params: -``` -addrs: 2NF2baYuJAkCKo5onjUKEPdARQkZ6SYyKd5,2NAre8sX2povnjy4aeiHKeEh97Qhn97tB1f -``` - -### Transactions by Block -``` - /api/txs/?block=HASH - /api/txs/?block=00000000fa6cf7367e50ad14eb0ca4737131f256fc4c5841fd3c3f140140e6b6 -``` -### Transactions by Address -``` - /api/txs/?address=ADDR - /api/txs/?address=mmhmMNfBiZZ37g1tgg2t8DDbNoEdqKVxAL -``` - -### Transactions for multiple addresses -GET method: -``` - /api/addrs/[:addrs]/txs[?from=&to=] - /api/addrs/2NF2baYuJAkCKo5onjUKEPdARQkZ6SYyKd5,2NAre8sX2povnjy4aeiHKeEh97Qhn97tB1f/txs?from=0&to=20 -``` - -POST method: -``` - /api/addrs/txs -``` - -POST params: -``` -addrs: 2NF2baYuJAkCKo5onjUKEPdARQkZ6SYyKd5,2NAre8sX2povnjy4aeiHKeEh97Qhn97tB1f -from (optional): 0 -to (optional): 20 -``` - -Sample output: -``` -{ totalItems: 100, - from: 0, - to: 20, - items: - [ { txid: '3e81723d069b12983b2ef694c9782d32fca26cc978de744acbc32c3d3496e915', - version: 1, - locktime: 0, - vin: [Object], - vout: [Object], - blockhash: '00000000011a135e5277f5493c52c66829792392632b8b65429cf07ad3c47a6c', - confirmations: 109367, - time: 1393659685, - blocktime: 1393659685, - valueOut: 0.3453, - size: 225, - firstSeenTs: undefined, - valueIn: 0.3454, - fees: 0.0001 }, - { ... }, - { ... }, - ... - { ... } - ] - } -``` - -Note: if pagination params are not specified, the result is an array of transactions. - - -### Transaction broadcasting -POST method: -``` - /api/tx/send -``` -POST params: -``` - rawtx: "signed transaction as hex string" - - eg - - rawtx: 01000000017b1eabe0209b1fe794124575ef807057c77ada2138ae4fa8d6c4de0398a14f3f00000000494830450221008949f0cb400094ad2b5eb399d59d01c14d73d8fe6e96df1a7150deb388ab8935022079656090d7f6bac4c9a94e0aad311a4268e082a725f8aeae0573fb12ff866a5f01ffffffff01f0ca052a010000001976a914cbc20a7664f2f69e5355aa427045bc15e7c6c77288ac00000000 - -``` -POST response: -``` - { - txid: [:txid] - } - - eg - - { - txid: "c7736a0a0046d5a8cc61c8c3c2821d4d7517f5de2bc66a966011aaa79965ffba" - } -``` - -### Historic blockchain data sync status -``` - /api/sync -``` - -### Live network p2p data sync status -``` - /api/peer -``` - -### Status of the bitcoin network -``` - /api/status?q=xxx -``` - -Where "xxx" can be: - - * getInfo - * getDifficulty - * getTxOutSetInfo - * getBestBlockHash - * getLastBlockHash - -## Web Socket API -The web socket API is served using [socket.io](http://socket.io). - -The following are the events published: - -'tx': new transaction received from network. This event is published in the 'inv' room. Data will be a app/models/Transaction object. -Sample output: -``` -{ - "txid":"00c1b1acb310b87085c7deaaeba478cef5dc9519fab87a4d943ecbb39bd5b053", - "processed":false - ... -} -``` - - -'block': new block received from network. This event is published in the 'inv' room. Data will be a app/models/Block object. -Sample output: -``` -{ - "hash":"000000004a3d187c430cd6a5e988aca3b19e1f1d1727a50dead6c8ac26899b96", - "time":1389789343, - ... -} -``` - -'': new transaction concerning received from network. This event is published in the '' room. - -'status': every 1% increment on the sync task, this event will be triggered. This event is published in the 'sync' room. - -Sample output: -``` -{ - blocksToSync: 164141, - syncedBlocks: 475, - upToExisting: true, - scanningBackward: true, - isEndGenesis: true, - end: "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943", - isStartGenesis: false, - start: "000000009f929800556a8f3cfdbe57c187f2f679e351b12f7011bfc276c41b6d" -} -``` - -### Example Usage - -The following html page connects to the socket.io API and listens for new transactions. - -html -``` - - - - - - -``` +https://docs.google.com/document/d/1rXQdfr8VDBSzheEn0KynnCKCMB0oAsMunkjdG4aY-18 ## License (The MIT License) diff --git a/index.js b/index.js index f9c06c51..4feb1448 100644 --- a/index.js +++ b/index.js @@ -1,12 +1,12 @@ 'use strict'; var BitcoreNode = require('./lib/node'); +BitcoreNode.errors = require('./lib/errors'); var BitcoreHTTP = require('./api/lib/http'); var bitcore = require('bitcore'); var Promise = require('bluebird'); Promise.longStackTraces(); -BitcoreNode.errors = require('./lib/errors'); if (require.main === module) { var config = require('config'); From 6628263b3161a6a178e0c22c7a2040ae905a4c31 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 07:13:59 -0300 Subject: [PATCH 12/21] readme --- README.md | 104 ++++++++++++++++++++++++++++++++++++++++++++++++ api/lib/http.js | 2 + 2 files changed, 106 insertions(+) diff --git a/README.md b/README.md index 5a92875e..01518561 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,110 @@ The end-points are detailed in the following document (please review and comment https://docs.google.com/document/d/1rXQdfr8VDBSzheEn0KynnCKCMB0oAsMunkjdG4aY-18 +Here is a small summary via examples: + +### Node routes +GET '/v1/node' +``` +{ + "sync": 0.0011844682935139, + "peerCount": 1, + "version": "0.0.1", + "network": "testnet", + "height": 445 +} +``` + +### Block routes +GET 'v1/blocks?from=100&offset=4&limit=2' + ``` +[ + { + "header": { + "version": 1, + "prevHash": "0000000040a24e14497879bdd67db948cf30edc5d0a5833e8cb2736582157b49", + "merkleRoot": "6749762ae220c10705556799dcec9bb6a54a7b881eb4b961323a3363b00db518", + "time": 1296699408, + "bits": 486604799, + "nonce": 2783774724 + }, + "transactions": [ + { + "version": 1, + "inputs": [ + { + "prevTxId": "0000000000000000000000000000000000000000000000000000000000000000", + "outputIndex": 4294967295, + "sequenceNumber": 4294967295, + "script": "0410104a4d011e062f503253482f" + } + ], + "outputs": [ + { + "satoshis": 5000000000, + "script": "33 0x02dd75eb56481a1be34cbea2dac1ed1b24c703fd42eb210fbc30112df5373ecc11 OP_CHECKSIG" + } + ], + "nLockTime": 0 + } + ] + }, + { + "header": { + "version": 1, + "prevHash": "00000000a04a30baed00999ad971f807b5e742f602e013519f89eb7248c7ddf5", + "merkleRoot": "b52fcf0359ba4dae01fece4dbf9907f459396ff755fec3af4447a150b846658f", + "time": 1296699475, + "bits": 486604799, + "nonce": 2389020417 + }, + "transactions": [ + { + "version": 1, + "inputs": [ + { + "prevTxId": "0000000000000000000000000000000000000000000000000000000000000000", + "outputIndex": 4294967295, + "sequenceNumber": 4294967295, + "script": "0453104a4d013e062f503253482f" + } + ], + "outputs": [ + { + "satoshis": 5000000000, + "script": "33 0x032b388f00544d231a1c964db35142e8909eb079aa533c8b70f23947a8a3002a89 OP_CHECKSIG" + } + ], + "nLockTime": 0 + } + ] + } +] + ``` + +GET '/blocks/latest' +GET '/blocks/0000000040a24e14497879bdd67db948cf30edc5d0a5833e8cb2736582157b49' +GET '/blocks/:height([0-9]+)' + +### Transaction routes +GET '/transactions/:txHash([A-Fa-f0-9]{64})' +POST '/transactions/send' + +### Input routes +GET '/transactions/:txHash([A-Fa-f0-9]{64})/inputs' +GET '/transactions/:txHash([A-Fa-f0-9]{64})/inputs/:index([0-9]+)' + +### Output routes +GET '/transactions/:txHash([A-Fa-f0-9]{64})/outputs' +GET '/transactions/:txHash([A-Fa-f0-9]{64})/outputs/:index([0-9]+)' + +### Address routes +GET '/addresses/:address' +GET '/addresses/:address/transactions' +GET '/addresses/:addresses/utxos' + + + ## License (The MIT License) diff --git a/api/lib/http.js b/api/lib/http.js index c946c43a..6c9e7ff6 100644 --- a/api/lib/http.js +++ b/api/lib/http.js @@ -44,6 +44,8 @@ BitcoreHTTP.prototype.setupExpress = function() { app.use(morgan('dev')); } + app.set('json spaces', 2); + // install routes app.use('/', routes(this.node)); From 49f26d3ae54fcbe4ac322f0e36a96a60c0361921 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 07:29:57 -0300 Subject: [PATCH 13/21] fix problem with transaction by hash --- README.md | 1484 ++++++++++++++++++++++++++++++- api/controllers/blocks.js | 7 +- api/controllers/transactions.js | 6 +- index.js | 1 - lib/node.js | 2 + lib/services/transaction.js | 5 +- 6 files changed, 1480 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 01518561..cd458050 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,7 @@ GET '/v1/node' ``` ### Block routes -GET 'v1/blocks?from=100&offset=4&limit=2' +GET '/v1/blocks?from=100&offset=4&limit=2' ``` [ { @@ -209,28 +209,1484 @@ GET 'v1/blocks?from=100&offset=4&limit=2' ] } ] - ``` +``` -GET '/blocks/latest' -GET '/blocks/0000000040a24e14497879bdd67db948cf30edc5d0a5833e8cb2736582157b49' -GET '/blocks/:height([0-9]+)' +GET '/v1/blocks/latest' +``` +{ + "header": { + "version": 2, + "prevHash": "0000000002a608efe381b7a451202bb08de18530701196aea150beff2902ca32", + "merkleRoot": "5d2e5d26693bf700bbcdb25bfa4c6e931d8c722e161dd5f1a2dd326be1e6a8a7", + "time": 1358100472, + "bits": 470294630, + "nonce": 2955808852 + }, + "transactions": [ + { + "version": 1, + "inputs": [ + { + "prevTxId": "0000000000000000000000000000000000000000000000000000000000000000", + "outputIndex": 4294967295, + "sequenceNumber": 4294967295, + "script": "03f2b9000175062f503253482f" + } + ], + "outputs": [ + { + "satoshis": 5002300000, + "script": "33 0x0392ef5b1c03e5bcb36bf98cfb5b2f3a6733fb7c144f36c77cbe2fa9bafb4c6d8f OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "4b7b80018c6fcc505f3e9c8491a387d14fbf4d2a94523ddc5869e461a13b42e0", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "493046022100ef36de15248e3186f0c41af380b25426080d7bf216c5e33ae88cb41ae967e4e602210080a54d59d4c314753c0ead98982c4eca00e774321bf4048cb3739502e626966c012103c09b1fb835ab3a34af9fdae9c218902a59f621daa3fb253b459db9ff8bdcb106", + "scriptString": "73 0x3046022100ef36de15248e3186f0c41af380b25426080d7bf216c5e33ae88cb41ae967e4e602210080a54d59d4c314753c0ead98982c4eca00e774321bf4048cb3739502e626966c01 33 0x03c09b1fb835ab3a34af9fdae9c218902a59f621daa3fb253b459db9ff8bdcb106" + } + ], + "outputs": [ + { + "satoshis": 4700050000, + "script": "OP_DUP OP_HASH160 20 0x88de567c6663eb09aca47896ea8b3871fea505b8 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 100000000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "5003de1b42da81ad5a2c1077c48463fc6946172ecc0219067f89a5ce9755f05a", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "48304502200313a12528bf04959ab1ab1dd5d4c3e33cbc1bf7fff35693b45229a2836dae37022100f4a34b9b46600c7cf90347f21b0e9b45bd83b9eaa9920ecc9af16a28971484810121028f441116b5957e231e66bba669883b007da492f5cd48eabd2478812451a34eee", + "scriptString": "72 0x304502200313a12528bf04959ab1ab1dd5d4c3e33cbc1bf7fff35693b45229a2836dae37022100f4a34b9b46600c7cf90347f21b0e9b45bd83b9eaa9920ecc9af16a289714848101 33 0x028f441116b5957e231e66bba669883b007da492f5cd48eabd2478812451a34eee" + } + ], + "outputs": [ + { + "satoshis": 3899600000, + "script": "OP_DUP OP_HASH160 20 0xcffaebba2380c4907cc9407beed632f192ead5ab OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 100000000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "afc4cedf98677d6ac435082125ac832fe13e329324f841da6b5a02c1d334ac7d", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "4830450220673b65a4740e559f2326db594b670beb8e9fe1fa8e4bc04bd0857aab84fd4e0a022100e57861b74e253dfb5d1a5f7cf767f86132bd8c5aea5c7446580d8d3e73e6813a0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x30450220673b65a4740e559f2326db594b670beb8e9fe1fa8e4bc04bd0857aab84fd4e0a022100e57861b74e253dfb5d1a5f7cf767f86132bd8c5aea5c7446580d8d3e73e6813a01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "47c7a86ff1ca298847b4e47655ab15d7e86079eacf815bbd1de66d7c2f9791f7", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "49304602210086a2798ff51a2915cb282e21b7d12ca9096bb76ed1075cb34c319d46c33b7e94022100a085481830194e0f47223c5dc14c29a3e09a914f8d37aca3a727b635ae75895d0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "73 0x304602210086a2798ff51a2915cb282e21b7d12ca9096bb76ed1075cb34c319d46c33b7e94022100a085481830194e0f47223c5dc14c29a3e09a914f8d37aca3a727b635ae75895d01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "c2614d710f83abe323f05dfe83f49da5102474e1e1b89809a582a4b8bc6059a9", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "483045022100cb369d906d8aaf083547badb329859f33c5e81cf02c446a99764b95214565bfd02205432e1d37f64cd6a678d43ee172670ccdc1eae494fc419b93c0e1e27678834de0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x3045022100cb369d906d8aaf083547badb329859f33c5e81cf02c446a99764b95214565bfd02205432e1d37f64cd6a678d43ee172670ccdc1eae494fc419b93c0e1e27678834de01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "39840c5f9092d3bfdbe917259811fac5a00d7116d9316886302185040117c3e5", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "483045022022cf9c3fc2281b885da06d0fb9180824cbf0c5cfd0d57bef615ae3190b679395022100c33cfb8932bb2afa8f32778a4134b64c4a1def3e7496a6a0762b9b37a7c3eb850141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x3045022022cf9c3fc2281b885da06d0fb9180824cbf0c5cfd0d57bef615ae3190b679395022100c33cfb8932bb2afa8f32778a4134b64c4a1def3e7496a6a0762b9b37a7c3eb8501 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "47e9b94475176f12ee07eeb003d45002b6188f682fc782e8aa17c2b59f793761", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "47304402200519a2b036e8f43bac41b972398082fbd54695fcb83a667dee859641adfa4139022068e99792c5b36a7357b73a75734954e449f8ff3a2e5c4c480f421fe80caa998f0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "71 0x304402200519a2b036e8f43bac41b972398082fbd54695fcb83a667dee859641adfa4139022068e99792c5b36a7357b73a75734954e449f8ff3a2e5c4c480f421fe80caa998f01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "176d4ab48674b4296a6b4b3a2578ac4799bc4688ee10bb4f9dac65db24da5a98", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "47304402200b9d394d86b50e92945873076b45ea1fec30db8157bc539ea4d41b2bdff85e040220115d7ebcef0be59c25ab0d5a2c3e3860002c851297b77bd5010670c1d2653b330141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "71 0x304402200b9d394d86b50e92945873076b45ea1fec30db8157bc539ea4d41b2bdff85e040220115d7ebcef0be59c25ab0d5a2c3e3860002c851297b77bd5010670c1d2653b3301 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "8f6f333b9355df34cf2ee7906f0fb0872b8e87ad7976e5d15c28356d12c3b784", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "4930460221008676de0aecda9f23038e8ca8941102123041b3f6695fe8135e2caa97e90e2bb6022100919f6dda773e76d9db00242874e9927ad912164875e9c23a812e2ba604dd224c0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "73 0x30460221008676de0aecda9f23038e8ca8941102123041b3f6695fe8135e2caa97e90e2bb6022100919f6dda773e76d9db00242874e9927ad912164875e9c23a812e2ba604dd224c01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "5205c902788e289548d777dc67c89af378bfde54c887499b4e17dd2205c29740", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "48304502201a2eb1ff625096badfc0dea590eec1c0ec513aeff99ec79183ec9c1e83f1da0b022100eb9bbf388939f7d312dab2ce7b887f00d6e985711b5cf0786b9dfe63486bdee70141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x304502201a2eb1ff625096badfc0dea590eec1c0ec513aeff99ec79183ec9c1e83f1da0b022100eb9bbf388939f7d312dab2ce7b887f00d6e985711b5cf0786b9dfe63486bdee701 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "175af8f5dcca3edb7158dbe86b9167e643b7682e0199cc6a2899db164cf794ee", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "48304502203b7e0488bd10a5e8c2a4f2616a7edeeec4dcfa0e0756b49a0fe5199cd2242d640221009aa4ef235c52d90ace76611d3810b724227e7a6978c3f6b3840c75d195764a3d0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x304502203b7e0488bd10a5e8c2a4f2616a7edeeec4dcfa0e0756b49a0fe5199cd2242d640221009aa4ef235c52d90ace76611d3810b724227e7a6978c3f6b3840c75d195764a3d01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "b2ba338551b93a8425b485d3021a2fd1a574878f859d19e92dfd28ae6799c70e", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "48304502207f6bb25b9021d77b56fdbfd2732f4d4314f0fd59552cf9f47ef8745986132dee022100f0412d1741d1e5c6260cb852097eb9dbcbcc86cd39e4f6f6e8f464ac083be2550141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x304502207f6bb25b9021d77b56fdbfd2732f4d4314f0fd59552cf9f47ef8745986132dee022100f0412d1741d1e5c6260cb852097eb9dbcbcc86cd39e4f6f6e8f464ac083be25501 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "8c4204a435002760a3cbafe5f1946083535d4f289b939adca3b8c565fe09062e", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "48304502206938462456d38646f97d7bbbd6ee5e4258eaa1f5ad90b44cef994dda1f2887c802210089522436e59dbe62ee1bbc9a72c40d66329845847e0077135562d396585c56f70141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x304502206938462456d38646f97d7bbbd6ee5e4258eaa1f5ad90b44cef994dda1f2887c802210089522436e59dbe62ee1bbc9a72c40d66329845847e0077135562d396585c56f701 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "01176b10d1393f2d1a5cd4998dfaf276cccbc1a535ae90665671fd3072891ed0", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "493046022100ffd5b40e444c6c5d22e53ce724c7292ff4169e2caa60de8e789172cf56d3ebae02210093920af6c067b1a501fc4de0abe39cea1eac63d28253a66e337a613292d0a3fc0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "73 0x3046022100ffd5b40e444c6c5d22e53ce724c7292ff4169e2caa60de8e789172cf56d3ebae02210093920af6c067b1a501fc4de0abe39cea1eac63d28253a66e337a613292d0a3fc01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "40834e854eafb7979339d3d97b80d9abc4b0bec0a2d05f7840b4145c822875f3", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "483045022011299767cb74b5ddcf73780ea0e5bea0b2f503691252e4c308f3ea6a43cd400f0221008413f01028d3a0a7597f281e7b0c537c33ac1b86c339ccafddc95990a977b39d0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x3045022011299767cb74b5ddcf73780ea0e5bea0b2f503691252e4c308f3ea6a43cd400f0221008413f01028d3a0a7597f281e7b0c537c33ac1b86c339ccafddc95990a977b39d01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "1279815fa3c39b2497f08405793299deac32e9dba94cb28bcc8183736daaafb5", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "48304502202cda299b464ffb8f4199ffa09d9fc016138ec25115c02ee2479900a83bc8fe15022100a36549741046707f1cdae42c1ba1922bdfc0166ea6812baa6a4870f8c97a9f400141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x304502202cda299b464ffb8f4199ffa09d9fc016138ec25115c02ee2479900a83bc8fe15022100a36549741046707f1cdae42c1ba1922bdfc0166ea6812baa6a4870f8c97a9f4001 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "40a3a097d98060401e76901e12a8002c78d5fb41ed16dce9e3d7d4e80ef1cfa9", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "483045022100e04d0d2c1dee52b7f72e4023db6b4d86f020d5fe866be6be8c5f3d07a779984c02206913cc938d9a6a25dcbdc1c6a4cca45b914503b125f358ef59d16465fa02151c0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x3045022100e04d0d2c1dee52b7f72e4023db6b4d86f020d5fe866be6be8c5f3d07a779984c02206913cc938d9a6a25dcbdc1c6a4cca45b914503b125f358ef59d16465fa02151c01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "3f2068a081e9659163ab923108baf0a24d61b162912fc322c256fa91b946b703", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "493046022100bb73a2ff276b12e256253d2792ebb12166c86b898c146eb6a202e7eff65122e3022100f78b136b90ae8cbc24d4d0fe3b502b1359c0642a05d964c79d1fb0b32c23dee20141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "73 0x3046022100bb73a2ff276b12e256253d2792ebb12166c86b898c146eb6a202e7eff65122e3022100f78b136b90ae8cbc24d4d0fe3b502b1359c0642a05d964c79d1fb0b32c23dee201 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "cc5944eca0805d25a2281f467d7652e207c783e3114bd260750d6610d4c2b936", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "4730440220280ab235fc23465f872b3ac7c70731aaf6bfbfa79ab169183a2bd910212b01c80220206d3bb1e23bba67c0a8d87071e88c4c1cde2cb497522434f9b9cf4ee3302bda0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "71 0x30440220280ab235fc23465f872b3ac7c70731aaf6bfbfa79ab169183a2bd910212b01c80220206d3bb1e23bba67c0a8d87071e88c4c1cde2cb497522434f9b9cf4ee3302bda01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "a91582fa7d09af92521f35debae48cedd90387505872d4df0b2e6198ea0e95a4", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "483045022100dbc3f93c380be5fe19280f4e2deb6feecc3fe85d6b8a1653231ab164d952274e02204bc0a3c185eb7c2e62dca863ab7927cf22e018567cf63fa8e87a8131eb0bbd8f0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x3045022100dbc3f93c380be5fe19280f4e2deb6feecc3fe85d6b8a1653231ab164d952274e02204bc0a3c185eb7c2e62dca863ab7927cf22e018567cf63fa8e87a8131eb0bbd8f01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "3952e193feadce900d49d807006b0b39aa2d3dba12e37c8820d773e83fa87a6c", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "483045022100a620f076659c5c308269dbbdcd890629ccc7a9091bf1feb12abcd4ff38cc2ac4022068ca07f673da63bd64f2de1ff97fc1141de93d3a84e1182bcc5f73eebedb2b1d0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x3045022100a620f076659c5c308269dbbdcd890629ccc7a9091bf1feb12abcd4ff38cc2ac4022068ca07f673da63bd64f2de1ff97fc1141de93d3a84e1182bcc5f73eebedb2b1d01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "d6db19c9f84e889dc2f2ee6b7627731fe4588e839bed5dd58ebf4f297826f435", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "473044022054fcfcfe3f976d63f0fc7f56a8b8edfa9d5ce9a4ab64d1348811a0c43f8efb4002203933e80f080835c6bd966fb20289985d5def7c6031d8ca41943dbbfb76b39df30141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "71 0x3044022054fcfcfe3f976d63f0fc7f56a8b8edfa9d5ce9a4ab64d1348811a0c43f8efb4002203933e80f080835c6bd966fb20289985d5def7c6031d8ca41943dbbfb76b39df301 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "d871f253201c6d1a47bb42fa5c20cdc489b268ee14b9cb93757b9a04246d77ec", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "483045022100b2ed1f4988862d13434b346aac50f6a868c30bb32429b69fc421e14ae7be680702200ea4c09b2b1537ee43856fbc98b2624aabe2846e251ced4ed61cfdf198f06bf00141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x3045022100b2ed1f4988862d13434b346aac50f6a868c30bb32429b69fc421e14ae7be680702200ea4c09b2b1537ee43856fbc98b2624aabe2846e251ced4ed61cfdf198f06bf001 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "e61f668c688f5bff7e1543461b17d86443bd436c17c5782e94ffd51ae797b491", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "473044022079c691683937dc8d37e1dc4d105abd355d4424b3a60a2151965ac467461b2c7902206d76051acc3bda054df5b6e5ca248377bfc89d45746b1ded16de74ef11629f7d0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "71 0x3044022079c691683937dc8d37e1dc4d105abd355d4424b3a60a2151965ac467461b2c7902206d76051acc3bda054df5b6e5ca248377bfc89d45746b1ded16de74ef11629f7d01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "fc7c3d2fe443be6975852e0fe4a7d42b8fb8988ad8b401437955f3627c0833cc", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "47304402205664a44bcdf57c8df2f29526237dbb12f3ddaa743eb0fe6a8cac7b062895ee2702203dea95a877d37579f906c53d68d348998df00890f3f2bf7f2b1943837a4f91d20141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "71 0x304402205664a44bcdf57c8df2f29526237dbb12f3ddaa743eb0fe6a8cac7b062895ee2702203dea95a877d37579f906c53d68d348998df00890f3f2bf7f2b1943837a4f91d201 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "37f1b75be71bb4cdf67197c2d3d3bb51cff34186889c99af19eb9bf53193ec8e", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "483045022100841fb9c0906f530c9bf849e2346399e1a3a0554cf57fef438358cbee2b8bfa75022059aa753b98f1bc6ecae586ca390ee826f7de48ca9e2987dc1bfc1bfff043bed20141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x3045022100841fb9c0906f530c9bf849e2346399e1a3a0554cf57fef438358cbee2b8bfa75022059aa753b98f1bc6ecae586ca390ee826f7de48ca9e2987dc1bfc1bfff043bed201 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "a1da15c75b8279db32693dd4ebd62f97d02692445073ae6a356881e06361e0b0", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "483045022100c82aa9a7c2479d1ac58ba1742ee531fcde2040a0e3fa6d87b2b76f64a09b979802207c50accdf5237a6e73b5199c34e17dbe62ab357b3c86c2f67247a11574b07c4b0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x3045022100c82aa9a7c2479d1ac58ba1742ee531fcde2040a0e3fa6d87b2b76f64a09b979802207c50accdf5237a6e73b5199c34e17dbe62ab357b3c86c2f67247a11574b07c4b01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "978a44a3e45c2a446eca04fbcafdfda0a0b6eeec552160f5f9d0cd48ae4956bd", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "493046022100c74e93240a541179744092829f140a7ada3a494425e1aac6ef17b36e7bbd451a022100c77d2a9752496737fd385bd00a58d110b8c993b6f499f1ad3cd2786eb01e4fbf0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "73 0x3046022100c74e93240a541179744092829f140a7ada3a494425e1aac6ef17b36e7bbd451a022100c77d2a9752496737fd385bd00a58d110b8c993b6f499f1ad3cd2786eb01e4fbf01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "2c8cb517dac21217fd47718d0fd74def9092cc02b90a6c3a72eb8d478f5d1aa0", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "473044022071da53afdce5078929acbc175306a528d65925c684de25d0dcc561bc529d031602207c8ba0f9ed28cc8424763abb285df781a5f85aaa37b6b16125bf3fdff177907f0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "71 0x3044022071da53afdce5078929acbc175306a528d65925c684de25d0dcc561bc529d031602207c8ba0f9ed28cc8424763abb285df781a5f85aaa37b6b16125bf3fdff177907f01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "0420188a6f6c0447f6e6b034d6989a9656ac6bcd21bcfddf8c7734292bf52309", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "4830450220371119dbadd964da6b2cb44134248ed07ba9f9bf821e669e878f6047abfe749c02210090d948a303605186c398da8ebcfba486755c2e5f0b5e51e388f5fd261cf2c7460141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x30450220371119dbadd964da6b2cb44134248ed07ba9f9bf821e669e878f6047abfe749c02210090d948a303605186c398da8ebcfba486755c2e5f0b5e51e388f5fd261cf2c74601 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "0224b3a23775b4166a356df3f6ac8fe989b2a56ec4931587de86fc364227d4d2", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "473044022002ef2ea9c304f3bcb81cd0cc1245a2630128b3e6f6054deb45bfcc263d0a5b1302204c5676be18a7fb1d4c5e49e2e29857303cd692d0aec22f757113142adb75c15a0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "71 0x3044022002ef2ea9c304f3bcb81cd0cc1245a2630128b3e6f6054deb45bfcc263d0a5b1302204c5676be18a7fb1d4c5e49e2e29857303cd692d0aec22f757113142adb75c15a01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "8e0753494b2f9ed149bf943709c23d72e67d92a5e08325fa96e46afc0076cc09", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "473044022076c6e30fbe2a4950e62cb81aa36369e71da7842e7e182fd5ee6cc6f0fbe3a2a9022003f41fe2e747fb6083e0d085f147fc9494b73424b5a89112560eb46e26fe20000141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "71 0x3044022076c6e30fbe2a4950e62cb81aa36369e71da7842e7e182fd5ee6cc6f0fbe3a2a9022003f41fe2e747fb6083e0d085f147fc9494b73424b5a89112560eb46e26fe200001 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "d83e815726d70357c43306bb056af94522c59b2c912d2ad208f2fba527d76c5a", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "493046022100931818a7358c59d56a8529ae0fb2c86d91b9309467320533aa823736dbd51b59022100c94ce73e6af45c5a249dce3c0ec184b1c2976b16ff38c2b44fe7e3874cc1058b0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "73 0x3046022100931818a7358c59d56a8529ae0fb2c86d91b9309467320533aa823736dbd51b59022100c94ce73e6af45c5a249dce3c0ec184b1c2976b16ff38c2b44fe7e3874cc1058b01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "2be52894d0f814294f2b7993ed2538e1571c68fbc25065529b1b5f31d1fa7cc0", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "47304402203280a8d85a887526320ec54ef37b69780d804e92898d885fcadbe6aa8de01aaa02207faf4f50ca871cfab7b7c69d10d755612def7ba16db038e460ecc3c7ac83a0ec0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "71 0x304402203280a8d85a887526320ec54ef37b69780d804e92898d885fcadbe6aa8de01aaa02207faf4f50ca871cfab7b7c69d10d755612def7ba16db038e460ecc3c7ac83a0ec01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "d0bbb3e35ef69b19fa3c493d26922c8f9e39848448640fd962206ecc9ce762e2", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "4730440220446083904fd7b36859823649c054dea090d898ed7fbfadd3d63461d73b5b0d96022030ad8deb4b1e1749df126256e4987eb1cb12a39bb56f36c9895d7dff99d4ec970141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "71 0x30440220446083904fd7b36859823649c054dea090d898ed7fbfadd3d63461d73b5b0d96022030ad8deb4b1e1749df126256e4987eb1cb12a39bb56f36c9895d7dff99d4ec9701 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "2a2d939a69f93c36de5f4f0da1c8a651820aeace8fc264d6a558423e3bf3b88a", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "48304502205136cbe4bd5f345bd7fb5a3d6555c34e214c3de7d7040f8bd51f1437259a03420221009bcc8e3e587ae1c2effdc47a39030af09afab0360ead812777e710c19ba1bcdd0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x304502205136cbe4bd5f345bd7fb5a3d6555c34e214c3de7d7040f8bd51f1437259a03420221009bcc8e3e587ae1c2effdc47a39030af09afab0360ead812777e710c19ba1bcdd01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "aa4f0c00e8fc4557e28d642e00e129463991715de7ee4438104bebec01e34fd1", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "473044022056614712eb87065362d2bf82d292a7634c8ccd8961bce8cfd2654d7ceaccee6502201b61d00a019af42499216b09f74cc12095ac3acf82e3635ccd3db06cf745e9860141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "71 0x3044022056614712eb87065362d2bf82d292a7634c8ccd8961bce8cfd2654d7ceaccee6502201b61d00a019af42499216b09f74cc12095ac3acf82e3635ccd3db06cf745e98601 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "36672b676e950d878ccf9a176a2cee22e63ccd3b4ea3aaac36277b8694120a81", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "48304502202392893218a892494c2935c537a1d7317777bf77a7c1a683c12ad43f55a89cdc022100e6ebf27e108ca43b3e241d74652a3881dc1f406ceb596fa293cf11616c99b7680141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x304502202392893218a892494c2935c537a1d7317777bf77a7c1a683c12ad43f55a89cdc022100e6ebf27e108ca43b3e241d74652a3881dc1f406ceb596fa293cf11616c99b76801 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "41f3c181deea56fa3dcbddc2100246db9e92ced381f8d2dd30a88c579e296809", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "493046022100e3d2ba3ed79dd61fe011cdc1085d17c2034a9aee13a3612d04147d2f1d8733c2022100d1b0b3cb382a8fb1441ec05b7d370709bbbd67dd591a09e13e1811ed5955ba990141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "73 0x3046022100e3d2ba3ed79dd61fe011cdc1085d17c2034a9aee13a3612d04147d2f1d8733c2022100d1b0b3cb382a8fb1441ec05b7d370709bbbd67dd591a09e13e1811ed5955ba9901 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "4118cb9809ad63cd3a8ec5bc345f8e8b0b9887604ee39420bb1be2e70fe015d7", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "49304602210098a3c77bba0280a4d0a1af805b965fe3930cc2b8da89bab11932f3261b1fb09b022100b46a499d84e07fdc5a8c09f991cbf67e29f115461db232015c2c5b7229f702210141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "73 0x304602210098a3c77bba0280a4d0a1af805b965fe3930cc2b8da89bab11932f3261b1fb09b022100b46a499d84e07fdc5a8c09f991cbf67e29f115461db232015c2c5b7229f7022101 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "68bba6154e65c18d414f165b4c982a43853b7bc4be2442bcb9d3c01ac43a702b", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "483045022100ab3bc49519276b58b0ab66643c8d4982d29d08ae79999aa7fa2061a6987d5fd802201b9013a1c0371903ccba69812cc1c64d101eeeff419cd6ca80a15ebf4b4a9d050141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x3045022100ab3bc49519276b58b0ab66643c8d4982d29d08ae79999aa7fa2061a6987d5fd802201b9013a1c0371903ccba69812cc1c64d101eeeff419cd6ca80a15ebf4b4a9d0501 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "c8d899a52c5a6a74ac03a3cbc4b7f40927440a3ddeed7ff45ca94e76c2f19deb", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "47304402200b52701b975d03db0a94a8eb98db859f5ce85adfb7f758e9d7266c1c728adc4a02200b686d0ccf07d37ffb4a47155d1f8d685c21a8a0308c274dd59e03c9d057261c0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "71 0x304402200b52701b975d03db0a94a8eb98db859f5ce85adfb7f758e9d7266c1c728adc4a02200b686d0ccf07d37ffb4a47155d1f8d685c21a8a0308c274dd59e03c9d057261c01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "e25bffcdc5369646c925c05e3337f8cdd4dcba77de0b6b5a4ed7d39cd6650ffc", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "48304502203cb373da8bcbcb105d0b02a6a6a9933556a7251d9e765f8bc7675552820d45b1022100bc00ce5b4ff4c0d088d925012c5e411d916090bdd3d89deb438873caee0fbe350141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x304502203cb373da8bcbcb105d0b02a6a6a9933556a7251d9e765f8bc7675552820d45b1022100bc00ce5b4ff4c0d088d925012c5e411d916090bdd3d89deb438873caee0fbe3501 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "1927a50f4f3641c0e1e7d6cbfff267d34a21174c431c688a53f2f43251851b70", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "493046022100e5e41024deb5ec82e1419ab65d92548c016500a0b2e95a2ab0ef9169485bc85d022100cb87ff11b7ef066b33a612998f1fb47609f7c13db017da6ef9a26cb597f087ed0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "73 0x3046022100e5e41024deb5ec82e1419ab65d92548c016500a0b2e95a2ab0ef9169485bc85d022100cb87ff11b7ef066b33a612998f1fb47609f7c13db017da6ef9a26cb597f087ed01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "a80f3f140549f3da04be7ad6706014c912498fef38823f36e8293834465cd19d", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "48304502206dde3140c4a3f56b922c10560f612442d2b8155c97e04d2b0de37af43d1985cf022100cc3aee9bbfbddd735b7571f0202aa8e8d1cef0ea5baf61da8e9550afe2752ecf0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x304502206dde3140c4a3f56b922c10560f612442d2b8155c97e04d2b0de37af43d1985cf022100cc3aee9bbfbddd735b7571f0202aa8e8d1cef0ea5baf61da8e9550afe2752ecf01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "652e701f4ead643be06c530761230713e23cb2c74ceaaecf962e44c167be11dd", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "4830450220630f4312cf3053ffb64cdf1e89c807d9c738438fe3f5db247ddeebf4e1aecc87022100d7458997d9ee959ea8ae796c2d01910e8c6151a77f36661e5dff3112ae7476bb0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x30450220630f4312cf3053ffb64cdf1e89c807d9c738438fe3f5db247ddeebf4e1aecc87022100d7458997d9ee959ea8ae796c2d01910e8c6151a77f36661e5dff3112ae7476bb01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "4f48eff52a754ee1a38fed75eb2cc5543332abd5a5e1a8f7f5f371c189833b1b", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "48304502210085f48c8f085858dd8503484f2147209c4568029dc551012b968030ba52d75754022061b018a1a4998c0ee49078f29d90543bcf308b267d858740134ea6ae8ac1f2080141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x304502210085f48c8f085858dd8503484f2147209c4568029dc551012b968030ba52d75754022061b018a1a4998c0ee49078f29d90543bcf308b267d858740134ea6ae8ac1f20801 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "8779334c04a2af6fcdf60cff0e14ec2aa34163ced77949622157b924b2fa83e1", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "47304402205e1e349d4aabb86c3787573e091304bc82fb62ddcf830cf76c0e68aea636281b02200d4d6146cf2db1d892a9d16d9afa1f6f7b84f21f8cfaea939c29eeb735a0c2360141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "71 0x304402205e1e349d4aabb86c3787573e091304bc82fb62ddcf830cf76c0e68aea636281b02200d4d6146cf2db1d892a9d16d9afa1f6f7b84f21f8cfaea939c29eeb735a0c23601 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "243a6a73aba24da407e711be13eccd8b322356b1d7ab8a33fd258353f84fa593", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "48304502204020af60b8219aa7c5797b8c3bbe6486c3e6d3011a5ff29da95db6fabfa0234a022100c16836f0177279fc5b0fd2cf445586a4e628e854bbe85753a04d74e0cfc1c69c0141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x304502204020af60b8219aa7c5797b8c3bbe6486c3e6d3011a5ff29da95db6fabfa0234a022100c16836f0177279fc5b0fd2cf445586a4e628e854bbe85753a04d74e0cfc1c69c01 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "28d2510d3f37324bfb6d81e6ab25ee984b60e67df24179c03fc9fa1c6e9866bf", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "483045022100e4f587779ef1b800f7908d06a7cc119ed91b31024e50c985efc7f8e0c0df25500220340d66080a4205b14bd2e158d3325da9772bb3350be8b17815204a35e8024a520141045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e", + "scriptString": "72 0x3045022100e4f587779ef1b800f7908d06a7cc119ed91b31024e50c985efc7f8e0c0df25500220340d66080a4205b14bd2e158d3325da9772bb3350be8b17815204a35e8024a5201 65 0x045c9cfbc6bccb7651ef01a107f5e9df3429df378ad3af2c4d2ee8562bc47656efafffaef77ff64180fb8a12e7c48b5f724a924409926f72bea811b2432cdd3d2e" + }, + { + "prevTxId": "9d4b9935f3bcb375a05d5e3e264b5a60306fad729676f4034e213798dcb89f06", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "4730440220629a42acd1cfe83f6789717e5d5c6a94719eab4370ab8801877098c06ffa81dd02201a366c8686c3ba4513f93f8e90083823c5f31958c579fce32eb506961e9a488f014104569bd6236fdb92a2374722bc27ffa54ddb9bfec843f1d7bd776314b98a19ebf383ff38249981a33854b7e57f3faa25718821f9af40d75998741cc07f8aca05e3", + "scriptString": "71 0x30440220629a42acd1cfe83f6789717e5d5c6a94719eab4370ab8801877098c06ffa81dd02201a366c8686c3ba4513f93f8e90083823c5f31958c579fce32eb506961e9a488f01 65 0x04569bd6236fdb92a2374722bc27ffa54ddb9bfec843f1d7bd776314b98a19ebf383ff38249981a33854b7e57f3faa25718821f9af40d75998741cc07f8aca05e3" + } + ], + "outputs": [ + { + "satoshis": 100000000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 306020000, + "script": "OP_DUP OP_HASH160 20 0xc8777e802750fee614119065e66c183773458181 OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "f03f039cd6926fcc139acfe2e1ef28d8277e78a7ffd54139472bbd765f45d70d", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "473044022052921d6c39ec0ec9632d859e8558972d5f54ebc2c428507a22e7df4a4a77730d022006912a5ced330499763fb60140682d5d37ad0a4235ca51a4a5e5926b498aedca012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "71 0x3044022052921d6c39ec0ec9632d859e8558972d5f54ebc2c428507a22e7df4a4a77730d022006912a5ced330499763fb60140682d5d37ad0a4235ca51a4a5e5926b498aedca01 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 200000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 95650000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "8d11a156ca04e08a5394ee620d040746b8acb4497e44ef51e37a6ddb5991db40", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "473044022075a5afbba2f59026557b008b315d07edb6a591e78bc5bf9c3602843754f968920220503e85798ef2c5e1c726282a703e72be6128ea3772a502ee6f9d138087a12cb4012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "71 0x3044022075a5afbba2f59026557b008b315d07edb6a591e78bc5bf9c3602843754f968920220503e85798ef2c5e1c726282a703e72be6128ea3772a502ee6f9d138087a12cb401 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1200000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 86200000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "8da8a191da08c9797849598dd880363e268342503bbbbdb4afdb011f369efa0a", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "4730440220753f4e779fc281765ba85000e2f84e996d1faba8bc2e0f9e05f0fbdfbd9e930e0220354b8c039f3a06b11da1cbce620d6165cfd69350036934f279c5719d66a70144012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "71 0x30440220753f4e779fc281765ba85000e2f84e996d1faba8bc2e0f9e05f0fbdfbd9e930e0220354b8c039f3a06b11da1cbce620d6165cfd69350036934f279c5719d66a7014401 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1900000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 77600000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "c6701c4cd5b30d7415d188bbf87e965d4058abcfa8c70de0e3b3df693fab2320", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "47304402200b8c9ba268aa51ccf6b9ebbe673f32f4eaa8b5e8b84aebfa428c662f67f44c0202205aea35b3d25de07859ff4697486d64da76d1a8033493d6a57d8083d7f2ab11aa012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "71 0x304402200b8c9ba268aa51ccf6b9ebbe673f32f4eaa8b5e8b84aebfa428c662f67f44c0202205aea35b3d25de07859ff4697486d64da76d1a8033493d6a57d8083d7f2ab11aa01 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1600000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 73200000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "48cc65dd9bd45323d755a66f816c02a7f8b25b6088cc824d6f57a520e905dd41", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "473044022009587fede4f3cb970224f93e29f81312919c7525c2c6fca89e535354d9749814022075ece88dbdcbf88168d2393641f86843bbb8f870c76bcbe10fc894a43b7240a5012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "71 0x3044022009587fede4f3cb970224f93e29f81312919c7525c2c6fca89e535354d9749814022075ece88dbdcbf88168d2393641f86843bbb8f870c76bcbe10fc894a43b7240a501 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1000000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 62950000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "0cff60acf73b4fd7a3e844a958d07efa434f71a0fe5108983e4d4203065ea792", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "473044022072770655546f2b8bd2a3924addde016fc02bde62f8d03b64fb6cc46aea6756ee0220023f82806ce437c038d87ba5cf83332d1bd81e907a212f18265a8c8fa7cd7930012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "71 0x3044022072770655546f2b8bd2a3924addde016fc02bde62f8d03b64fb6cc46aea6756ee0220023f82806ce437c038d87ba5cf83332d1bd81e907a212f18265a8c8fa7cd793001 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1400000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 55550000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "8779334c04a2af6fcdf60cff0e14ec2aa34163ced77949622157b924b2fa83e1", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "47304402206381f3c28c0298df357c489fdb8e5c05897dc7a767ec05ac61a7dfa0ec7461a802202c8724e5eeb503f5611695048c1c39d40275a082a6229102d05aebc017d2b6e0012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "71 0x304402206381f3c28c0298df357c489fdb8e5c05897dc7a767ec05ac61a7dfa0ec7461a802202c8724e5eeb503f5611695048c1c39d40275a082a6229102d05aebc017d2b6e001 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1600000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 51550000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "8f40d17d22a0362e56d6f4167247908519c444946c10f8ed43d478ded807e9b8", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "473044022013088ae86f577ce328b709c9656262c07a8cd0c12b03ae62d6f17c781800578802205649101638e2db8456272dd6d92aca14087dc789d11d1a33a75c09f91b4e206f012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "71 0x3044022013088ae86f577ce328b709c9656262c07a8cd0c12b03ae62d6f17c781800578802205649101638e2db8456272dd6d92aca14087dc789d11d1a33a75c09f91b4e206f01 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 400000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 44000000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "c1094d652e483e9a070b18676d4cd4bb2476fc837d50003e641544147fb14d63", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "483045022100d32c7977a4d9121dcfd8287cc5bed90866c3baa9a1e9678d4426c387c450f3ca022019388090d3000fe27b84324deb80f0de06981726233716957ff43d113076832a012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "72 0x3045022100d32c7977a4d9121dcfd8287cc5bed90866c3baa9a1e9678d4426c387c450f3ca022019388090d3000fe27b84324deb80f0de06981726233716957ff43d113076832a01 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1300000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 95200000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "053036bb12c437ecf22ccff33e3c8a7b7ea5a3a8ac81885d1e1d85fc78f4e122", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "48304502205bb2ed237ccff66f1cf7a7091a3b28c61987e220e076e9435f57c1859638717202210082eb1417b32499ebc329b5aa9224a735cae0e188379719811c6d071fe2fc670a012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "72 0x304502205bb2ed237ccff66f1cf7a7091a3b28c61987e220e076e9435f57c1859638717202210082eb1417b32499ebc329b5aa9224a735cae0e188379719811c6d071fe2fc670a01 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 700000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 95300000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "09bed750d5935e854b3981c5c5c08761fe0fb66842c5cb6f6608e543fc332cb8", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "4830450220184569aa17149167d8259a65b193224bf844f2330b25f35d437adbd87f99f0df022100c32791d0885c8c7fa8809d50c85e254d04766d13a109abac68ddf917ec6387b4012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "72 0x30450220184569aa17149167d8259a65b193224bf844f2330b25f35d437adbd87f99f0df022100c32791d0885c8c7fa8809d50c85e254d04766d13a109abac68ddf917ec6387b401 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 600000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 93050000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "162ba95a53e62b860fedc63381e4dd79a639d141e9ec80d758dd4db5393cd43a", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "483045022078168958b0079bff93229b29342e33cbb1c00be713c4bd76ad7ba1572f49ac26022100d869e3b0e6d69fa97710e6a373e404f1c2ea0ceb1f80bb8674aec2ae4c2a9770012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "72 0x3045022078168958b0079bff93229b29342e33cbb1c00be713c4bd76ad7ba1572f49ac26022100d869e3b0e6d69fa97710e6a373e404f1c2ea0ceb1f80bb8674aec2ae4c2a977001 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 200000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 93400000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "36672b676e950d878ccf9a176a2cee22e63ccd3b4ea3aaac36277b8694120a81", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "483045022100d55d68b7df42d5c793db94a780e35f4dcf9b8ffb72c86bfa2242e6ab1d92b8290220465b6cc8e49a8ece95b598449d3ed8f3fc122b34e5943d88cd739c51b6002752012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "72 0x3045022100d55d68b7df42d5c793db94a780e35f4dcf9b8ffb72c86bfa2242e6ab1d92b8290220465b6cc8e49a8ece95b598449d3ed8f3fc122b34e5943d88cd739c51b600275201 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 500000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 92700000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "39ab4ae54e8ab31d53adc4918592fad158d8d19bea95eb8e48ccd8ce8ba31992", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "483045022100d90c876ec99988db9e9a99b4a8cfc59073858c101076ac7f6e41d84ca09d323f0220405bd97725ab9aef0d3c44df1b433a649276674490941f4026787435368eb7fb012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "72 0x3045022100d90c876ec99988db9e9a99b4a8cfc59073858c101076ac7f6e41d84ca09d323f0220405bd97725ab9aef0d3c44df1b433a649276674490941f4026787435368eb7fb01 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1800000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 91000000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "c8d899a52c5a6a74ac03a3cbc4b7f40927440a3ddeed7ff45ca94e76c2f19deb", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "48304502204ae7a5aac74952e2646737e0845b51e710dc0a6917297e823c9532bea0efa0ea022100ed0823e17f882f22f532dc138ab849501617be16a8040415727b3a6a5527bb7a012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "72 0x304502204ae7a5aac74952e2646737e0845b51e710dc0a6917297e823c9532bea0efa0ea022100ed0823e17f882f22f532dc138ab849501617be16a8040415727b3a6a5527bb7a01 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 700000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 91200000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "cc009e595ddb4711f0770fb126a454303907fb382d7d1da523c865c87b0cca31", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "48304502206c1f6806325dbe140cc0f3112c8eb985031837b605dde2044ef8f974cad004a7022100e16c9d3226c5782dfbfa6cb1d5e8c0839401400840ae5b6be5ff46f120cd5461012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "72 0x304502206c1f6806325dbe140cc0f3112c8eb985031837b605dde2044ef8f974cad004a7022100e16c9d3226c5782dfbfa6cb1d5e8c0839401400840ae5b6be5ff46f120cd546101 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1700000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 88550000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "c6a22d58e4ad2df172ba3883cd1266cc5ea9d47c811ebb786a80974a884307e9", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "483045022100fc4d41f35838962a0af5b1c0b11046a6dc34e2dd08f5736b4a14d815927ea88b022042e746b327c628f6aacba0e9393a0f6aed9874a360d6505b8a949bce6cb8945e012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "72 0x3045022100fc4d41f35838962a0af5b1c0b11046a6dc34e2dd08f5736b4a14d815927ea88b022042e746b327c628f6aacba0e9393a0f6aed9874a360d6505b8a949bce6cb8945e01 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1900000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 87600000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "78e3238047dae67e195827a79454856d58358e979ec567f6655dff838919c1e6", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "48304502207b95d9340b6deabb5b144e29f0d644afaa0315ecda4cd2ac40fb45b1d425718b0221009f40082ed2e3559b607ecfc7a221189fbd94a65c3e03ce2206a22cb834fa46e6012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "72 0x304502207b95d9340b6deabb5b144e29f0d644afaa0315ecda4cd2ac40fb45b1d425718b0221009f40082ed2e3559b607ecfc7a221189fbd94a65c3e03ce2206a22cb834fa46e601 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1100000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 87050000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "8e029b02822bd5957f1016738857de6a260df0240f94e4695a31d1666dacb76a", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "48304502203bd4d4baa140e67035e06a60ad832907dea4fdcb9fd2bd3bf3c3eed7f4f9e768022100b2bccc2479d3e7e30dc0d986e34a927ef2389f8a59d8407b5436a24212d946fa012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "72 0x304502203bd4d4baa140e67035e06a60ad832907dea4fdcb9fd2bd3bf3c3eed7f4f9e768022100b2bccc2479d3e7e30dc0d986e34a927ef2389f8a59d8407b5436a24212d946fa01 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1400000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 75800000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "99331fa7a3b37d71372584694fa11e82555978e98a309a4705d4810c8fe84a16", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "48304502206f28d49222f3ec486ea171870579f87efec72954828d8b8ad52f5ed931c9fb15022100d4f386166e65f8b517ee1cfe5888a41c87b6a23e9201f7d1608920b6639255bc012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "72 0x304502206f28d49222f3ec486ea171870579f87efec72954828d8b8ad52f5ed931c9fb15022100d4f386166e65f8b517ee1cfe5888a41c87b6a23e9201f7d1608920b6639255bc01 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 900000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 71850000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "b2ba338551b93a8425b485d3021a2fd1a574878f859d19e92dfd28ae6799c70e", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "483045022100a75155e20536cd75f5268878ec6a88f5a3db17c5031e746b2b09782da592e43b022077941e2d648ddfcb91e0c3f8efff25faafccd82a6ae60ce189281826f35e78f9012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "72 0x3045022100a75155e20536cd75f5268878ec6a88f5a3db17c5031e746b2b09782da592e43b022077941e2d648ddfcb91e0c3f8efff25faafccd82a6ae60ce189281826f35e78f901 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1000000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 69650000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "0f1f3de936930c1042aab11d4bb2acac10e58051b6af7ce64893569f1349e023", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "483045022100d40e99eb227a3c8c65dfb66be643776d64ffdf2787374f6cf10561ed33b4d0ff022035558f7a04b6bb5ef0aef203c0686e11cf7c224ecddf122e092d7d89bc0c94a1012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "72 0x3045022100d40e99eb227a3c8c65dfb66be643776d64ffdf2787374f6cf10561ed33b4d0ff022035558f7a04b6bb5ef0aef203c0686e11cf7c224ecddf122e092d7d89bc0c94a101 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1500000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 65600000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "2a2d939a69f93c36de5f4f0da1c8a651820aeace8fc264d6a558423e3bf3b88a", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "483045022100d55857fcedcef64d4457fdadcefdfb0a0c80d050fc62dec643b231c3c14ca7c0022061cb9d2227c26c9a2b35d62839b2173a49727f4fac2b9786732f90e97af116a6012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "72 0x3045022100d55857fcedcef64d4457fdadcefdfb0a0c80d050fc62dec643b231c3c14ca7c0022061cb9d2227c26c9a2b35d62839b2173a49727f4fac2b9786732f90e97af116a601 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 300000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 59300000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "3bd9cf9809b729b93a1d97397013019e276a11a5d6a108a87cf2175d42560cdd", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "4830450220099f59fd6dd54f360f5ec39c856e890362f98a9239dff583e639490004d17111022100c9d47c6a560b4b4aa26bacd49fb3e82d5d68f0616be1d42112d9bcf6e1b1c284012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "72 0x30450220099f59fd6dd54f360f5ec39c856e890362f98a9239dff583e639490004d17111022100c9d47c6a560b4b4aa26bacd49fb3e82d5d68f0616be1d42112d9bcf6e1b1c28401 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1300000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 43350000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "7f007ee0bb95bdc05f9d42b93c708e962d0aea3fbeb7750eb5769330714464a6", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "483045022100e0a2ba7d2ae16f302c08f98cadd0e4bfe283c7b78576909cf6179a9eb76b656a022027c29b42e0a2d6dc00bca3e2b499e6096e0d1605da6e1ffaa3f4bb70ff2ba6e1012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "72 0x3045022100e0a2ba7d2ae16f302c08f98cadd0e4bfe283c7b78576909cf6179a9eb76b656a022027c29b42e0a2d6dc00bca3e2b499e6096e0d1605da6e1ffaa3f4bb70ff2ba6e101 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1800000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 41850000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "3952e193feadce900d49d807006b0b39aa2d3dba12e37c8820d773e83fa87a6c", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "493046022100b2634c5250e470106436a3b176f73770f5d959ced9302b0379055045bdfb63a6022100ab8083e535552b5a26a42e7b95dba40527208af53a360fc3e406e9cfcf8367bb012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "73 0x3046022100b2634c5250e470106436a3b176f73770f5d959ced9302b0379055045bdfb63a6022100ab8083e535552b5a26a42e7b95dba40527208af53a360fc3e406e9cfcf8367bb01 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 100000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 94850000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "876cb2f4550d3ab59f92304434026dad213d8cf17c4743b93e1267cae3c3b504", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "493046022100e7921534c2b83eeba6ee9ae3a388c68602ea11e272c2f39f457406ef48473eac022100d720375d3be91a305c6dd3d9be033baaf1a28b8e5b98a1af292a83400f4e737a012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "73 0x3046022100e7921534c2b83eeba6ee9ae3a388c68602ea11e272c2f39f457406ef48473eac022100d720375d3be91a305c6dd3d9be033baaf1a28b8e5b98a1af292a83400f4e737a01 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1700000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 92700000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "e7acb8c75af586f31cdffae4c88e7e4a01f29722aec708f6a7bfe8ea035f792a", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "493046022100c934120dc5a775641db7134d561cd6d5510033341da5d7cbdf7543611de62fd2022100f82c672b8e3adec18ea634a277d23ecfaedce1553424470705bece3cf63f2f46012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "73 0x3046022100c934120dc5a775641db7134d561cd6d5510033341da5d7cbdf7543611de62fd2022100f82c672b8e3adec18ea634a277d23ecfaedce1553424470705bece3cf63f2f4601 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 2000000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 91850000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "176d4ab48674b4296a6b4b3a2578ac4799bc4688ee10bb4f9dac65db24da5a98", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "493046022100b3257567410d7092c668f9aede4ec6737b53981a352381789ec469537e71cfb5022100c38235223f68e7f0fe65105f9ab5f0e5db09591794c3c9cfccfc21cd86bd4be5012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "73 0x3046022100b3257567410d7092c668f9aede4ec6737b53981a352381789ec469537e71cfb5022100c38235223f68e7f0fe65105f9ab5f0e5db09591794c3c9cfccfc21cd86bd4be501 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 800000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 92750000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "aa9f6070ef4a956cc558e750fcd85201ac47dd571e1d41ff67732c520ba8e5db", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "4930460221008a74bc10d2cc2135ac32a6f93a330ca8d0ececd9777ee5521eb81682eca18814022100dc71e0205ec06389be8ba858926671c82a81fe479f52acf8889b66589890c26d012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "73 0x30460221008a74bc10d2cc2135ac32a6f93a330ca8d0ececd9777ee5521eb81682eca18814022100dc71e0205ec06389be8ba858926671c82a81fe479f52acf8889b66589890c26d01 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 600000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 92550000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "ec2fadda6dcbd1be5209971d3a3ef07e0e047bad245ca64d4086affd2e054029", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "4930460221008a0d279344c451cd74d760b2f1b514f39071fd875bcd53e3079d09e476c5d0a6022100c62d2ec2136ff41959fd95184b761129baa0d2ea798073411d7acd3866fc904a012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "73 0x30460221008a0d279344c451cd74d760b2f1b514f39071fd875bcd53e3079d09e476c5d0a6022100c62d2ec2136ff41959fd95184b761129baa0d2ea798073411d7acd3866fc904a01 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 800000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 90700000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "12f23c6fcabb0d1971238164d5539c729fd7219721b060e91373a03ef37d944f", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "493046022100b75a6181a7b66c0d75926c1f65c966d66bc954c5f34f7903102fe16c2e6473050221009d2cb610d6a510416e3565cf2ab3674635ca67f2c95f8a2a24452b41524f614e012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "73 0x3046022100b75a6181a7b66c0d75926c1f65c966d66bc954c5f34f7903102fe16c2e6473050221009d2cb610d6a510416e3565cf2ab3674635ca67f2c95f8a2a24452b41524f614e01 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 900000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 90300000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "b2819d58cc0059fd912c384f24df901ffff862ce69c1433028dd9d3df5fbbce4", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "493046022100d12c9f3544226566309c3430c826c829aa70bf186763aa742c20c27c6719f1f7022100931599227951f1e46839fc5eda88816c6591f2162b9db918c47e0a1499861a1c012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "73 0x3046022100d12c9f3544226566309c3430c826c829aa70bf186763aa742c20c27c6719f1f7022100931599227951f1e46839fc5eda88816c6591f2162b9db918c47e0a1499861a1c01 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1200000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 87750000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "ed08a375b5e486bcd606c65ddcbdd8e1c96ceb5b836247fdcce9e6c0b76bd81c", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "493046022100a7600feec0ac6f51dc4ab018f8777e713746b80702039b6e521aea587a8d4c580221009a7dbc8c1f3e32cb3d05a505f86ed5f95f04a17004a4dc5efb183729a2d57cf5012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "73 0x3046022100a7600feec0ac6f51dc4ab018f8777e713746b80702039b6e521aea587a8d4c580221009a7dbc8c1f3e32cb3d05a505f86ed5f95f04a17004a4dc5efb183729a2d57cf501 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 100000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 78300000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "d5e83351428fad33a5c004b28230ca75e00249f3cf6465f812ea1ed885ed0684", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "493046022100c938882acecf93342397822044b3ff80f7c2454f4f917460a8d9fea7b8b4275a022100aa8690eff16359f156c1aa051a76ce19bf9bbce6b78e655d08a8759a30b8f9fb012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "73 0x3046022100c938882acecf93342397822044b3ff80f7c2454f4f917460a8d9fea7b8b4275a022100aa8690eff16359f156c1aa051a76ce19bf9bbce6b78e655d08a8759a30b8f9fb01 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 300000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 77000000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "07096db7b40e9f50d69c8b9c99ac60eb4a8fac9f9296709f75d72638abe1ccf9", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "493046022100b4985ed42f7ec5d4f6e49cd87ba1985b4e1e3ce04c79d9c12964c474870fa7f3022100e70056ce9f1d73795cffa52ce3a613f18b2ba05884d21f9fad9adce0eebfb05a012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "73 0x3046022100b4985ed42f7ec5d4f6e49cd87ba1985b4e1e3ce04c79d9c12964c474870fa7f3022100e70056ce9f1d73795cffa52ce3a613f18b2ba05884d21f9fad9adce0eebfb05a01 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 400000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 71400000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "fc7c3d2fe443be6975852e0fe4a7d42b8fb8988ad8b401437955f3627c0833cc", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "493046022100f4f6b8fd29966f3dbe7323166f70ae7d880638781821817069d13886a248398f022100f0f206155e1ef2743447abcbfd1592d6c76e7b7583c2817f6182c58ff1734a53012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "73 0x3046022100f4f6b8fd29966f3dbe7323166f70ae7d880638781821817069d13886a248398f022100f0f206155e1ef2743447abcbfd1592d6c76e7b7583c2817f6182c58ff1734a5301 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 500000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 56550000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "a8f63d5e8e5c80dbe6becba028df5f95263f6bffa4a23d9310962bfbd2b33317", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "493046022100d5ef6a8c81300da360e190d53bec4229e4deabeb8441409bd3a85cfdb125a7640221009059cd4c99c43d2568fd1b4e834e9c9f5710ae310fe0b5f37cb20c15982fa74f012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "73 0x3046022100d5ef6a8c81300da360e190d53bec4229e4deabeb8441409bd3a85cfdb125a7640221009059cd4c99c43d2568fd1b4e834e9c9f5710ae310fe0b5f37cb20c15982fa74f01 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1100000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 48250000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "81b5b81bc92210d816e0f49006361138ace329b7a7183ef6eb11975b19696a73", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "493046022100d44ede53f364f982d3127faef609ee523802d3697028d3fa12fdaa3810f125b7022100eff930ed0bac55e1570bbe5701b493aa003bf708a7c2706d2488c0b78785e307012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "73 0x3046022100d44ede53f364f982d3127faef609ee523802d3697028d3fa12fdaa3810f125b7022100eff930ed0bac55e1570bbe5701b493aa003bf708a7c2706d2488c0b78785e30701 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 1500000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 45450000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "2a9ec468c4853d69770d2e98311b94e791b64220e2007a3417ea62f75d7ca292", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "493046022100cf062de21fd98a2a07c07ad6bb5ab44dc1bbc1f73e1e6d3d7322e8e63b281e1e022100eb7b5820f847571b063a3710db2b5e88a3c9bd905f2d5bd5ce66b329b30e5334012103bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30", + "scriptString": "73 0x3046022100cf062de21fd98a2a07c07ad6bb5ab44dc1bbc1f73e1e6d3d7322e8e63b281e1e022100eb7b5820f847571b063a3710db2b5e88a3c9bd905f2d5bd5ce66b329b30e533401 33 0x03bf755045f89a9203c4864fa11d556ae051d131f4169ee0d4d8d5fd9e07a7ca30" + } + ], + "outputs": [ + { + "satoshis": 2000000, + "script": "OP_DUP OP_HASH160 20 0xc48c902a25d7939668f8a3a1194179cf7bade0b9 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 21150000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "86fdd1937f743e43c712b022c956ed0a89ff35b973af20f927856f0c94d2b6c2", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "4930460221008d273bd1e178cbb8b70d0783a78e791f80281a52a11b7e5911dfcf8881b0138802210089698a838034f05aed27144b9e769b144625b9cc8ffb833b892b8367adc165a70121024c5e1fad91e5a595c604155f5878d5d1289299f519646c640c4589b44c4c96ee", + "scriptString": "73 0x30460221008d273bd1e178cbb8b70d0783a78e791f80281a52a11b7e5911dfcf8881b0138802210089698a838034f05aed27144b9e769b144625b9cc8ffb833b892b8367adc165a701 33 0x024c5e1fad91e5a595c604155f5878d5d1289299f519646c640c4589b44c4c96ee" + } + ], + "outputs": [ + { + "satoshis": 3799550000, + "script": "OP_DUP OP_HASH160 20 0xe3e95b09a5d8cb54b9ba41d4c8a6b8b25d1b18f3 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 100000000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "93c4ab19a2ef9604fc087b15481de3bdc7c0dcad55f1e3c9cb00a6e6467743e2", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "47304402204859e43b8d6c6eb36ecfc6fcc8e61ac53cf2262f93bfe571d9ae4446db7fd36e02200983d746d8e2451a1f70e71ec7a5d9d4bb4e1cbe033edab9603f87a6296d771e01210397a25d1ae2521140d9e82ea82ed65525ab6ff8f01f1d5a8b15cebd0ace020ed8", + "scriptString": "71 0x304402204859e43b8d6c6eb36ecfc6fcc8e61ac53cf2262f93bfe571d9ae4446db7fd36e02200983d746d8e2451a1f70e71ec7a5d9d4bb4e1cbe033edab9603f87a6296d771e01 33 0x0397a25d1ae2521140d9e82ea82ed65525ab6ff8f01f1d5a8b15cebd0ace020ed8" + } + ], + "outputs": [ + { + "satoshis": 3699500000, + "script": "OP_DUP OP_HASH160 20 0x2262d05117fe83a5a1206081c52f7bcd23def15a OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 100000000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "a42744aacbd4de90b6385c874817a64847452af226e0bc83f3f69cd38ad337fa", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "48304502200f996600263212e7e094508a9e3b59ab9b8a0fb0af8d6e2c684e06e7efaf4015022100959eb296fcb34f61bd602f28bb8f9d67800d1998e8f839c6a8af50352577cb450121030ab005540ec3c5eac275c6b7c4ca00f95ff6ff6d682179450f3b9d43d115049c", + "scriptString": "72 0x304502200f996600263212e7e094508a9e3b59ab9b8a0fb0af8d6e2c684e06e7efaf4015022100959eb296fcb34f61bd602f28bb8f9d67800d1998e8f839c6a8af50352577cb4501 33 0x030ab005540ec3c5eac275c6b7c4ca00f95ff6ff6d682179450f3b9d43d115049c" + } + ], + "outputs": [ + { + "satoshis": 3599450000, + "script": "OP_DUP OP_HASH160 20 0x02c957b6860b5fc23c04bb19a9f0c1e6e13e529e OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 100000000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + }, + { + "version": 1, + "inputs": [ + { + "prevTxId": "09ae727b0fecfd9e885c10edf3352c348b01440e7e5a0295fbf0b3d17a700e01", + "outputIndex": 0, + "sequenceNumber": 4294967295, + "script": "4730440220738a901daf78642718bdf15cbd93c8bbe33410f1bdd5647f363f167c1e986e9502201227251d4c2a003bc748bbeb585c02b7819f0bda7d29f42f5ce1e5a2eceaa9f5012102a477051089094556b31861a1a27f13e6c311e8b1f73fed07e5684b9dc4c0b466", + "scriptString": "71 0x30440220738a901daf78642718bdf15cbd93c8bbe33410f1bdd5647f363f167c1e986e9502201227251d4c2a003bc748bbeb585c02b7819f0bda7d29f42f5ce1e5a2eceaa9f501 33 0x02a477051089094556b31861a1a27f13e6c311e8b1f73fed07e5684b9dc4c0b466" + } + ], + "outputs": [ + { + "satoshis": 3499400000, + "script": "OP_DUP OP_HASH160 20 0x793e1587533d77be40161349451c7df1a3c081a2 OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 100000000, + "script": "OP_DUP OP_HASH160 20 0xa44048be6ba9ade8411019c00ef113dcb34f5afe OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 + } + ] +} +``` + + +GET '/v1/blocks/0000000040a24e14497879bdd67db948cf30edc5d0a5833e8cb2736582157b49' +``` + +``` + + +GET '/v1/blocks/4' ### Transaction routes -GET '/transactions/:txHash([A-Fa-f0-9]{64})' -POST '/transactions/send' +GET '/v1/transactions/:txHash([A-Fa-f0-9]{64})' +POST '/v1/transactions/send' ### Input routes -GET '/transactions/:txHash([A-Fa-f0-9]{64})/inputs' -GET '/transactions/:txHash([A-Fa-f0-9]{64})/inputs/:index([0-9]+)' +GET '/v1/transactions/:txHash([A-Fa-f0-9]{64})/inputs' +GET '/v1/transactions/:txHash([A-Fa-f0-9]{64})/inputs/:index([0-9]+)' ### Output routes -GET '/transactions/:txHash([A-Fa-f0-9]{64})/outputs' -GET '/transactions/:txHash([A-Fa-f0-9]{64})/outputs/:index([0-9]+)' +GET '/v1/transactions/:txHash([A-Fa-f0-9]{64})/outputs' +GET '/v1/transactions/:txHash([A-Fa-f0-9]{64})/outputs/:index([0-9]+)' ### Address routes -GET '/addresses/:address' -GET '/addresses/:address/transactions' -GET '/addresses/:addresses/utxos' +GET '/v1/addresses/:address' +GET '/v1/addresses/:address/transactions' +GET '/v1/addresses/:addresses/utxos' diff --git a/api/controllers/blocks.js b/api/controllers/blocks.js index a1ed647e..11c26124 100644 --- a/api/controllers/blocks.js +++ b/api/controllers/blocks.js @@ -1,11 +1,10 @@ 'use strict'; var bitcore = require('bitcore'); -var _ = bitcore.deps._; var $ = bitcore.util.preconditions; var Block = bitcore.Block; -var BitcoreNode = require('../../'); +var errors = require('../../lib/errors'); var Blocks = {}; @@ -28,7 +27,7 @@ Blocks.blockHashParam = function(req, res, next, blockHash) { req.block = block; }) .then(next) - .catch(BitcoreNode.errors.Blocks.NotFound, function() { + .catch(errors.Blocks.NotFound, function() { res.status(404).send('Block with id ' + blockHash + ' not found'); }) .catch(function() { @@ -46,7 +45,7 @@ Blocks.heightParam = function(req, res, next, height) { req.block = block; }) .then(next) - .catch(BitcoreNode.errors.Blocks.NotFound, function() { + .catch(errors.Blocks.NotFound, function() { res.status(404).send('Block with height ' + height + ' not found'); }) .catch(function() { diff --git a/api/controllers/transactions.js b/api/controllers/transactions.js index 5bf4244f..6be1e860 100644 --- a/api/controllers/transactions.js +++ b/api/controllers/transactions.js @@ -7,7 +7,7 @@ var _ = bitcore.deps._; var $ = bitcore.util.preconditions; var Transaction = bitcore.Transaction; -var BitcoreNode = require('../../'); +var errors = require('../../lib/errors'); var Transactions = {}; @@ -30,7 +30,7 @@ Transactions.txHashParam = function(req, res, next, txHash) { req.tx = tx; }) .then(next) - .catch(BitcoreNode.errors.Transactions.NotFound, function() { + .catch(errors.Transactions.NotFound, function() { res.status(404).send('Transaction with id ' + txHash + ' not found'); }) .catch(function() { @@ -81,7 +81,7 @@ Transactions.send = function(req, res) { .then(function() { res.send('Transaction broadcasted successfully'); }) - .catch(BitcoreNode.errors.Transactions.CantBroadcast, function(err) { + .catch(errors.Transactions.CantBroadcast, function(err) { res.status(422).send(err.message); }); }; diff --git a/index.js b/index.js index 4feb1448..ff345e21 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,6 @@ 'use strict'; var BitcoreNode = require('./lib/node'); -BitcoreNode.errors = require('./lib/errors'); var BitcoreHTTP = require('./api/lib/http'); var bitcore = require('bitcore'); var Promise = require('bluebird'); diff --git a/lib/node.js b/lib/node.js index 0d7ac927..4c6b470f 100644 --- a/lib/node.js +++ b/lib/node.js @@ -223,4 +223,6 @@ BitcoreNode.prototype.sync = function() { }); }; +var errors = require('./errors'); +BitcoreNode.errors = errors; module.exports = BitcoreNode; diff --git a/lib/services/transaction.js b/lib/services/transaction.js index 7f581db4..a955f4ed 100644 --- a/lib/services/transaction.js +++ b/lib/services/transaction.js @@ -20,12 +20,11 @@ var LevelUp = require('levelup'); var Promise = require('bluebird'); var bitcore = require('bitcore'); var config = require('config'); -var BitcoreNode = require('../../'); +var errors = require('../errors'); var _ = bitcore.deps._; var $ = bitcore.util.preconditions; -var NULLTXHASH = bitcore.util.buffer.emptyBuffer(32).toString('hex'); var GENESISTX = '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b'; var helper = function(name) { @@ -87,7 +86,7 @@ TransactionService.Index = Index; var txNotFound = function(error) { if (error.message === 'No information available about transaction') { - throw new BitcoreNode.errors.Transactions.NotFound(); + throw new errors.Transactions.NotFound(); } throw error; }; From a23d242f8c92681615019cb25138ce9e123bae56 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 07:30:44 -0300 Subject: [PATCH 14/21] readme --- README.md | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cd458050..f63a85ba 100644 --- a/README.md +++ b/README.md @@ -1665,11 +1665,72 @@ GET '/v1/blocks/latest' GET '/v1/blocks/0000000040a24e14497879bdd67db948cf30edc5d0a5833e8cb2736582157b49' ``` - +{ + "header": { + "version": 1, + "prevHash": "00000000423cc5a91cb52e9e1ee5bc817b50c74e11f3f4424d92f45ebae69663", + "merkleRoot": "598df49f42632c33ca0afb3875dda82391adb6cacfe15cd6067a7baf0892af49", + "time": 1296699374, + "bits": 486604799, + "nonce": 3542639877 + }, + "transactions": [ + { + "version": 1, + "inputs": [ + { + "prevTxId": "0000000000000000000000000000000000000000000000000000000000000000", + "outputIndex": 4294967295, + "sequenceNumber": 4294967295, + "script": "04ee0f4a4d0103062f503253482f" + } + ], + "outputs": [ + { + "satoshis": 5000000000, + "script": "33 0x03628ac026185f6e94d9c789ffe5cb92c0c4442a4b124b8f6811fa2e8cd2d7aeda OP_CHECKSIG" + } + ], + "nLockTime": 0 + } + ] +} ``` GET '/v1/blocks/4' +``` +{ + "header": { + "version": 1, + "prevHash": "000000008b896e272758da5297bcd98fdc6d97c9b765ecec401e286dc1fdbe10", + "merkleRoot": "2d1f657e970f724c4cd690494152a83bd297cd10e86ed930daa2dd76576d974c", + "time": 1296689066, + "bits": 486604799, + "nonce": 1081518338 + }, + "transactions": [ + { + "version": 1, + "inputs": [ + { + "prevTxId": "0000000000000000000000000000000000000000000000000000000000000000", + "outputIndex": 4294967295, + "sequenceNumber": 4294967295, + "script": "04aae7494d011d062f503253482f" + } + ], + "outputs": [ + { + "satoshis": 5000000000, + "script": "33 0x021f72de1cff1777a9584f31adc458041814c3bc39c66241ac4d43136d7106aebe OP_CHECKSIG" + } + ], + "nLockTime": 0 + } + ] +} +``` ### Transaction routes GET '/v1/transactions/:txHash([A-Fa-f0-9]{64})' From 46420b79309c15b48f010567c860503686484f31 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 07:40:38 -0300 Subject: [PATCH 15/21] readme --- README.md | 78 +++++++++++++++++++++++++++------ api/controllers/transactions.js | 4 +- 2 files changed, 66 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index f63a85ba..476d8efa 100644 --- a/README.md +++ b/README.md @@ -133,7 +133,7 @@ https://docs.google.com/document/d/1rXQdfr8VDBSzheEn0KynnCKCMB0oAsMunkjdG4aY-18 Here is a small summary via examples: ### Node routes -GET '/v1/node' +####GET '/v1/node' ``` { "sync": 0.0011844682935139, @@ -145,7 +145,7 @@ GET '/v1/node' ``` ### Block routes -GET '/v1/blocks?from=100&offset=4&limit=2' +####GET '/v1/blocks?from=100&offset=4&limit=2' ``` [ { @@ -211,7 +211,7 @@ GET '/v1/blocks?from=100&offset=4&limit=2' ] ``` -GET '/v1/blocks/latest' +####GET '/v1/blocks/latest' ``` { "header": { @@ -1663,7 +1663,7 @@ GET '/v1/blocks/latest' ``` -GET '/v1/blocks/0000000040a24e14497879bdd67db948cf30edc5d0a5833e8cb2736582157b49' +####GET '/v1/blocks/0000000040a24e14497879bdd67db948cf30edc5d0a5833e8cb2736582157b49' ``` { "header": { @@ -1698,7 +1698,7 @@ GET '/v1/blocks/0000000040a24e14497879bdd67db948cf30edc5d0a5833e8cb2736582157b49 ``` -GET '/v1/blocks/4' +####GET '/v1/blocks/4' ``` { "header": { @@ -1733,21 +1733,71 @@ GET '/v1/blocks/4' ``` ### Transaction routes -GET '/v1/transactions/:txHash([A-Fa-f0-9]{64})' -POST '/v1/transactions/send' +####GET '/v1/transactions/2ceea8fb53873ae3f61fb332bf844e5a35630a1a4885a212f84f63f39c638b5e' +``` +{ + "version": 1, + "inputs": [ + { + "prevTxId": "8e6a7fc6493064e4a1a957b03a1f95ec387c26d25ac40de01eac770a9574a4b8", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "4730440220608500a5381dcdbd529438f2f42c1feb936b776b6e53866fcc47f09dcb04f86402207c6bd88925a534159068f901dcf9d7e1e2b443afdccafac76739e06c13e93290012102021335f4a109182d6df47d0ab9aa0635217f2ad208ae403a86922edcbcb08e4f", + "scriptString": "71 0x30440220608500a5381dcdbd529438f2f42c1feb936b776b6e53866fcc47f09dcb04f86402207c6bd88925a534159068f901dcf9d7e1e2b443afdccafac76739e06c13e9329001 33 0x02021335f4a109182d6df47d0ab9aa0635217f2ad208ae403a86922edcbcb08e4f" + } + ], + "outputs": [ + { + "satoshis": 47203800, + "script": "OP_DUP OP_HASH160 20 0x7c8fe8004e1dfdf0826f357de9ff93db25a8239d OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 9490000, + "script": "OP_DUP OP_HASH160 20 0xbf158227da5604c112bdf5af744f30bb7e85c7bf OP_EQUALVERIFY OP_CHECKSIG" + } + ], + "nLockTime": 0 +} +``` + +####POST '/v1/transactions/send' +``` +Transaction broadcasted successfully +``` ### Input routes -GET '/v1/transactions/:txHash([A-Fa-f0-9]{64})/inputs' -GET '/v1/transactions/:txHash([A-Fa-f0-9]{64})/inputs/:index([0-9]+)' +####GET '/v1/transactions/2ceea8fb53873ae3f61fb332bf844e5a35630a1a4885a212f84f63f39c638b5e/inputs/`' +``` +[ + { + "prevTxId": "8e6a7fc6493064e4a1a957b03a1f95ec387c26d25ac40de01eac770a9574a4b8", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "4730440220608500a5381dcdbd529438f2f42c1feb936b776b6e53866fcc47f09dcb04f86402207c6bd88925a534159068f901dcf9d7e1e2b443afdccafac76739e06c13e93290012102021335f4a109182d6df47d0ab9aa0635217f2ad208ae403a86922edcbcb08e4f", + "scriptString": "71 0x30440220608500a5381dcdbd529438f2f42c1feb936b776b6e53866fcc47f09dcb04f86402207c6bd88925a534159068f901dcf9d7e1e2b443afdccafac76739e06c13e9329001 33 0x02021335f4a109182d6df47d0ab9aa0635217f2ad208ae403a86922edcbcb08e4f" + } +] +``` + +####GET '/v1/transactions/2ceea8fb53873ae3f61fb332bf844e5a35630a1a4885a212f84f63f39c638b5e/inputs/0`' +``` +{ + "prevTxId": "8e6a7fc6493064e4a1a957b03a1f95ec387c26d25ac40de01eac770a9574a4b8", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "4730440220608500a5381dcdbd529438f2f42c1feb936b776b6e53866fcc47f09dcb04f86402207c6bd88925a534159068f901dcf9d7e1e2b443afdccafac76739e06c13e93290012102021335f4a109182d6df47d0ab9aa0635217f2ad208ae403a86922edcbcb08e4f", + "scriptString": "71 0x30440220608500a5381dcdbd529438f2f42c1feb936b776b6e53866fcc47f09dcb04f86402207c6bd88925a534159068f901dcf9d7e1e2b443afdccafac76739e06c13e9329001 33 0x02021335f4a109182d6df47d0ab9aa0635217f2ad208ae403a86922edcbcb08e4f" +} +``` ### Output routes -GET '/v1/transactions/:txHash([A-Fa-f0-9]{64})/outputs' -GET '/v1/transactions/:txHash([A-Fa-f0-9]{64})/outputs/:index([0-9]+)' +####GET '/v1/transactions/:txHash([A-Fa-f0-9]{64})/outputs' +####GET '/v1/transactions/:txHash([A-Fa-f0-9]{64})/outputs/:index([0-9]+)' ### Address routes -GET '/v1/addresses/:address' -GET '/v1/addresses/:address/transactions' -GET '/v1/addresses/:addresses/utxos' +####GET '/v1/addresses/:address' +####GET '/v1/addresses/:address/transactions' +####GET '/v1/addresses/:addresses/utxos' diff --git a/api/controllers/transactions.js b/api/controllers/transactions.js index 6be1e860..31386caf 100644 --- a/api/controllers/transactions.js +++ b/api/controllers/transactions.js @@ -110,11 +110,11 @@ var buildIOHelper = function(name) { ' for ' + req.tx.id + ' not found, it only has ' + req.tx[name].length + ' ' + name + '.'); return; } - res.send(req.tx[name][req.index].toJSON()); + res.send(req.tx[name][req.index].toObject()); return; } res.send(req.tx[name].map(function(x) { - return x.toJSON(); + return x.toObject(); })); }; From 85ad9fcdb6e433bf3ae88cd243135b9c8e02d82b Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 08:45:48 -0300 Subject: [PATCH 16/21] final polish --- README.md | 91 +++++++++++++++++++++++++++++++-- api/controllers/addresses.js | 4 +- api/controllers/transactions.js | 12 ----- api/routes/v1.js | 1 - lib/services/address.js | 39 +++++++++++++- lib/services/block.js | 15 ------ 6 files changed, 125 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 476d8efa..97d78ff7 100644 --- a/README.md +++ b/README.md @@ -1791,14 +1791,95 @@ Transaction broadcasted successfully ``` ### Output routes -####GET '/v1/transactions/:txHash([A-Fa-f0-9]{64})/outputs' -####GET '/v1/transactions/:txHash([A-Fa-f0-9]{64})/outputs/:index([0-9]+)' +####GET '/v1/transactions/2ceea8fb53873ae3f61fb332bf844e5a35630a1a4885a212f84f63f39c638b5e/outputs' +``` +[ + { + "satoshis": 47203800, + "script": "OP_DUP OP_HASH160 20 0x7c8fe8004e1dfdf0826f357de9ff93db25a8239d OP_EQUALVERIFY OP_CHECKSIG" + }, + { + "satoshis": 9490000, + "script": "OP_DUP OP_HASH160 20 0xbf158227da5604c112bdf5af744f30bb7e85c7bf OP_EQUALVERIFY OP_CHECKSIG" + } +] +``` + +####GET '/v1/transactions/2ceea8fb53873ae3f61fb332bf844e5a35630a1a4885a212f84f63f39c638b5e/outputs/1' +``` +{ + "satoshis": 9490000, + "script": "OP_DUP OP_HASH160 20 0xbf158227da5604c112bdf5af744f30bb7e85c7bf OP_EQUALVERIFY OP_CHECKSIG" +} +``` ### Address routes -####GET '/v1/addresses/:address' -####GET '/v1/addresses/:address/transactions' -####GET '/v1/addresses/:addresses/utxos' +####GET '/v1/addresses/msWN7CbKLWh88P1Vr8pQa7DmZNSiy9xfkj' +``` +{ + "address": "mtBHBTKTZv74cytccymVq3weidcoy4o1UY", + "transactions": [ + "88c844570a227fe89d82e4e20d41576b95df8aa790a799bf7114dbed83b788b0", + "d1cd5072cf4f6bff12e46a1e7949e58b544abed969313d65263141b9c94221cd" + ], + "confirmed": { + "balance": 0, + "sent": 4900642709, + "received": 4900642709 + }, + "unconfirmed": { + "balance": 0, + "sent": 4900642709, + "received": 4900642709 + } +} +``` +####GET '/v1/addresses/:addresses/utxos' +``` +[ + { + "satoshis": 967008, + "script": "OP_DUP OP_HASH160 20 0x0b4322ac01719030a710b60b0a3397c074cf9edf OP_EQUALVERIFY OP_CHECKSIG", + "heightConfirmed": 410, + "address": "mgYW9pHcxjUSvqHwaJF48uFbrDfFoPAcjx", + "txId": "0c233e2730cb94dc85e32546060c2361d348921961ab957ae66acadf88a578f1", + "outputIndex": "1" + }, + { + "satoshis": 568367, + "script": "OP_DUP OP_HASH160 20 0x0b4322ac01719030a710b60b0a3397c074cf9edf OP_EQUALVERIFY OP_CHECKSIG", + "heightConfirmed": 417, + "address": "mgYW9pHcxjUSvqHwaJF48uFbrDfFoPAcjx", + "txId": "0ca394ce3c2feecb2957b3aa5ecdc964f706e0b4ceec96bfc1ace526a80c67d1", + "outputIndex": "1" + }, + { + "satoshis": 977315, + "script": "OP_DUP OP_HASH160 20 0x0b4322ac01719030a710b60b0a3397c074cf9edf OP_EQUALVERIFY OP_CHECKSIG", + "heightConfirmed": 421, + "address": "mgYW9pHcxjUSvqHwaJF48uFbrDfFoPAcjx", + "txId": "96bdd67bd1b80f70acc7cca454c5ca80cfc8ba621e0e93756c406977102b586a", + "outputIndex": "1" + }, + { + "satoshis": 496223, + "script": "OP_DUP OP_HASH160 20 0x0b4322ac01719030a710b60b0a3397c074cf9edf OP_EQUALVERIFY OP_CHECKSIG", + "heightConfirmed": 420, + "address": "mgYW9pHcxjUSvqHwaJF48uFbrDfFoPAcjx", + "txId": "97d561085af6041e2b570dd07d4ee8b49a2d5667776f2112fac611727f949b3b", + "outputIndex": "1" + }, + { + "satoshis": 123667, + "script": "OP_DUP OP_HASH160 20 0x0b4322ac01719030a710b60b0a3397c074cf9edf OP_EQUALVERIFY OP_CHECKSIG", + "heightConfirmed": 405, + "address": "mgYW9pHcxjUSvqHwaJF48uFbrDfFoPAcjx", + "txId": "e72f781efc41224cf37d1aa0c63fa4655a86b647233622e653b38eb3d379b1cc", + "outputIndex": "1" + } +] +``` ## License diff --git a/api/controllers/addresses.js b/api/controllers/addresses.js index ed1aefc8..8cfffbfe 100644 --- a/api/controllers/addresses.js +++ b/api/controllers/addresses.js @@ -23,7 +23,7 @@ Addresses.setNode = function(aNode) { * Finds an address' info by it's string representation */ Addresses.addressParam = function(req, res, next, address) { - if (!Address.isValid(address)) { + if (!Address.isValid(address, bitcore.Networks.defaultNetwork)) { res.status(422); res.send('/v1/addresses/ parameter must be a valid bitcoin address'); return; @@ -76,7 +76,7 @@ Addresses.utxos = function(req, res) { $.checkState(_.all(req.addresses, function(addr) { return addr instanceof Address; })); - node.getUTXOs(req.addresses) + node.addressService.getUnspent(req.addresses) .then(function(utxos) { res.send(utxos); }); diff --git a/api/controllers/transactions.js b/api/controllers/transactions.js index 31386caf..c819dc00 100644 --- a/api/controllers/transactions.js +++ b/api/controllers/transactions.js @@ -87,18 +87,6 @@ Transactions.send = function(req, res) { }; -/* - * Returns a list of transactions given certain request options - */ -Transactions.list = function(req, res) { - var opts = {}; - opts.address = req.address; - node.listTransactions(opts) - .then(function(transactions) { - res.send(transactions); - }); -}; - var buildIOHelper = function(name) { $.checkArgument(name === 'inputs' || name === 'outputs'); diff --git a/api/routes/v1.js b/api/routes/v1.js index 5faf1cb2..3449043c 100644 --- a/api/routes/v1.js +++ b/api/routes/v1.js @@ -44,7 +44,6 @@ function initRouter(node) { // Address routes router.get('/addresses/:address', Addresses.get); - router.get('/addresses/:address/transactions', Transactions.list); router.get('/addresses/:addresses/utxos', Addresses.utxos); // error routes diff --git a/lib/services/address.js b/lib/services/address.js index 76e6092e..f59e3caa 100644 --- a/lib/services/address.js +++ b/lib/services/address.js @@ -5,6 +5,7 @@ var bitcore = require('bitcore'); var TransactionService = require('./transaction'); var RPC = require('bitcoind-rpc'); var _ = bitcore.deps._; +var $ = bitcore.util.preconditions; var NULLTXHASH = bitcore.util.buffer.emptyBuffer(32).toString('hex'); var LASTTXHASH = bitcore.util.buffer.fill(bitcore.util.buffer.emptyBuffer(32), -1).toString('hex'); @@ -56,6 +57,7 @@ AddressService.processOutput = function(data) { var retrieveOutputs = function(indexFunction, processElement) { return function(address) { + $.checkArgument(address, 'address required'); var results = []; var self = this; @@ -81,11 +83,44 @@ AddressService.prototype.getAllOutputs = retrieveOutputs( AddressService.prototype.getSpent = retrieveOutputs( TransactionService.Index.getSpentOutputsForAddress, - function(element) { - return JSON.parse(element.value); + function(e) { + return AddressService.processOutput(e); } ); + +AddressService.prototype.getUnspent = function(addrs) { + + $.checkArgument(addrs, 'addresses required'); + $.checkArgument(_.isArray(addrs), 'addresses is array required'); + + var self = this; + return Promise.all(addrs.map(function(addr) { + return self.getUnspentForAddress(addr); + })) + .then(function(results) { + return _.flatten(results); + }); + + +}; +AddressService.prototype.getUnspentForAddress = function(addr) { + $.checkArgument(addr, 'address required'); + var all, spent; + var self = this; + return this.getAllOutputs(addr) + .then(function(s) { + all = s; + return self.getSpent(addr); + }) + .then(function(s) { + spent = s; + return _.filter(all, function(out) { + return !_.contains(spent, out); + }); + }); +}; + AddressService.prototype.buildAddressSummary = function(address, tip, allOutputs, spent, confirmations) { var result = {}; diff --git a/lib/services/block.js b/lib/services/block.js index d499e6c1..e828f8d7 100644 --- a/lib/services/block.js +++ b/lib/services/block.js @@ -206,8 +206,6 @@ BlockService.prototype.listBlocks = function(from, to, offset, limit) { var start = from + offset; var end = Math.min(to, start + limit); var blocks = []; - //console.log(from, to, offset, limit); - //console.log(start, end); // TODO: optimize: precompute heights and fetch all blocks in parallel? var fetchBlock = function(height) { if (height >= end) { @@ -284,37 +282,27 @@ BlockService.prototype.confirm = function(block, ops) { ops = ops || []; - //console.log(0); return Promise.try(function() { - //console.log(0.5); self._setHeader(ops, block); - //console.log(1); self._setNextBlock(ops, block.header.prevHash, block); - //console.log(3); self._setBlockHeight(ops, block); - //console.log(3); self._setBlockWork(ops, block); - //console.log(4); self._setBlockByTs(ops, block); - //console.log(4.1); self._setTip(ops, block); - //console.log(5); return Promise.all(block.transactions.map(function(transaction) { return self.transactionService._confirmTransaction(ops, block, transaction); })); }) .then(function() { - //console.log(6); return self.database.batchAsync(ops); }) .then(function() { - //console.log(7); return block; }); }; @@ -373,17 +361,14 @@ BlockService.prototype._setBlockByTs = function(ops, block) { /* var self = this; var key = Index.timestamp + block.header.time; - console.log('key', key); return Promise.try(function() { - console.log('a'); return self.database.getAsync(key); }) .then(function(result) { - console.log('b'); if (result === block.hash) { return Promise.resolve(); } else { From 671665c052d155f591d40b1337de83a68adeaaa7 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 08:59:28 -0300 Subject: [PATCH 17/21] fix address regressions --- api/controllers/addresses.js | 2 - api/test/v1/addresses.js | 29 +---- lib/services/address.js | 5 +- test/services/address.js | 245 ++++++++++++++++++++++++----------- 4 files changed, 178 insertions(+), 103 deletions(-) diff --git a/api/controllers/addresses.js b/api/controllers/addresses.js index 8cfffbfe..3edb2516 100644 --- a/api/controllers/addresses.js +++ b/api/controllers/addresses.js @@ -5,8 +5,6 @@ var _ = bitcore.deps._; var $ = bitcore.util.preconditions; var Address = bitcore.Address; -var BitcoreNode = require('../../'); - var Addresses = {}; var node; diff --git a/api/test/v1/addresses.js b/api/test/v1/addresses.js index 341a41f4..86cb8cd5 100644 --- a/api/test/v1/addresses.js +++ b/api/test/v1/addresses.js @@ -11,17 +11,11 @@ var _ = bitcore.deps._; var mockAddresses = require('../data/addresses'); -var mockTransactions = require('../data/transactions'); describe('BitcoreHTTP v1 addresses routes', function() { // mocks - var transactionList = _.values(mockTransactions); var nodeMock, agent; - var txs_for_addr = function(addr) { - var amount = mockAddresses[addr].summary.transactions.length; - return transactionList.slice(0, amount); - }; var utxos_for_addrs = function(addrs) { return _.reduce(addrs, function(utxos, addr) { return utxos.concat(mockAddresses[addr].utxos); @@ -53,10 +47,7 @@ describe('BitcoreHTTP v1 addresses routes', function() { nodeMock.addressService.getSummary = function(address) { return Promise.resolve(mockAddresses[address.toString()].summary); }; - nodeMock.listTransactions = function(opts) { - return Promise.resolve(txs_for_addr(opts.address)); - }; - nodeMock.getUTXOs = function(addresses) { + nodeMock.addressService.getUnspent = function(addresses) { return Promise.resolve(utxos_for_addrs(addresses)); }; agent = require('../app')(nodeMock); @@ -77,19 +68,7 @@ describe('BitcoreHTTP v1 addresses routes', function() { it('works with valid address ' + addr, function(cb) { agent.get('/v1/addresses/' + addr) .expect(200) - .expect(JSON.stringify(info.summary), cb); - }); - }); - }); - describe('/addresses/:address/transactions', function() { - it('fails with invalid address', function(cb) { - failsWithInvalidAddress(agent, '/v1/addresses/1BpbpfLdY7oBS9gK7aDXgvMgr1DpvNH3B2/transactions', cb); - }); - _.keys(mockAddresses).forEach(function(addr) { - it('works with valid address ' + addr, function(cb) { - agent.get('/v1/addresses/' + addr + '/transactions') - .expect(200) - .expect(JSON.stringify(txs_for_addr(addr)), cb); + .expect(info.summary, cb); }); }); }); @@ -104,7 +83,7 @@ describe('BitcoreHTTP v1 addresses routes', function() { it('works with valid address ' + addr, function(cb) { agent.get('/v1/addresses/' + addr + '/utxos') .expect(200) - .expect(JSON.stringify(utxos_for_addrs([addr])), cb); + .expect(utxos_for_addrs([addr]), cb); }); }); }); @@ -118,7 +97,7 @@ describe('BitcoreHTTP v1 addresses routes', function() { var path = '/v1/addresses/' + list + '/utxos'; agent.get(path) .expect(200) - .expect(JSON.stringify(utxos_for_addrs(addresses)), cb); + .expect(utxos_for_addrs(addresses), cb); }); }); }); diff --git a/lib/services/address.js b/lib/services/address.js index f59e3caa..40b754a8 100644 --- a/lib/services/address.js +++ b/lib/services/address.js @@ -3,7 +3,6 @@ var Promise = require('bluebird'); var bitcore = require('bitcore'); var TransactionService = require('./transaction'); -var RPC = require('bitcoind-rpc'); var _ = bitcore.deps._; var $ = bitcore.util.preconditions; @@ -15,8 +14,8 @@ function AddressService(opts) { opts = _.extend({}, opts); this.transactionService = opts.transactionService; this.blockService = opts.blockService; - this.database = opts.database || Promise.promisifyAll(new LevelUp(config.get('LevelUp'))); - this.rpc = opts.rpc || Promise.promisifyAll(new RPC(config.get('RPC'))); + this.database = opts.database; + this.rpc = opts.rpc; } AddressService.prototype.getSummary = function(address, confirmations) { diff --git a/test/services/address.js b/test/services/address.js index 7f8ad05b..41661930 100644 --- a/test/services/address.js +++ b/test/services/address.js @@ -6,7 +6,6 @@ var events = require('events'); var Promise = require('bluebird'); var bitcore = require('bitcore'); -var _ = bitcore.deps._; var AddressService = require('../../lib/services/address'); @@ -43,7 +42,9 @@ describe('AddressService', function() { beforeEach(initialize); it('calls internal functions as expected', function(done) { - service.blockService = { getLatest: sinon.mock() }; + service.blockService = { + getLatest: sinon.mock() + }; service.getAllOutputs = sinon.mock(); service.getSpent = sinon.mock(); service.buildAddressSummary = sinon.mock(); @@ -105,17 +106,16 @@ describe('AddressService', function() { AddressService.processOutput = sinon.stub(AddressService, 'processOutput'); AddressService.processOutput.onFirstCall().returns('processed'); - var element = {key: 'key', value: 'value'}; + var element = { + key: 'key', + value: 'value' + }; var address = '12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S'; service.getAllOutputs(address).then(function(arg) { - service.database.createReadStream.firstCall.args[0].should.deep.equal( - { - gte: 'txa-12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S-' - + '0000000000000000000000000000000000000000000000000000000000000000-0', - lte: 'txa-12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S-' - + 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff-4294967295' - } - ); + service.database.createReadStream.firstCall.args[0].should.deep.equal({ + gte: 'txa-12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S-' + '0000000000000000000000000000000000000000000000000000000000000000-0', + lte: 'txa-12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S-' + 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff-4294967295' + }); AddressService.processOutput.firstCall.args[0].should.equal(element); AddressService.processOutput.reset(); arg[0].should.equal('processed'); @@ -131,20 +131,23 @@ describe('AddressService', function() { var dataCall = new events.EventEmitter(); service.database.createReadStream.onFirstCall().returns(dataCall); - var element = {key: 'key', value: JSON.stringify({a: 'b'})}; + var element = { + key: 'key', + value: JSON.stringify({ + a: 'b' + }) + }; var address = '12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S'; - service.getSpent(address).then(function(arg) { - service.database.createReadStream.firstCall.args[0].should.deep.equal( - { - gte: 'txas-12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S-' - + '0000000000000000000000000000000000000000000000000000000000000000-0', - lte: 'txas-12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S-' - + 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff-4294967295' - } - ); - arg[0].should.deep.equal({a: 'b'}); - done(); - }); + service.getSpent(address) + .then(function(arg) { + service.database.createReadStream.firstCall.args[0].should.deep.equal({ + gte: 'txas-12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S-' + '0000000000000000000000000000000000000000000000000000000000000000-0', + lte: 'txas-12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S-' + 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff-4294967295' + }); + console.log(arguments); + arg[0].should.deep.equal('processed'); + done(); + }); dataCall.emit('data', element); dataCall.emit('end'); @@ -158,107 +161,203 @@ describe('AddressService', function() { var tip = { height: 10 }; - var allOutputs = [ - { + var allOutputs = [{ + satoshis: 10, + txId: 'A', + outputIndex: 1, + heightConfirmed: 1 + }]; + + it('calculates balance correctly for confirmed balance', function() { + var allOutputs = [{ satoshis: 10, txId: 'A', outputIndex: 1, heightConfirmed: 1 - } - ]; - - it('calculates balance correctly for confirmed balance', function() { - var allOutputs = [ { satoshis: 10, txId: 'A', outputIndex: 1, heightConfirmed: 1 } ]; + }]; var spendOutputs = []; service.buildAddressSummary(address, tip, allOutputs, spendOutputs).should.deep.equal({ address: address.toString(), transactions: ['A'], - confirmed: { balance: 10, sent: 0, received: 10 }, - unconfirmed: { balance: 10, sent: 0, received: 10 } + confirmed: { + balance: 10, + sent: 0, + received: 10 + }, + unconfirmed: { + balance: 10, + sent: 0, + received: 10 + } }); }); it('calculates balance correctly for unconfirmed balance', function() { - var allOutputs = [ - { satoshis: 20, txId: 'B', outputIndex: 1, heightConfirmed: 10 } - ]; - var spendOutputs = [ ]; + var allOutputs = [{ + satoshis: 20, + txId: 'B', + outputIndex: 1, + heightConfirmed: 10 + }]; + var spendOutputs = []; service.buildAddressSummary(address, tip, allOutputs, spendOutputs).should.deep.equal({ address: address.toString(), transactions: ['B'], - confirmed: { balance: 0, sent: 0, received: 0 }, - unconfirmed: { balance: 20, sent: 0, received: 20 } + confirmed: { + balance: 0, + sent: 0, + received: 0 + }, + unconfirmed: { + balance: 20, + sent: 0, + received: 20 + } }); }); it('works with multiple transactions', function() { - var allOutputs = [ - { satoshis: 10, txId: 'A', outputIndex: 1, heightConfirmed: 1 }, - { satoshis: 20, txId: 'B', outputIndex: 1, heightConfirmed: 10 } - ]; - var spendOutputs = [ - { spendInput: { prevTxId: 'A', outputIndex: 1 }, spentTx: 'A', heightSpent: 10 } - ]; + var allOutputs = [{ + satoshis: 10, + txId: 'A', + outputIndex: 1, + heightConfirmed: 1 + }, { + satoshis: 20, + txId: 'B', + outputIndex: 1, + heightConfirmed: 10 + }]; + var spendOutputs = [{ + spendInput: { + prevTxId: 'A', + outputIndex: 1 + }, + spentTx: 'A', + heightSpent: 10 + }]; service.buildAddressSummary(address, tip, allOutputs, spendOutputs).should.deep.equal({ address: address.toString(), transactions: ['A', 'B'], - confirmed: { balance: 10, sent: 0, received: 10 }, - unconfirmed: { balance: 20, sent: 10, received: 30 } + confirmed: { + balance: 10, + sent: 0, + received: 10 + }, + unconfirmed: { + balance: 20, + sent: 10, + received: 30 + } }); }); it('works with a medium amount of transactions', function() { - var allOutputs = [ - { satoshis: 10, txId: 'A', outputIndex: 1, heightConfirmed: 1 }, - { satoshis: 20, txId: 'B', outputIndex: 1, heightConfirmed: 5 }, - { satoshis: 30, txId: 'C', outputIndex: 1, heightConfirmed: 10 } - ]; - var spendOutputs = [ - { spendInput: { prevTxId: 'A', outputIndex: 1 }, spentTx: 'D', heightSpent: 10 } - ]; + var allOutputs = [{ + satoshis: 10, + txId: 'A', + outputIndex: 1, + heightConfirmed: 1 + }, { + satoshis: 20, + txId: 'B', + outputIndex: 1, + heightConfirmed: 5 + }, { + satoshis: 30, + txId: 'C', + outputIndex: 1, + heightConfirmed: 10 + }]; + var spendOutputs = [{ + spendInput: { + prevTxId: 'A', + outputIndex: 1 + }, + spentTx: 'D', + heightSpent: 10 + }]; service.buildAddressSummary(address, tip, allOutputs, spendOutputs).should.deep.equal({ address: address.toString(), transactions: ['A', 'B', 'C', 'D'], - confirmed: { balance: 30, sent: 0, received: 30 }, - unconfirmed: { balance: 50, sent: 10, received: 60 } + confirmed: { + balance: 30, + sent: 0, + received: 30 + }, + unconfirmed: { + balance: 50, + sent: 10, + received: 60 + } }); }); it('works with a transaction that includes twice the same address', function() { - var allOutputs = [ - { satoshis: 10, txId: 'A', outputIndex: 0, heightConfirmed: 1 }, - { satoshis: 10, txId: 'A', outputIndex: 1, heightConfirmed: 1 }, - ]; + var allOutputs = [{ + satoshis: 10, + txId: 'A', + outputIndex: 0, + heightConfirmed: 1 + }, { + satoshis: 10, + txId: 'A', + outputIndex: 1, + heightConfirmed: 1 + }, ]; var spendOutputs = []; service.buildAddressSummary(address, tip, allOutputs, spendOutputs).should.deep.equal({ address: address.toString(), transactions: ['A'], - confirmed: { balance: 20, sent: 0, received: 20 }, - unconfirmed: { balance: 20, sent: 0, received: 20 } + confirmed: { + balance: 20, + sent: 0, + received: 20 + }, + unconfirmed: { + balance: 20, + sent: 0, + received: 20 + } }); }); it('confirmed spent transactions change the balance', function() { - var allOutputs = [ - { satoshis: 10, txId: 'A', outputIndex: 0, heightConfirmed: 1 }, - ]; - var spendOutputs = [ - { spendInput: { prevTxId: 'A', outputIndex: 0 }, spentTx: 'D', heightSpent: 2 } - ]; + var allOutputs = [{ + satoshis: 10, + txId: 'A', + outputIndex: 0, + heightConfirmed: 1 + }, ]; + var spendOutputs = [{ + spendInput: { + prevTxId: 'A', + outputIndex: 0 + }, + spentTx: 'D', + heightSpent: 2 + }]; service.buildAddressSummary(address, tip, allOutputs, spendOutputs).should.deep.equal({ address: address.toString(), transactions: ['A', 'D'], - confirmed: { balance: 0, sent: 10, received: 10 }, - unconfirmed: { balance: 0, sent: 10, received: 10 } + confirmed: { + balance: 0, + sent: 10, + received: 10 + }, + unconfirmed: { + balance: 0, + sent: 10, + received: 10 + } }); }); }); }); - From fd62c62a83511789845b4715d4bcd6dca646a6ca Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 09:00:36 -0300 Subject: [PATCH 18/21] fix block regressions --- api/test/v1/blocks.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/test/v1/blocks.js b/api/test/v1/blocks.js index 574d077b..b91e49cb 100644 --- a/api/test/v1/blocks.js +++ b/api/test/v1/blocks.js @@ -120,7 +120,7 @@ describe('BitcoreHTTP v1 blocks routes', function() { it('works with valid blockHash ...' + hash.substring(hash.length - 8), function(cb) { agent.get('/v1/blocks/' + hash) .expect(200) - .expect(block.toJSON(), cb); + .expect(block.toObject(), cb); }); }); }); @@ -138,7 +138,7 @@ describe('BitcoreHTTP v1 blocks routes', function() { it('works with valid height', function(cb) { agent.get('/v1/blocks/100000') .expect(200) - .expect(b1.toJSON(), cb); + .expect(b1.toObject(), cb); }); }); From 36137c6beaee48bdaa4892b29d0ca210c075e34b Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 09:00:59 -0300 Subject: [PATCH 19/21] fix block regressions --- api/test/v1/transactions.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/test/v1/transactions.js b/api/test/v1/transactions.js index 93d8b5f0..3af02b65 100644 --- a/api/test/v1/transactions.js +++ b/api/test/v1/transactions.js @@ -60,7 +60,7 @@ describe('BitcoreHTTP v1 transactions routes', function() { it('works with valid txHash ...' + hash.substring(hash.length - 8), function(cb) { agent.get('/v1/transactions/' + hash) .expect(200) - .expect(mockTransactions[hash].toJSON(), cb); + .expect(mockTransactions[hash].toObject(), cb); }); }); }); @@ -112,7 +112,7 @@ describe('BitcoreHTTP v1 transactions routes', function() { agent.get('/v1/transactions/' + hash + '/' + name + '/') .expect(200) .expect(tx[name].map(function(x) { - return x.toJSON(); + return x.toObject(); }), cb); }); var canGetSpecificInput = function(i) { @@ -120,7 +120,7 @@ describe('BitcoreHTTP v1 transactions routes', function() { return function(cb) { agent.get('/v1/transactions/' + hash + '/' + name + '/' + i) .expect(200) - .expect(x.toJSON(), cb); + .expect(x.toObject(), cb); }; }; for (var i = 0; i < tx[name].length; i++) { From 5129fb4d8fd37645a3b3c28d60c5fc08445b4ecc Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 09:07:06 -0300 Subject: [PATCH 20/21] remove unncessary logs --- index.js | 4 ---- lib/node.js | 5 ++--- lib/services/block.js | 1 - 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index ff345e21..13f51acb 100644 --- a/index.js +++ b/index.js @@ -22,10 +22,6 @@ if (require.main === module) { console.log('Error: ', err); } }); - process.on('SIGINT', function() { - node.stop(); - process.exit(); - }); var http = new BitcoreHTTP(node, httpConfig); http.start() .catch(function(err) { diff --git a/lib/node.js b/lib/node.js index 4c6b470f..85e689fb 100644 --- a/lib/node.js +++ b/lib/node.js @@ -79,8 +79,6 @@ BitcoreNode.prototype.initialize = function() { var prevHeight = 0; var statTimer = 5 * 1000; this.interval = setInterval(function() { - console.log('MB used:', process.memoryUsage().heapTotal / 1024 / 1024, - 100 * self.getSyncProgress() + '% synced'); if (!self.blockchain) { // not ready yet console.log('No blockchain yet'); @@ -94,7 +92,8 @@ BitcoreNode.prototype.initialize = function() { } var delta = block.height - prevHeight; prevHeight = block.height; - console.log(block.id, block.height, 'vel', delta * 1000 / statTimer, 'b/s'); + console.log(block.id, block.height, 'vel', delta * 1000 / statTimer, 'b/s', + 100 * self.getSyncProgress() + '% synced'); }, statTimer); this.bus.register(bitcore.Block, function(block) { diff --git a/lib/services/block.js b/lib/services/block.js index e828f8d7..442870d7 100644 --- a/lib/services/block.js +++ b/lib/services/block.js @@ -486,7 +486,6 @@ BlockService.prototype.getBlockchain = function() { var fetchHeader = function(blockHash) { if (blockHash === BlockChain.NULL) { console.log('All headers fetched, total =', headers.length); - console.log(process.memoryUsage().heapTotal / 1024 / 1024, 'mb used'); return; } var headerKey = Index.getBlockHeader(blockHash); From fe820c8ee5d53ef2ba8affdb04639d21d126272c Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 30 Apr 2015 09:09:58 -0300 Subject: [PATCH 21/21] remove unncessary log --- test/services/address.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/services/address.js b/test/services/address.js index 41661930..30621f67 100644 --- a/test/services/address.js +++ b/test/services/address.js @@ -144,7 +144,6 @@ describe('AddressService', function() { gte: 'txas-12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S-' + '0000000000000000000000000000000000000000000000000000000000000000-0', lte: 'txas-12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S-' + 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff-4294967295' }); - console.log(arguments); arg[0].should.deep.equal('processed'); done(); });