Source: primitives/memblock.js

  1. /*!
  2. * memblock.js - memblock block object for bcoin
  3. * Copyright (c) 2014-2015, Fedor Indutny (MIT License)
  4. * Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
  5. * https://github.com/bcoin-org/bcoin
  6. */
  7. 'use strict';
  8. const bio = require('bufio');
  9. const AbstractBlock = require('./abstractblock');
  10. const Block = require('./block');
  11. const Headers = require('./headers');
  12. const Script = require('../script/script');
  13. const DUMMY = Buffer.alloc(0);
  14. /**
  15. * Mem Block
  16. * A block object which is essentially a "placeholder"
  17. * for a full {@link Block} object. The v8 garbage
  18. * collector's head will explode if there is too much
  19. * data on the javascript heap. Blocks can currently
  20. * be up to 1mb in size. In the future, they may be
  21. * 2mb, 8mb, or maybe 20mb, who knows? A MemBlock
  22. * is an optimization in Bcoin which defers parsing of
  23. * the serialized transactions (the block Buffer) until
  24. * the block has passed through the chain queue and
  25. * is about to enter the chain. This keeps a lot data
  26. * off of the javascript heap for most of the time a
  27. * block even exists in memory, and manages to keep a
  28. * lot of strain off of the garbage collector. Having
  29. * 500mb of blocks on the js heap would not be a good
  30. * thing.
  31. * @alias module:primitives.MemBlock
  32. * @extends AbstractBlock
  33. */
  34. class MemBlock extends AbstractBlock {
  35. /**
  36. * Create a mem block.
  37. * @constructor
  38. */
  39. constructor() {
  40. super();
  41. this._raw = DUMMY;
  42. }
  43. /**
  44. * Test whether the block is a memblock.
  45. * @returns {Boolean}
  46. */
  47. isMemory() {
  48. return true;
  49. }
  50. /**
  51. * Serialize the block headers.
  52. * @returns {Buffer}
  53. */
  54. toHead() {
  55. return this._raw.slice(0, 80);
  56. }
  57. /**
  58. * Get the full block size.
  59. * @returns {Number}
  60. */
  61. getSize() {
  62. return this._raw.length;
  63. }
  64. /**
  65. * Verify the block.
  66. * @returns {Boolean}
  67. */
  68. verifyBody() {
  69. return true;
  70. }
  71. /**
  72. * Retrieve the coinbase height
  73. * from the coinbase input script.
  74. * @returns {Number} height (-1 if not present).
  75. */
  76. getCoinbaseHeight() {
  77. if (this.version < 2)
  78. return -1;
  79. try {
  80. return this.parseCoinbaseHeight();
  81. } catch (e) {
  82. return -1;
  83. }
  84. }
  85. /**
  86. * Parse the coinbase height
  87. * from the coinbase input script.
  88. * @private
  89. * @returns {Number} height (-1 if not present).
  90. */
  91. parseCoinbaseHeight() {
  92. const br = bio.read(this._raw, true);
  93. br.seek(80);
  94. const txCount = br.readVarint();
  95. if (txCount === 0)
  96. return -1;
  97. br.seek(4);
  98. let inCount = br.readVarint();
  99. if (inCount === 0) {
  100. if (br.readU8() !== 0)
  101. inCount = br.readVarint();
  102. }
  103. if (inCount === 0)
  104. return -1;
  105. br.seek(36);
  106. const script = br.readVarBytes();
  107. return Script.getCoinbaseHeight(script);
  108. }
  109. /**
  110. * Inject properties from serialized data.
  111. * @private
  112. * @param {Buffer} data
  113. */
  114. fromRaw(data) {
  115. const br = bio.read(data, true);
  116. this.readHead(br);
  117. this._raw = br.data;
  118. return this;
  119. }
  120. /**
  121. * Insantiate a memblock from serialized data.
  122. * @param {Buffer} data
  123. * @returns {MemBlock}
  124. */
  125. static fromRaw(data) {
  126. return new this().fromRaw(data);
  127. }
  128. /**
  129. * Return serialized block data.
  130. * @returns {Buffer}
  131. */
  132. toRaw() {
  133. return this._raw;
  134. }
  135. /**
  136. * Return serialized block data.
  137. * @returns {Buffer}
  138. */
  139. toNormal() {
  140. return this._raw;
  141. }
  142. /**
  143. * Parse the serialized block data
  144. * and create an actual {@link Block}.
  145. * @returns {Block}
  146. * @throws Parse error
  147. */
  148. toBlock() {
  149. const block = Block.fromRaw(this._raw);
  150. block._hash = this._hash;
  151. block._hhash = this._hhash;
  152. return block;
  153. }
  154. /**
  155. * Convert the block to a headers object.
  156. * @returns {Headers}
  157. */
  158. toHeaders() {
  159. return Headers.fromBlock(this);
  160. }
  161. /**
  162. * Test whether an object is a MemBlock.
  163. * @param {Object} obj
  164. * @returns {Boolean}
  165. */
  166. static isMemBlock(obj) {
  167. return obj instanceof MemBlock;
  168. }
  169. }
  170. /*
  171. * Expose
  172. */
  173. module.exports = MemBlock;