Source: primitives/filter.js

  1. /*!
  2. * filters.js - filter object for bcoin
  3. * Copyright (c) 2019, the bcoin developers (MIT License).
  4. * https://github.com/bcoin-org/bcoin
  5. */
  6. 'use strict';
  7. const assert = require('bsert');
  8. const bio = require('bufio');
  9. const util = require('../utils/util');
  10. const consensus = require('../protocol/consensus');
  11. const {inspectSymbol} = require('../utils');
  12. /*
  13. * Constants
  14. */
  15. const EMPTY_BUFFER = Buffer.alloc(0);
  16. /**
  17. * Filter
  18. * Represents a GCSFilter.
  19. * @alias module:primitives.Filter
  20. * @property {Hash} hash
  21. * @property {Number} index
  22. */
  23. class Filter {
  24. /**
  25. * Create an filter.
  26. * @constructor
  27. * @param {Object?} options
  28. */
  29. constructor(options) {
  30. this.header = consensus.ZERO_HASH;
  31. this.filter = EMPTY_BUFFER;
  32. if (options)
  33. this.fromOptions(options);
  34. }
  35. /**
  36. * Inject properties from options object.
  37. * @private
  38. * @param {Object} options
  39. */
  40. fromOptions(options) {
  41. assert(options, 'Filter data is required.');
  42. assert(Buffer.isBuffer(options.header));
  43. assert(Buffer.isBuffer(options.filter));
  44. this.header = options.header;
  45. this.filter = options.filter;
  46. return this;
  47. }
  48. /**
  49. * Instantate outpoint from options object.
  50. * @param {Object} options
  51. * @returns {Filter}
  52. */
  53. static fromOptions(options) {
  54. return new this().fromOptions(options);
  55. }
  56. /**
  57. * Write filter to a buffer writer.
  58. * @param {BufferWriter} bw
  59. */
  60. toWriter(bw) {
  61. bw.writeHash(this.header);
  62. bw.writeBytes(this.filter);
  63. return bw;
  64. }
  65. /**
  66. * Calculate size of filter.
  67. * @returns {Number}
  68. */
  69. getSize() {
  70. let size = 0;
  71. size += 32;
  72. size += this.filter.length;
  73. return size;
  74. }
  75. /**
  76. * Serialize filter.
  77. * @returns {Buffer}
  78. */
  79. toRaw() {
  80. const size = this.getSize();
  81. return this.toWriter(bio.write(size)).render();
  82. }
  83. /**
  84. * Inject properties from buffer reader.
  85. * @private
  86. * @param {BufferReader} br
  87. */
  88. fromReader(br) {
  89. this.header = br.readHash();
  90. this.filter = br.readBytes(br.getSize() - br.offset);
  91. return this;
  92. }
  93. /**
  94. * Inject properties from serialized data.
  95. * @private
  96. * @param {Buffer} data
  97. */
  98. fromRaw(data) {
  99. return this.fromReader(bio.read(data));
  100. }
  101. /**
  102. * Instantiate filter from a buffer reader.
  103. * @param {BufferReader} br
  104. * @returns {Filter}
  105. */
  106. static fromReader(br) {
  107. return new this().fromReader(br);
  108. }
  109. /**
  110. * Instantiate filter from serialized data.
  111. * @param {Buffer} data
  112. * @returns {Filter}
  113. */
  114. static fromRaw(data) {
  115. return new this().fromRaw(data);
  116. }
  117. /**
  118. * Inject properties from json object.
  119. * @private
  120. * @params {Object} json
  121. */
  122. fromJSON(json) {
  123. assert(json, 'Filter data is required.');
  124. assert(typeof json.filter === 'string', 'Filter must be a string.');
  125. assert(typeof json.header === 'string', 'Header must be a string.');
  126. this.filter = Buffer.from(json.filter);
  127. this.header = Buffer.from(json.header);
  128. return this;
  129. }
  130. /**
  131. * Convert the filter to an object suitable
  132. * for JSON serialization.
  133. * @returns {Object}
  134. */
  135. toJSON() {
  136. return {
  137. filter: this.filter.toString('hex'),
  138. header: util.revHex(this.header)
  139. };
  140. }
  141. /**
  142. * Instantiate filter from json object.
  143. * @param {Object} json
  144. * @returns {Filter}
  145. */
  146. static fromJSON(json) {
  147. return new this().fromJSON(json);
  148. }
  149. /**
  150. * Convert the filter to a user-friendly string.
  151. * @returns {String}
  152. */
  153. [inspectSymbol]() {
  154. return `<Filter: ${this.filter.toString('hex')}>`;
  155. }
  156. /**
  157. * Test an object to see if it is an filter.
  158. * @param {Object} obj
  159. * @returns {Boolean}
  160. */
  161. static isFilter(obj) {
  162. return obj instanceof Filter;
  163. }
  164. }
  165. /*
  166. * Expose
  167. */
  168. module.exports = Filter;