UNPKG

neo-blockchain-impl

Version:
1,602 lines (1,413 loc) 106 kB
import { Account, Asset, ClaimTransaction, EnrollmentTransaction, InvocationData, InvocationResultError, InvocationResultSuccess, InvocationTransaction, IssueTransaction, PublishTransaction, RegisterTransaction, SCRIPT_CONTAINER_TYPE, TRANSACTION_TYPE, Validator, common, crypto, utils } from 'neo-blockchain-core'; import { BlockSystemFee, NULL_ACTION, TRIGGER_TYPE, TransactionSpentCoins } from 'neo-blockchain-node-core'; import PriorityQueue from 'js-priority-queue'; import _ from 'lodash'; import { performance } from 'perf_hooks'; import { Observable } from 'rxjs'; function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function (obj) { return typeof obj; }; } else { _typeof = function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _next(value) { step("next", value); } function _throw(err) { step("throw", err); } _next(); }); }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _slicedToArray(arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return _sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } } var _fixBabelExtend = function (O) { var gOPD = O.getOwnPropertyDescriptor, gPO = O.getPrototypeOf || function (o) { return o.__proto__; }, sPO = O.setPrototypeOf || function (o, p) { o.__proto__ = p; return o; }, construct = _typeof(Reflect) === 'object' ? Reflect.construct : function (Parent, args, Class) { var Constructor, a = [null]; a.push.apply(a, args); Constructor = Parent.bind.apply(Parent, a); return sPO(new Constructor(), Class.prototype); }; return function fixBabelExtend(Class) { var Parent = gPO(Class); return sPO(Class, sPO(function Super() { return construct(Parent, arguments, gPO(this).constructor); }, Parent)); }; }(Object); var GenesisBlockNotRegisteredError = _fixBabelExtend( /*#__PURE__*/ function (_Error) { _inherits(GenesisBlockNotRegisteredError, _Error); function GenesisBlockNotRegisteredError() { _classCallCheck(this, GenesisBlockNotRegisteredError); return _possibleConstructorReturn(this, (GenesisBlockNotRegisteredError.__proto__ || Object.getPrototypeOf(GenesisBlockNotRegisteredError)).call(this, 'Genesis block was not registered with storage.')); } return GenesisBlockNotRegisteredError; }(Error)); var VerifyError = _fixBabelExtend( /*#__PURE__*/ function (_Error2) { _inherits(VerifyError, _Error2); function VerifyError() { _classCallCheck(this, VerifyError); return _possibleConstructorReturn(this, (VerifyError.__proto__ || Object.getPrototypeOf(VerifyError)).call(this, 'Script verification failed.')); } return VerifyError; }(Error)); var WitnessVerifyError = _fixBabelExtend( /*#__PURE__*/ function (_Error3) { _inherits(WitnessVerifyError, _Error3); function WitnessVerifyError() { _classCallCheck(this, WitnessVerifyError); return _possibleConstructorReturn(this, (WitnessVerifyError.__proto__ || Object.getPrototypeOf(WitnessVerifyError)).call(this, 'Witness verification failed.')); } return WitnessVerifyError; }(Error)); function createGet(_ref) { var tryGetTracked = _ref.tryGetTracked, readStorage = _ref.readStorage; return function () { var _ref2 = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee(key) { var trackedChange, value; return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: trackedChange = tryGetTracked(key); if (!(trackedChange != null)) { _context.next = 5; break; } if (!(trackedChange.type === 'delete')) { _context.next = 4; break; } throw new Error('Not found'); case 4: return _context.abrupt("return", trackedChange.value); case 5: _context.next = 7; return readStorage.get(key); case 7: value = _context.sent; return _context.abrupt("return", value); case 9: case "end": return _context.stop(); } } }, _callee, this); })); return function (_x) { return _ref2.apply(this, arguments); }; }(); } function createTryGet(_ref3) { var tryGetTracked = _ref3.tryGetTracked, readStorage = _ref3.readStorage; return function () { var _ref4 = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee2(key) { var trackedChange, value; return regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: trackedChange = tryGetTracked(key); if (!(trackedChange != null)) { _context2.next = 5; break; } if (!(trackedChange.type === 'delete')) { _context2.next = 4; break; } return _context2.abrupt("return", null); case 4: return _context2.abrupt("return", trackedChange.value); case 5: _context2.next = 7; return readStorage.tryGet(key); case 7: value = _context2.sent; return _context2.abrupt("return", value); case 9: case "end": return _context2.stop(); } } }, _callee2, this); })); return function (_x2) { return _ref4.apply(this, arguments); }; }(); } var BaseReadStorageCache = /*#__PURE__*/ function () { function BaseReadStorageCache(options) { _classCallCheck(this, BaseReadStorageCache); this._readStorage = options.readStorage; this._name = options.name; this._createAddChange = options.createAddChange; this._createDeleteChange = options.createDeleteChange; this._onAdd = options.onAdd; this._values = {}; this.get = createGet({ readStorage: this._readStorage, tryGetTracked: this._tryGetTracked.bind(this) }); this.tryGet = createTryGet({ readStorage: this._readStorage, tryGetTracked: this._tryGetTracked.bind(this) }); } _createClass(BaseReadStorageCache, [{ key: "getChangeSet", value: function getChangeSet() { var _this = this; var createDeleteChange = this._createDeleteChange; return utils.values(this._values).map(function (value) { if (value.type === 'delete') { if (createDeleteChange == null) { // TODO: Make better throw new Error('Invalid delete'); } return { type: 'delete', change: createDeleteChange(value.key) }; } return { type: 'add', change: _this._createAddChange(value.addValue) }; }); } // eslint-disable-next-line }, { key: "_tryGetTracked", value: function _tryGetTracked(key) { throw new Error('Not Implemented'); } }]); return BaseReadStorageCache; }(); var ReadStorageCache = /*#__PURE__*/ function (_BaseReadStorageCache) { _inherits(ReadStorageCache, _BaseReadStorageCache); function ReadStorageCache(options) { var _this2; _classCallCheck(this, ReadStorageCache); _this2 = _possibleConstructorReturn(this, (ReadStorageCache.__proto__ || Object.getPrototypeOf(ReadStorageCache)).call(this, { readStorage: options.readStorage, name: options.name, createAddChange: options.createAddChange, createDeleteChange: options.createDeleteChange, onAdd: options.onAdd })); _this2._getKeyString = options.getKeyString; return _this2; } _createClass(ReadStorageCache, [{ key: "_tryGetTracked", value: function _tryGetTracked(key) { return this._values[this._getKeyString(key)]; } }]); return ReadStorageCache; }(BaseReadStorageCache); var ReadAllStorageCache = /*#__PURE__*/ function (_ReadStorageCache) { _inherits(ReadAllStorageCache, _ReadStorageCache); function ReadAllStorageCache(options) { var _this3; _classCallCheck(this, ReadAllStorageCache); _this3 = _possibleConstructorReturn(this, (ReadAllStorageCache.__proto__ || Object.getPrototypeOf(ReadAllStorageCache)).call(this, { readStorage: { get: options.readAllStorage.get, tryGet: options.readAllStorage.tryGet }, name: options.name, getKeyString: options.getKeyString, createAddChange: options.createAddChange, createDeleteChange: options.createDeleteChange, onAdd: options.onAdd })); _this3._readAllStorage = options.readAllStorage; _this3._getKeyFromValue = options.getKeyFromValue; _this3.all = Observable.concat(Observable.defer(function () { return Observable.of.apply(Observable, _toConsumableArray(utils.values(_this3._values).map(function (value) { return value.type === 'add' ? value.value : null; }).filter(Boolean))); }), _this3._readAllStorage.all.concatMap(function (value) { var trackedChange = _this3._tryGetTracked(_this3._getKeyFromValue(value)); if (trackedChange != null && trackedChange.type === 'delete') { return Observable.of(); } return Observable.of(value); })); return _this3; } return ReadAllStorageCache; }(ReadStorageCache); var ReadGetAllStorageCache = /*#__PURE__*/ function (_ReadStorageCache2) { _inherits(ReadGetAllStorageCache, _ReadStorageCache2); function ReadGetAllStorageCache(options) { var _this4; _classCallCheck(this, ReadGetAllStorageCache); _this4 = _possibleConstructorReturn(this, (ReadGetAllStorageCache.__proto__ || Object.getPrototypeOf(ReadGetAllStorageCache)).call(this, { readStorage: { get: options.readGetAllStorage.get, tryGet: options.readGetAllStorage.tryGet }, name: options.name, getKeyString: options.getKeyString, createAddChange: options.createAddChange, createDeleteChange: options.createDeleteChange, onAdd: options.onAdd })); _this4._readGetAllStorage = options.readGetAllStorage; _this4._getKeyFromValue = options.getKeyFromValue; _this4._matchesPartialKey = options.matchesPartialKey; _this4.getAll = function (key) { var createdValues = utils.values(_this4._values).map(function (value) { return value.type === 'add' && _this4._matchesPartialKey(value.value, key) ? value.value : null; }).filter(Boolean); return Observable.concat(Observable.of.apply(Observable, _toConsumableArray(createdValues)), _this4._readGetAllStorage.getAll(key).concatMap(function (value) { var trackedChange = _this4._tryGetTracked(_this4._getKeyFromValue(value)); if (trackedChange != null && trackedChange.type === 'delete') { return Observable.of(); } return Observable.of(value); })); }; return _this4; } return ReadGetAllStorageCache; }(ReadStorageCache); function createAdd(_ref5) { var cache = _ref5.cache, getKeyFromValue = _ref5.getKeyFromValue, getKeyString = _ref5.getKeyString; return function () { var _ref6 = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee3(value, force) { var key, currentValue; return regeneratorRuntime.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: key = getKeyFromValue(value); if (force) { _context3.next = 7; break; } _context3.next = 4; return cache.tryGet(key); case 4: currentValue = _context3.sent; if (!(currentValue != null)) { _context3.next = 7; break; } throw new Error("Attempted to add an already existing object for key " + "".concat(cache._name, ":").concat(getKeyString(key), ".")); case 7: if (!(cache._onAdd != null)) { _context3.next = 10; break; } _context3.next = 10; return cache._onAdd(value); case 10: // eslint-disable-next-line cache._values[cache._getKeyString(key)] = { type: 'add', addValue: value, value: value }; case 11: case "end": return _context3.stop(); } } }, _callee3, this); })); return function (_x3, _x4) { return _ref6.apply(this, arguments); }; }(); } function createUpdate(_ref7) { var cache = _ref7.cache, updateFunc = _ref7.update, getKeyFromValue = _ref7.getKeyFromValue; return function () { var _ref8 = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee4(value, update) { var key, updatedValue; return regeneratorRuntime.wrap(function _callee4$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: key = getKeyFromValue(value); updatedValue = updateFunc(value, update); // eslint-disable-next-line cache._values[cache._getKeyString(key)] = { type: 'add', addValue: updatedValue, value: updatedValue }; return _context4.abrupt("return", updatedValue); case 4: case "end": return _context4.stop(); } } }, _callee4, this); })); return function (_x5, _x6) { return _ref8.apply(this, arguments); }; }(); } function createDelete(_ref9) { var cache = _ref9.cache; return function () { var _ref10 = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee5(key) { return regeneratorRuntime.wrap(function _callee5$(_context5) { while (1) { switch (_context5.prev = _context5.next) { case 0: // eslint-disable-next-line cache._values[cache._getKeyString(key)] = { type: 'delete', key: key }; case 1: case "end": return _context5.stop(); } } }, _callee5, this); })); return function (_x7) { return _ref10.apply(this, arguments); }; }(); } var ReadAddUpdateDeleteStorageCache = /*#__PURE__*/ function (_ReadStorageCache3) { _inherits(ReadAddUpdateDeleteStorageCache, _ReadStorageCache3); function ReadAddUpdateDeleteStorageCache(options) { var _this5; _classCallCheck(this, ReadAddUpdateDeleteStorageCache); _this5 = _possibleConstructorReturn(this, (ReadAddUpdateDeleteStorageCache.__proto__ || Object.getPrototypeOf(ReadAddUpdateDeleteStorageCache)).call(this, { readStorage: options.readStorage, name: options.name, getKeyString: options.getKeyString, createAddChange: options.createAddChange, createDeleteChange: options.createDeleteChange, onAdd: options.onAdd })); _this5.add = createAdd({ cache: _this5, getKeyFromValue: options.getKeyFromValue, getKeyString: options.getKeyString }); _this5.update = createUpdate({ cache: _this5, update: options.update, getKeyFromValue: options.getKeyFromValue }); _this5.delete = createDelete({ cache: _this5 }); return _this5; } return ReadAddUpdateDeleteStorageCache; }(ReadStorageCache); var ReadAddUpdateStorageCache = /*#__PURE__*/ function (_ReadStorageCache4) { _inherits(ReadAddUpdateStorageCache, _ReadStorageCache4); function ReadAddUpdateStorageCache(options) { var _this6; _classCallCheck(this, ReadAddUpdateStorageCache); _this6 = _possibleConstructorReturn(this, (ReadAddUpdateStorageCache.__proto__ || Object.getPrototypeOf(ReadAddUpdateStorageCache)).call(this, { readStorage: options.readStorage, name: options.name, getKeyString: options.getKeyString, createAddChange: options.createAddChange, createDeleteChange: options.createDeleteChange, onAdd: options.onAdd })); _this6.add = createAdd({ cache: _this6, getKeyFromValue: options.getKeyFromValue, getKeyString: options.getKeyString }); _this6.update = createUpdate({ cache: _this6, update: options.update, getKeyFromValue: options.getKeyFromValue }); return _this6; } return ReadAddUpdateStorageCache; }(ReadStorageCache); var ReadAddDeleteStorageCache = /*#__PURE__*/ function (_ReadStorageCache5) { _inherits(ReadAddDeleteStorageCache, _ReadStorageCache5); function ReadAddDeleteStorageCache(options) { var _this7; _classCallCheck(this, ReadAddDeleteStorageCache); _this7 = _possibleConstructorReturn(this, (ReadAddDeleteStorageCache.__proto__ || Object.getPrototypeOf(ReadAddDeleteStorageCache)).call(this, { readStorage: options.readStorage, name: options.name, getKeyString: options.getKeyString, createAddChange: options.createAddChange, createDeleteChange: options.createDeleteChange, onAdd: options.onAdd })); _this7.add = createAdd({ cache: _this7, getKeyFromValue: options.getKeyFromValue, getKeyString: options.getKeyString }); _this7.delete = createDelete({ cache: _this7 }); return _this7; } return ReadAddDeleteStorageCache; }(ReadStorageCache); var ReadAddStorageCache = /*#__PURE__*/ function (_ReadStorageCache6) { _inherits(ReadAddStorageCache, _ReadStorageCache6); function ReadAddStorageCache(options) { var _this8; _classCallCheck(this, ReadAddStorageCache); _this8 = _possibleConstructorReturn(this, (ReadAddStorageCache.__proto__ || Object.getPrototypeOf(ReadAddStorageCache)).call(this, { readStorage: options.readStorage, name: options.name, getKeyString: options.getKeyString, createAddChange: options.createAddChange, createDeleteChange: options.createDeleteChange, onAdd: options.onAdd })); _this8.add = createAdd({ cache: _this8, getKeyFromValue: options.getKeyFromValue, getKeyString: options.getKeyString }); return _this8; } return ReadAddStorageCache; }(ReadStorageCache); var ReadGetAllAddUpdateDeleteStorageCache = /*#__PURE__*/ function (_ReadGetAllStorageCac) { _inherits(ReadGetAllAddUpdateDeleteStorageCache, _ReadGetAllStorageCac); function ReadGetAllAddUpdateDeleteStorageCache(options) { var _this9; _classCallCheck(this, ReadGetAllAddUpdateDeleteStorageCache); _this9 = _possibleConstructorReturn(this, (ReadGetAllAddUpdateDeleteStorageCache.__proto__ || Object.getPrototypeOf(ReadGetAllAddUpdateDeleteStorageCache)).call(this, { readGetAllStorage: options.readGetAllStorage, name: options.name, getKeyString: options.getKeyString, createAddChange: options.createAddChange, createDeleteChange: options.createDeleteChange, onAdd: options.onAdd, getKeyFromValue: options.getKeyFromValue, matchesPartialKey: options.matchesPartialKey })); _this9.add = createAdd({ cache: _this9, getKeyFromValue: options.getKeyFromValue, getKeyString: options.getKeyString }); _this9.update = createUpdate({ cache: _this9, update: options.update, getKeyFromValue: options.getKeyFromValue }); _this9.delete = createDelete({ cache: _this9 }); return _this9; } return ReadGetAllAddUpdateDeleteStorageCache; }(ReadGetAllStorageCache); var ReadGetAllAddStorageCache = /*#__PURE__*/ function (_ReadGetAllStorageCac2) { _inherits(ReadGetAllAddStorageCache, _ReadGetAllStorageCac2); function ReadGetAllAddStorageCache(options) { var _this10; _classCallCheck(this, ReadGetAllAddStorageCache); _this10 = _possibleConstructorReturn(this, (ReadGetAllAddStorageCache.__proto__ || Object.getPrototypeOf(ReadGetAllAddStorageCache)).call(this, { readGetAllStorage: options.readGetAllStorage, name: options.name, getKeyString: options.getKeyString, createAddChange: options.createAddChange, createDeleteChange: options.createDeleteChange, onAdd: options.onAdd, getKeyFromValue: options.getKeyFromValue, matchesPartialKey: options.matchesPartialKey })); _this10.add = createAdd({ cache: _this10, getKeyFromValue: options.getKeyFromValue, getKeyString: options.getKeyString }); return _this10; } return ReadGetAllAddStorageCache; }(ReadGetAllStorageCache); var ReadAllAddUpdateDeleteStorageCache = /*#__PURE__*/ function (_ReadAllStorageCache) { _inherits(ReadAllAddUpdateDeleteStorageCache, _ReadAllStorageCache); function ReadAllAddUpdateDeleteStorageCache(options) { var _this11; _classCallCheck(this, ReadAllAddUpdateDeleteStorageCache); _this11 = _possibleConstructorReturn(this, (ReadAllAddUpdateDeleteStorageCache.__proto__ || Object.getPrototypeOf(ReadAllAddUpdateDeleteStorageCache)).call(this, { readAllStorage: options.readAllStorage, name: options.name, getKeyString: options.getKeyString, createAddChange: options.createAddChange, createDeleteChange: options.createDeleteChange, onAdd: options.onAdd, getKeyFromValue: options.getKeyFromValue })); _this11.add = createAdd({ cache: _this11, getKeyFromValue: options.getKeyFromValue, getKeyString: options.getKeyString }); _this11.update = createUpdate({ cache: _this11, update: options.update, getKeyFromValue: options.getKeyFromValue }); _this11.delete = createDelete({ cache: _this11 }); return _this11; } return ReadAllAddUpdateDeleteStorageCache; }(ReadAllStorageCache); var ReadAllAddStorageCache = /*#__PURE__*/ function (_ReadAllStorageCache2) { _inherits(ReadAllAddStorageCache, _ReadAllStorageCache2); function ReadAllAddStorageCache(options) { var _this12; _classCallCheck(this, ReadAllAddStorageCache); _this12 = _possibleConstructorReturn(this, (ReadAllAddStorageCache.__proto__ || Object.getPrototypeOf(ReadAllAddStorageCache)).call(this, { readAllStorage: options.readAllStorage, name: options.name, getKeyString: options.getKeyString, createAddChange: options.createAddChange, createDeleteChange: options.createDeleteChange, onAdd: options.onAdd, getKeyFromValue: options.getKeyFromValue })); _this12.add = createAdd({ cache: _this12, getKeyFromValue: options.getKeyFromValue, getKeyString: options.getKeyString }); return _this12; } return ReadAllAddStorageCache; }(ReadAllStorageCache); var BlockLikeStorageCache = /*#__PURE__*/ function (_BaseReadStorageCache2) { _inherits(BlockLikeStorageCache, _BaseReadStorageCache2); function BlockLikeStorageCache(options) { var _this13; _classCallCheck(this, BlockLikeStorageCache); _this13 = _possibleConstructorReturn(this, (BlockLikeStorageCache.__proto__ || Object.getPrototypeOf(BlockLikeStorageCache)).call(this, { readStorage: options.readStorage, name: options.name, createAddChange: options.createAddChange })); _this13._indexValues = {}; return _this13; } _createClass(BlockLikeStorageCache, [{ key: "add", value: function () { var _ref11 = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee6(value, force) { var currentValue, addValue; return regeneratorRuntime.wrap(function _callee6$(_context6) { while (1) { switch (_context6.prev = _context6.next) { case 0: if (force) { _context6.next = 6; break; } _context6.next = 3; return this.tryGet({ hashOrIndex: value.index }); case 3: currentValue = _context6.sent; if (!(currentValue != null)) { _context6.next = 6; break; } throw new Error('Attempted to add an already existing object.'); case 6: addValue = { type: 'add', addValue: value, value: value }; this._values[common.uInt256ToString(value.hash)] = addValue; this._indexValues["".concat(value.index)] = addValue; case 9: case "end": return _context6.stop(); } } }, _callee6, this); })); function add(_x8, _x9) { return _ref11.apply(this, arguments); } return add; }() }, { key: "_tryGetTracked", value: function _tryGetTracked(key) { if (typeof key.hashOrIndex !== 'number') { return this._values[common.uInt256ToString(key.hashOrIndex)]; } return this._indexValues["".concat(key.hashOrIndex)]; } }]); return BlockLikeStorageCache; }(BaseReadStorageCache); var getOutputValueKeyString = function getOutputValueKeyString(key) { return "".concat(common.uInt256ToHex(key.hash), ":").concat(key.index); }; var OutputStorageCache = /*#__PURE__*/ function (_ReadStorageCache7) { _inherits(OutputStorageCache, _ReadStorageCache7); function OutputStorageCache(readStorage) { var _this14; _classCallCheck(this, OutputStorageCache); _this14 = _possibleConstructorReturn(this, (OutputStorageCache.__proto__ || Object.getPrototypeOf(OutputStorageCache)).call(this, { readStorage: readStorage, name: 'output', getKeyString: getOutputValueKeyString, createAddChange: function createAddChange(value) { return { type: 'output', value: value }; } })); _this14.add = function () { var _ref12 = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee7(value, force) { var key, currentValue; return regeneratorRuntime.wrap(function _callee7$(_context7) { while (1) { switch (_context7.prev = _context7.next) { case 0: key = { hash: value.hash, index: value.index }; if (force) { _context7.next = 7; break; } _context7.next = 4; return _this14.tryGet(key); case 4: currentValue = _context7.sent; if (!(currentValue != null)) { _context7.next = 7; break; } throw new Error("Attempted to add an already existing object for key " + "".concat(_this14._name, ":").concat(_this14._getKeyString(key), ".")); case 7: // eslint-disable-next-line _this14._values[_this14._getKeyString(key)] = { type: 'add', addValue: value, value: value.output }; case 8: case "end": return _context7.stop(); } } }, _callee7, this); })); return function (_x10, _x11) { return _ref12.apply(this, arguments); }; }(); return _this14; } return OutputStorageCache; }(ReadStorageCache); var WriteBatchBlockchain = /*#__PURE__*/ function () { function WriteBatchBlockchain(options) { _classCallCheck(this, WriteBatchBlockchain); this.settings = options.settings; this._currentBlock = options.currentBlock; this._currentHeader = options.currentHeader; this._storage = options.storage; this._vm = options.vm; this._onStep = options.onStep; var output = new OutputStorageCache(this._storage.output); this._caches = { account: new ReadAllAddUpdateDeleteStorageCache({ name: 'account', readAllStorage: this._storage.account, update: function update(value, _update) { return value.update(_update); }, getKeyFromValue: function getKeyFromValue(value) { return { hash: value.hash }; }, getKeyString: function getKeyString(key) { return common.uInt160ToString(key.hash); }, createAddChange: function createAddChange(value) { return { type: 'account', value: value }; }, createDeleteChange: function createDeleteChange(key) { return { type: 'account', key: key }; } }), action: new ReadGetAllAddStorageCache({ name: 'action', readGetAllStorage: this._storage.action, getKeyFromValue: function getKeyFromValue(value) { return { blockIndex: value.blockIndex, transactionIndex: value.transactionIndex, index: value.index }; }, getKeyString: function getKeyString(key) { return "".concat(key.blockIndex, ":").concat(key.transactionIndex, ":").concat(key.index); }, // eslint-disable-next-line matchesPartialKey: function matchesPartialKey(value, key) { // TODO: Implement me throw new Error('Not implemented'); }, createAddChange: function createAddChange(value) { return { type: 'action', value: value }; } }), asset: new ReadAddUpdateStorageCache({ name: 'asset', readStorage: this._storage.asset, update: function update(value, _update2) { return value.update(_update2); }, getKeyFromValue: function getKeyFromValue(value) { return { hash: value.hash }; }, getKeyString: function getKeyString(key) { return common.uInt256ToString(key.hash); }, createAddChange: function createAddChange(value) { return { type: 'asset', value: value }; } }), block: new BlockLikeStorageCache({ name: 'block', readStorage: { get: this._storage.block.get, tryGet: this._storage.block.tryGet }, createAddChange: function createAddChange(value) { return { type: 'block', value: value }; } }), blockSystemFee: new ReadAddStorageCache({ name: 'blockSystemFee', readStorage: this._storage.blockSystemFee, getKeyFromValue: function getKeyFromValue(value) { return { hash: value.hash }; }, getKeyString: function getKeyString(key) { return common.uInt256ToString(key.hash); }, createAddChange: function createAddChange(value) { return { type: 'blockSystemFee', value: value }; } }), header: new BlockLikeStorageCache({ name: 'header', readStorage: { get: this._storage.header.get, tryGet: this._storage.header.tryGet }, createAddChange: function createAddChange(value) { return { type: 'header', value: value }; } }), transaction: new ReadAddStorageCache({ name: 'transaction', readStorage: this._storage.transaction, getKeyFromValue: function getKeyFromValue(value) { return { hash: value.hash }; }, getKeyString: function getKeyString(key) { return common.uInt256ToString(key.hash); }, createAddChange: function createAddChange(value) { return { type: 'transaction', value: value }; }, onAdd: function () { var _ref = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee(value) { return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.next = 2; return Promise.all(value.outputs.map(function (out, index) { return output.add({ hash: value.hash, index: index, output: out }); })); case 2: case "end": return _context.stop(); } } }, _callee, this); })); function onAdd(_x) { return _ref.apply(this, arguments); } return onAdd; }() }), transactionSpentCoins: new ReadAddUpdateStorageCache({ name: 'transactionSpentCoins', readStorage: this._storage.transactionSpentCoins, update: function update(value, _update3) { return value.update(_update3); }, getKeyFromValue: function getKeyFromValue(value) { return { hash: value.hash }; }, getKeyString: function getKeyString(key) { return common.uInt256ToString(key.hash); }, createAddChange: function createAddChange(value) { return { type: 'transactionSpentCoins', value: value }; } }), output: output, contract: new ReadAddDeleteStorageCache({ name: 'contract', readStorage: this._storage.contract, getKeyFromValue: function getKeyFromValue(value) { return { hash: value.hash }; }, getKeyString: function getKeyString(key) { return common.uInt160ToString(key.hash); }, createAddChange: function createAddChange(value) { return { type: 'contract', value: value }; }, createDeleteChange: function createDeleteChange(key) { return { type: 'contract', key: key }; } }), storageItem: new ReadGetAllAddUpdateDeleteStorageCache({ name: 'storageItem', readGetAllStorage: this._storage.storageItem, update: function update(value, _update4) { return value.update(_update4); }, getKeyFromValue: function getKeyFromValue(value) { return { hash: value.hash, key: value.key }; }, getKeyString: function getKeyString(key) { return "".concat(common.uInt160ToString(key.hash), ":").concat(key.key.toString('hex')); }, matchesPartialKey: function matchesPartialKey(value, key) { return key.hash == null || common.uInt160Equal(value.hash, key.hash); }, createAddChange: function createAddChange(value) { return { type: 'storageItem', value: value }; }, createDeleteChange: function createDeleteChange(key) { return { type: 'storageItem', key: key }; } }), validator: new ReadAllAddStorageCache({ name: 'validator', readAllStorage: this._storage.validator, getKeyFromValue: function getKeyFromValue(value) { return { publicKey: value.publicKey }; }, getKeyString: function getKeyString(key) { return common.ecPointToString(key.publicKey); }, createAddChange: function createAddChange(value) { return { type: 'validator', value: value }; } }), invocationData: new ReadAddStorageCache({ name: 'invocationData', readStorage: this._storage.invocationData, getKeyFromValue: function getKeyFromValue(value) { return { hash: value.hash }; }, getKeyString: function getKeyString(key) { return common.uInt256ToString(key.hash); }, createAddChange: function createAddChange(value) { return { type: 'invocationData', value: value }; } }) }; this.account = this._caches.account; this.action = this._caches.action; this.asset = this._caches.asset; this.block = this._caches.block; this.blockSystemFee = this._caches.blockSystemFee; this.header = this._caches.header; this.transaction = this._caches.transaction; this.transactionSpentCoins = this._caches.transactionSpentCoins; this.output = this._caches.output; this.contract = this._caches.contract; this.storageItem = this._caches.storageItem; this.validator = this._caches.validator; this.invocationData = this._caches.invocationData; } _createClass(WriteBatchBlockchain, [{ key: "getChangeSet", value: function getChangeSet() { return this.account.getChangeSet().concat(this.asset.getChangeSet()).concat(this.action.getChangeSet()).concat(this.block.getChangeSet()).concat(this.blockSystemFee.getChangeSet()).concat(this.header.getChangeSet()).concat(this.transaction.getChangeSet()).concat(this.output.getChangeSet()).concat(this.transactionSpentCoins.getChangeSet()).concat(this.contract.getChangeSet()).concat(this.storageItem.getChangeSet()).concat(this.validator.getChangeSet()).concat(this.invocationData.getChangeSet()); } }, { key: "persistBlock", value: function () { var _ref2 = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee2(block) { var _ref3, _ref4, systemFee, _$$1, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, _ref7, _ref6, _idx, _transaction2; return regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: _context2.next = 2; return Promise.all([block.index === 0 ? Promise.resolve(utils.ZERO) : this.blockSystemFee.get({ hash: block.previousHash }).then(function (blockSystemFee) { return blockSystemFee.systemFee; }), this.block.add(block), this.header.add(block.header)]); case 2: _ref3 = _context2.sent; _ref4 = _slicedToArray(_ref3, 2); systemFee = _ref4[0]; _$$1 = _ref4[1]; _context2.next = 8; return this.blockSystemFee.add(new BlockSystemFee({ hash: block.hash, systemFee: systemFee.add(block.getSystemFee({ getOutput: this.output.get, governingToken: this.settings.governingToken, utilityToken: this.settings.utilityToken, fees: this.settings.fees })) })); case 8: _iteratorNormalCompletion = true; _didIteratorError = false; _iteratorError = undefined; _context2.prev = 11; _iterator = block.transactions.entries()[Symbol.iterator](); case 13: if (_iteratorNormalCompletion = (_step = _iterator.next()).done) { _context2.next = 23; break; } _ref7 = _step.value; _ref6 = _slicedToArray(_ref7, 2); _idx = _ref6[0]; _transaction2 = _ref6[1]; _context2.next = 20; return this._persistTransaction(block, _transaction2, _idx); case 20: _iteratorNormalCompletion = true; _context2.next = 13; break; case 23: _context2.next = 29; break; case 25: _context2.prev = 25; _context2.t0 = _context2["catch"](11); _didIteratorError = true; _iteratorError = _context2.t0; case 29: _context2.prev = 29; _context2.prev = 30; if (!_iteratorNormalCompletion && _iterator.return != null) { _iterator.return(); } case 32: _context2.prev = 32; if (!_didIteratorError) { _context2.next = 35; break; } throw _iteratorError; case 35: return _context2.finish(32); case 36: return _context2.finish(29); case 37: case "end": return _context2.stop(); } } }, _callee2, this, [[11, 25, 29, 37], [30,, 32, 36]]); })); function persistBlock(_x2) { return _ref2.apply(this, arguments); } return persistBlock; }() }, { key: "_persistTransaction", value: function () { var _ref8 = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee5(block, transaction, transactionIndex) { var _this = this; var results, _contract, temporaryBlockchain, result, assetChangeSet, assetHash, contractsChangeSet, contractHashes; return regeneratorRuntime.wrap(function _callee5$(_context5) { while (1) { switch (_context5.prev = _context5.next) { case 0: _context5.next = 2; return Promise.all([this.transaction.add(transaction), this.transactionSpentCoins.add(new TransactionSpentCoins({ hash: transaction.hash, startHeight: block.index })), this._updateAccounts(transaction.inputs, transaction.outputs), this._updateCoins(transaction.inputs, transaction.type === TRANSACTION_TYPE.CLAIM && transaction instanceof ClaimTransaction ? transaction.claims : [], block)]); case 2: if (!(transaction.type === TRANSACTION_TYPE.REGISTER && transaction instanceof RegisterTransaction)) { _context5.next = 7; break; } _context5.next = 5; return this.asset.add(new Asset({ hash: transaction.hash, type: transaction.asset.type, name: transaction.asset.name, amount: transaction.asset.amount, precision: transaction.asset.precision, owner: transaction.asset.owner, admin: transaction.asset.admin, issuer: transaction.asset.admin, expiration: this.currentBlockIndex + 2 * 2000000, isFrozen: false })); case 5: _context5.next = 47; break; case 7: if (!(transaction.type === TRANSACTION_TYPE.ISSUE && transaction instanceof IssueTransaction)) { _context5.next = 15; break; } _context5.next = 10; return utils.entries(transaction.getTransactionResults({ getOutput: this.output.get })); case 10: results = _context5.sent; _context5.next = 13; return Promise.all(results.map(function () { var _ref10 = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee3(_ref9) { var _ref11, assetHex, value, hash, asset; return regeneratorRuntime.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: _ref11 = _slicedToArray(_ref9, 2), assetHex = _ref11[0], value = _ref11[1]; hash = common.stringToUInt256(assetHex); _context3.next = 4; return _this.asset.get({ hash: hash }); case 4: asset = _context3.sent; _context3.next = 7; return _this.asset.update(asset, { available: asset.available.add(value.neg()) }); case 7: case "end": return _context3.stop(); } } }, _callee3, this); })); return function (_x6) { return _ref10.apply(this, arguments); }; }())); case 13: _context5.next = 47; break; case 15: if (!(transaction.type === TRANSACTION_TYPE.ENROLLMENT && transaction instanceof EnrollmentTransaction)) { _context5.next = 20; break; } _context5.next = 18; return this.validator.add(new Validator({ publicKey: transaction.publicKey })); case 18: _context5.next = 47; break; case 20: if (!(transaction.type === TRANSACTION_TYPE.PUBLISH && transaction instanceof PublishTransaction)) { _context5.next = 29; break; } _context