UNPKG

deth

Version:

Ethereum node focused on Developer Experience

107 lines (106 loc) 4.52 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const ethereumjs_account_1 = __importDefault(require("ethereumjs-account")); const ts_essentials_1 = require("ts-essentials"); const ethereumjs_util_1 = require("ethereumjs-util"); const CheckpointMap_1 = require("./CheckpointMap"); const primitives_1 = require("../../primitives"); const EMPTY_BUFFER = Buffer.from(''); /** * Holds account, code, storage state in memory. * Pretends to maintain trie like structure by generating fake state roots and load them as snapshots when needed */ class DethStateManger { constructor(accountsState = new CheckpointMap_1.CheckpointMap(), codeState = new CheckpointMap_1.CheckpointMap(), storageState = new CheckpointMap_1.CheckpointMap(), savedAccountsState = new CheckpointMap_1.CheckpointMap(), savedCodeState = new CheckpointMap_1.CheckpointMap(), savedStorageState = new CheckpointMap_1.CheckpointMap(), saveIndex = 0) { this.accountsState = accountsState; this.codeState = codeState; this.storageState = storageState; this.savedAccountsState = savedAccountsState; this.savedCodeState = savedCodeState; this.savedStorageState = savedStorageState; this.saveIndex = saveIndex; } copy() { return new DethStateManger(this.accountsState.copy(), this.codeState.copy(), this.storageState.copy(), this.savedAccountsState.copy(), this.savedCodeState.copy(), this.savedStorageState.copy(), this.saveIndex); } getAccount(address) { var _a; const account = (_a = this.accountsState.get(address), (_a !== null && _a !== void 0 ? _a : new ethereumjs_account_1.default())); return new ethereumjs_account_1.default(account.serialize()); } putAccount(address, account) { this.accountsState.set(address, account); } putContractCode(address, code) { const codeHashAsBuffer = ethereumjs_util_1.keccak256(code); const codeHash = primitives_1.bufferToHash(codeHashAsBuffer); const account = this.getAccount(address); account.codeHash = codeHashAsBuffer; this.putAccount(address, account); this.codeState.set(codeHash, code); } getContractCode(address) { const account = this.getAccount(address); return this.codeState.get(primitives_1.bufferToHash(account.codeHash)) || EMPTY_BUFFER; } getContractStorage(address, key) { var _a, _b; const s = (_a = this.storageState.get(address), (_a !== null && _a !== void 0 ? _a : {})); return _b = s[key], (_b !== null && _b !== void 0 ? _b : EMPTY_BUFFER); } putContractStorage(address, key, value) { var _a; const s = (_a = this.storageState.get(address), (_a !== null && _a !== void 0 ? _a : {})); const newState = { ...s, [key]: value }; this.storageState.set(address, newState); } clearContractStorage(address) { this.storageState.set(address, {}); } checkpoint() { this.accountsState.checkpoint(); this.codeState.checkpoint(); this.storageState.checkpoint(); } commit() { this.accountsState.commit(); this.codeState.commit(); this.storageState.commit(); } revert() { this.accountsState.revert(); this.codeState.revert(); this.storageState.revert(); } getStateRoot() { const i = this.saveIndex++; const hash = primitives_1.bufferToHash(ethereumjs_util_1.keccak256(i)); this.savedAccountsState.set(hash, this.accountsState.copy()); this.savedCodeState.set(hash, this.codeState.copy()); this.savedStorageState.set(hash, this.storageState.copy()); return hash; } setStateRoot(root) { { const s = this.savedAccountsState.get(root); ts_essentials_1.assert(s, `state root ${root.toString()} doesnt exist`); this.accountsState = s; } { const s = this.savedCodeState.get(root); this.codeState = s; } { const s = this.savedStorageState.get(root); this.storageState = s; } } isAccountEmpty(address) { // @todo fix, it's simplified implementation return !!this.accountsState.get(address); } } exports.DethStateManger = DethStateManger;