@leofcoin/chain 1.5.57 → 1.5.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -94,9 +94,7 @@ function getCursorAdvanceMethods() {
94
94
  IDBCursor.prototype.continuePrimaryKey,
95
95
  ]));
96
96
  }
97
- const cursorRequestMap = new WeakMap();
98
97
  const transactionDoneMap = new WeakMap();
99
- const transactionStoreNamesMap = new WeakMap();
100
98
  const transformCache = new WeakMap();
101
99
  const reverseTransformCache = new WeakMap();
102
100
  function promisifyRequest(request) {
@@ -116,16 +114,6 @@ function promisifyRequest(request) {
116
114
  request.addEventListener('success', success);
117
115
  request.addEventListener('error', error);
118
116
  });
119
- promise
120
- .then((value) => {
121
- // Since cursoring reuses the IDBRequest (*sigh*), we cache it for later retrieval
122
- // (see wrapFunction).
123
- if (value instanceof IDBCursor) {
124
- cursorRequestMap.set(value, request);
125
- }
126
- // Catching to avoid "Uncaught Promise exceptions"
127
- })
128
- .catch(() => { });
129
117
  // This mapping exists in reverseTransformCache but doesn't doesn't exist in transformCache. This
130
118
  // is because we create many promises from a single IDBRequest.
131
119
  reverseTransformCache.set(promise, request);
@@ -162,10 +150,6 @@ let idbProxyTraps = {
162
150
  // Special handling for transaction.done.
163
151
  if (prop === 'done')
164
152
  return transactionDoneMap.get(target);
165
- // Polyfill for objectStoreNames because of Edge.
166
- if (prop === 'objectStoreNames') {
167
- return target.objectStoreNames || transactionStoreNamesMap.get(target);
168
- }
169
153
  // Make tx.store return the only store in the transaction, or undefined if there are many.
170
154
  if (prop === 'store') {
171
155
  return receiver.objectStoreNames[1]
@@ -194,15 +178,6 @@ function replaceTraps(callback) {
194
178
  function wrapFunction(func) {
195
179
  // Due to expected object equality (which is enforced by the caching in `wrap`), we
196
180
  // only create one new func per func.
197
- // Edge doesn't support objectStoreNames (booo), so we polyfill it here.
198
- if (func === IDBDatabase.prototype.transaction &&
199
- !('objectStoreNames' in IDBTransaction.prototype)) {
200
- return function (storeNames, ...args) {
201
- const tx = func.call(unwrap(this), storeNames, ...args);
202
- transactionStoreNamesMap.set(tx, storeNames.sort ? storeNames.sort() : [storeNames]);
203
- return wrap(tx);
204
- };
205
- }
206
181
  // Cursor methods are special, as the behaviour is a little more different to standard IDB. In
207
182
  // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the
208
183
  // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense
@@ -213,7 +188,7 @@ function wrapFunction(func) {
213
188
  // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
214
189
  // the original object.
215
190
  func.apply(unwrap(this), args);
216
- return wrap(cursorRequestMap.get(this));
191
+ return wrap(this.request);
217
192
  };
218
193
  }
219
194
  return function (...args) {
@@ -3860,12 +3860,9 @@ const isExecutionError = (error) => error.name === 'ExecutionError';
3860
3860
 
3861
3861
  // import State from './state'
3862
3862
  class Machine {
3863
- #contracts;
3864
- #nonces;
3863
+ #contracts = {};
3864
+ #nonces = {};
3865
3865
  constructor(blocks) {
3866
- this.#contracts = {};
3867
- this.#nonces = {};
3868
- this.lastBlock = { index: 0, hash: '0x0', previousHash: '0x0' };
3869
3866
  // @ts-ignore
3870
3867
  return this.#init(blocks);
3871
3868
  }
@@ -3909,7 +3906,6 @@ class Machine {
3909
3906
  break;
3910
3907
  }
3911
3908
  case 'machine-ready': {
3912
- this.lastBlock = data.lastBlock;
3913
3909
  pubsub.publish('machine.ready', true);
3914
3910
  break;
3915
3911
  }
@@ -4095,21 +4091,44 @@ class Machine {
4095
4091
  });
4096
4092
  });
4097
4093
  }
4098
- async nativeCalls() {
4094
+ get nativeCalls() {
4099
4095
  return this.#askWorker('nativeCalls');
4100
4096
  }
4101
- async nativeMints() {
4097
+ get nativeMints() {
4102
4098
  return this.#askWorker('nativeMints');
4103
4099
  }
4104
- async nativeBurns() {
4100
+ get nativeBurns() {
4105
4101
  return this.#askWorker('nativeBurns');
4106
4102
  }
4107
- async nativeTransfers() {
4103
+ get nativeTransfers() {
4108
4104
  return this.#askWorker('nativeTransfers');
4109
4105
  }
4110
- async totalTransactions() {
4106
+ get totalTransactions() {
4111
4107
  return this.#askWorker('totalTransactions');
4112
4108
  }
4109
+ get blocks() {
4110
+ return this.getBlocks();
4111
+ }
4112
+ get lastBlock() {
4113
+ return this.#askWorker('lastBlock');
4114
+ }
4115
+ get totalBlocks() {
4116
+ return this.#askWorker('totalBlocks');
4117
+ }
4118
+ getBlocks(from, to) {
4119
+ return this.#askWorker('blocks', { from, to });
4120
+ }
4121
+ getBlock(index) {
4122
+ return this.#askWorker('block', index);
4123
+ }
4124
+ async addLoadedBlock(block) {
4125
+ if (block.decoded)
4126
+ block = { ...block.decoded, hahs: await block.hash() };
4127
+ return this.#askWorker('addLoadedBlock', block);
4128
+ }
4129
+ async latestTransactions() {
4130
+ return this.#askWorker('latestTransactions');
4131
+ }
4113
4132
  async delete(hash) {
4114
4133
  return globalThis.contractStore.delete(hash);
4115
4134
  }
@@ -4166,7 +4185,6 @@ class State extends Contract {
4166
4185
  #syncErrorCount;
4167
4186
  #blockHashMap;
4168
4187
  #chainSyncing;
4169
- #lastBlock;
4170
4188
  #blocks;
4171
4189
  #totalSize;
4172
4190
  #machine;
@@ -4187,25 +4205,31 @@ class State extends Contract {
4187
4205
  return this.#resolving;
4188
4206
  }
4189
4207
  get nativeMints() {
4190
- return this.#machine.nativeMints();
4208
+ return this.#machine.nativeMints;
4191
4209
  }
4192
4210
  get nativeBurns() {
4193
- return this.#machine.nativeBurns();
4211
+ return this.#machine.nativeBurns;
4194
4212
  }
4195
4213
  get nativeTransfers() {
4196
- return this.#machine.nativeTransfers();
4214
+ return this.#machine.nativeTransfers;
4197
4215
  }
4198
4216
  get totalTransactions() {
4199
- return this.#machine.totalTransactions();
4217
+ return this.#machine.totalTransactions;
4200
4218
  }
4201
4219
  get nativeCalls() {
4202
- return this.#machine.nativeCalls();
4220
+ return this.#machine.nativeCalls;
4203
4221
  }
4204
4222
  get blocks() {
4205
- return [...this.#blocks];
4223
+ return this.getBlocks();
4206
4224
  }
4207
4225
  get lastBlock() {
4208
- return this.#lastBlock;
4226
+ return this.#machine ? this.#machine.lastBlock : { index: 0, hash: '0x0', previousHash: '0x0' };
4227
+ }
4228
+ getBlock(index) {
4229
+ return this.#machine.getBlock(index);
4230
+ }
4231
+ getBlocks(from, to) {
4232
+ return this.#machine.getBlocks(from, to);
4209
4233
  }
4210
4234
  get totalSize() {
4211
4235
  return this.#totalSize;
@@ -4222,7 +4246,6 @@ class State extends Contract {
4222
4246
  this.#syncErrorCount = 0;
4223
4247
  this.#blockHashMap = new Map();
4224
4248
  this.#chainSyncing = false;
4225
- this.#lastBlock = { index: 0, hash: '0x0', previousHash: '0x0' };
4226
4249
  this.#blocks = [];
4227
4250
  this.knownBlocks = [];
4228
4251
  this.#totalSize = 0;
@@ -4234,7 +4257,7 @@ class State extends Contract {
4234
4257
  };
4235
4258
  this.#lastBlockHandler = async () => {
4236
4259
  return new globalThis.peernet.protos['peernet-response']({
4237
- response: { hash: this.#lastBlock?.hash, index: this.#lastBlock?.index }
4260
+ response: await this.lastBlock
4238
4261
  });
4239
4262
  };
4240
4263
  this.#knownBlocksHandler = async () => {
@@ -4244,7 +4267,7 @@ class State extends Contract {
4244
4267
  };
4245
4268
  this.#loadBlockTransactions = (transactions) => Promise.all(transactions.map((transaction) => new TransactionMessage(transaction)));
4246
4269
  this.#getLastTransactions = async () => {
4247
- let lastTransactions = (await Promise.all(this.#blocks
4270
+ let lastTransactions = (await Promise.all((await this.blocks)
4248
4271
  .filter((block) => block.loaded)
4249
4272
  .slice(-128)
4250
4273
  .map((block) => this.#loadBlockTransactions(block.transactions)))).reduce((all, transactions) => [...all, ...transactions], []);
@@ -4274,35 +4297,12 @@ class State extends Contract {
4274
4297
  await globalThis.peernet.addRequestHandler('knownBlocks', this.#knownBlocksHandler);
4275
4298
  await globalThis.peernet.addRequestHandler('chainState', this.#chainStateHandler);
4276
4299
  try {
4277
- let localBlock;
4278
- try {
4279
- localBlock = await globalThis.chainStore.get('lastBlock');
4280
- }
4281
- catch {
4282
- await globalThis.chainStore.put('lastBlock', '0x0');
4283
- localBlock = await globalThis.chainStore.get('lastBlock');
4284
- }
4285
- localBlock = new TextDecoder().decode(localBlock);
4286
- if (localBlock && localBlock !== '0x0') {
4287
- localBlock = await globalThis.peernet.get(localBlock, 'block');
4288
- localBlock = await new BlockMessage(localBlock);
4289
- this.#lastBlock = {
4290
- ...localBlock.decoded,
4291
- hash: await localBlock.hash()
4292
- };
4293
- }
4294
- else {
4295
- if (globalThis.peernet?.connections.length > 0) {
4296
- const latestBlock = await this.#getLatestBlock();
4297
- await this.#syncChain(latestBlock);
4298
- }
4299
- }
4300
+ await globalThis.chainStore.has('lastBlock');
4300
4301
  }
4301
- catch (error) {
4302
- console.log({ e: error });
4303
- console.log({ e: error });
4302
+ catch {
4303
+ await globalThis.chainStore.put('lastBlock', '0x0');
4304
4304
  }
4305
- globalThis.pubsub.publish('lastBlock', this.lastBlock);
4305
+ globalThis.pubsub.publish('lastBlock', await this.lastBlock);
4306
4306
  // load local blocks
4307
4307
  try {
4308
4308
  this.knownBlocks = await blockStore.keys();
@@ -4314,6 +4314,9 @@ class State extends Contract {
4314
4314
  try {
4315
4315
  await this.resolveBlocks();
4316
4316
  this.#machine = await new Machine(this.#blocks);
4317
+ const lastBlock = await this.#machine.lastBlock;
4318
+ this.updateState(new BlockMessage(lastBlock));
4319
+ this.#loaded = true;
4317
4320
  // await this.#loadBlocks(this.#blocks)
4318
4321
  }
4319
4322
  catch (error) {
@@ -4325,10 +4328,9 @@ class State extends Contract {
4325
4328
  }
4326
4329
  async updateState(message) {
4327
4330
  const hash = await message.hash();
4328
- this.#lastBlock = { hash, ...message.decoded };
4329
4331
  // await this.state.updateState(message)
4330
4332
  await globalThis.chainStore.put('lastBlock', hash);
4331
- globalThis.pubsub.publish('lastBlock', this.#lastBlock);
4333
+ globalThis.pubsub.publish('lastBlock', message.encoded);
4332
4334
  }
4333
4335
  getLatestBlock() {
4334
4336
  // @ts-ignore
@@ -4414,7 +4416,6 @@ class State extends Contract {
4414
4416
  const hash = new TextDecoder().decode(localBlock);
4415
4417
  if (hash && hash !== '0x0') {
4416
4418
  await this.resolveBlock(hash);
4417
- this.#lastBlock = this.#blocks[this.#blocks.length - 1];
4418
4419
  }
4419
4420
  }
4420
4421
  catch (error) {
@@ -4432,7 +4433,6 @@ class State extends Contract {
4432
4433
  await globalThis.chainStore.put('lastBlock', hash);
4433
4434
  if (hash && hash !== '0x0') {
4434
4435
  await this.resolveBlock(hash);
4435
- this.#lastBlock = this.#blocks[this.#blocks.length - 1];
4436
4436
  }
4437
4437
  }
4438
4438
  catch (error) {
@@ -4462,7 +4462,7 @@ class State extends Contract {
4462
4462
  if (!lastBlock)
4463
4463
  lastBlock = await this.#getLatestBlock();
4464
4464
  console.log('starting sync');
4465
- if (globalThis.peernet.connections.length === 0)
4465
+ if (globalThis.peernet.peers.length === 0)
4466
4466
  return 'connectionless';
4467
4467
  try {
4468
4468
  await this.#syncChain(lastBlock);
@@ -4496,18 +4496,21 @@ class State extends Contract {
4496
4496
  promises = promises.filter(({ status, value }) => status === 'fulfilled' && !value.has);
4497
4497
  await Promise.allSettled(promises.map(({ value }) => this.getAndPutBlock(value.address)));
4498
4498
  }
4499
- if (!this.#lastBlock || Number(this.#lastBlock.index) < Number(lastBlock.index)) {
4499
+ const localBlock = await this.lastBlock;
4500
+ if (!localBlock || Number(localBlock.index) < Number(lastBlock.index)) {
4500
4501
  // TODO: check if valid
4501
- const localIndex = this.#lastBlock ? this.lastBlock.index : 0;
4502
+ const localIndex = localBlock ? localBlock.index : 0;
4502
4503
  const index = lastBlock.index;
4503
4504
  await this.resolveBlock(lastBlock.hash);
4504
4505
  console.log('ok');
4505
4506
  let blocksSynced = localIndex > 0 ? (localIndex > index ? localIndex - index : index + -localIndex) : index;
4506
4507
  globalThis.debug(`synced ${blocksSynced} ${blocksSynced > 1 ? 'blocks' : 'block'}`);
4507
- const start = this.#blocks.length - blocksSynced;
4508
- if (this.#machine)
4509
- await this.#loadBlocks(this.blocks.slice(start));
4510
- await this.updateState(new BlockMessage(this.#blocks[this.#blocks.length - 1]));
4508
+ const blocks = this.#blocks;
4509
+ const start = blocks.length - blocksSynced;
4510
+ if (this.#machine) {
4511
+ await this.#loadBlocks(blocks.slice(start));
4512
+ }
4513
+ await this.updateState(new BlockMessage(blocks[blocks.length - 1]));
4511
4514
  }
4512
4515
  }
4513
4516
  catch (error) {
@@ -4521,8 +4524,6 @@ class State extends Contract {
4521
4524
  request: 'lastBlock'
4522
4525
  });
4523
4526
  let node = await globalThis.peernet.prepareMessage(data);
4524
- console.log(node.encoded);
4525
- console.log(node.encode());
4526
4527
  for (const id in globalThis.peernet.connections) {
4527
4528
  // @ts-ignore
4528
4529
  const peer = globalThis.peernet.connections[id];
@@ -4585,11 +4586,12 @@ class State extends Contract {
4585
4586
  await globalThis.transactionPoolStore.delete(await transaction.hash());
4586
4587
  console.log('removing invalid transaction');
4587
4588
  if (isExecutionError(error)) {
4588
- console.log(`removing invalid block ${block.index}`);
4589
- await globalThis.blockStore.delete(await (await new BlockMessage(block)).hash());
4590
- const deletedBlock = blocks.splice(block.index, 1);
4591
- console.log(`removed block ${deletedBlock[0].index}`);
4592
- return this.#loadBlocks(blocks);
4589
+ console.log(error);
4590
+ // console.log(`removing invalid block ${block.index}`)
4591
+ // await globalThis.blockStore.delete(await (await new BlockMessage(block)).hash())
4592
+ // const deletedBlock = blocks.splice(block.index, 1)
4593
+ // console.log(`removed block ${deletedBlock[0].index}`)
4594
+ // return this.#loadBlocks(blocks)
4593
4595
  }
4594
4596
  console.log(error);
4595
4597
  return false;
@@ -4632,6 +4634,7 @@ class State extends Contract {
4632
4634
  transactions = transactions.filter((transaction) => !transaction.decoded.priority);
4633
4635
  await Promise.all(transactions.map((transaction) => this.#_executeTransaction(transaction)));
4634
4636
  this.#blocks[block.index - 1].loaded = true;
4637
+ await this.#machine.addLoadedBlock(block);
4635
4638
  // @ts-ignore
4636
4639
  globalThis.debug(`loaded block: ${block.hash} @${block.index}`);
4637
4640
  globalThis.pubsub.publish('block-loaded', { ...block });
@@ -4891,7 +4894,8 @@ class Chain extends VersionControl {
4891
4894
  if (!peer.version || peer.version !== this.version)
4892
4895
  return;
4893
4896
  const lastBlock = await this.#makeRequest(peer, 'lastBlock');
4894
- const higherThenCurrentLocal = !this.lastBlock?.index ? true : lastBlock.index > this.lastBlock?.index;
4897
+ const localBlock = await this.lastBlock;
4898
+ const higherThenCurrentLocal = !localBlock.index ? true : lastBlock.index > localBlock.index;
4895
4899
  const peerTransactionPool = (higherThenCurrentLocal && (await this.getPeerTransactionPool(peer))) || [];
4896
4900
  if (Object.keys(lastBlock).length > 0) {
4897
4901
  if (!this.lastBlock || higherThenCurrentLocal) {
@@ -4934,26 +4938,27 @@ class Chain extends VersionControl {
4934
4938
  // @ts-ignore
4935
4939
  .map(async (transaction) => {
4936
4940
  let hash = transaction.hash;
4937
- if (!hash)
4938
- await new TransactionMessage(transaction).hash();
4941
+ if (!hash) {
4942
+ hash = await new TransactionMessage(transaction).hash();
4943
+ transaction.hash = hash;
4944
+ }
4939
4945
  (await transactionPoolStore.has(hash)) && (await transactionPoolStore.delete(hash));
4946
+ return transaction;
4940
4947
  }));
4941
4948
  const hash = await blockMessage.hash();
4942
4949
  await globalThis.blockStore.put(hash, blockMessage.encoded);
4943
- if (this.lastBlock.index < Number(blockMessage.decoded.index))
4950
+ if ((await this.lastBlock).index < Number(blockMessage.decoded.index))
4944
4951
  await this.updateState(blockMessage);
4945
4952
  globalThis.debug(`added block: ${hash}`);
4946
4953
  let promises = [];
4947
4954
  let contracts = [];
4948
4955
  for (let transaction of blockMessage.decoded.transactions) {
4949
4956
  // await transactionStore.put(transaction.hash, transaction.encoded)
4950
- // @ts-ignore
4951
- const index = contracts.indexOf(transaction.to);
4952
- // @ts-ignore
4953
- if (index === -1)
4957
+ if (!contracts.includes(transaction.to)) {
4954
4958
  contracts.push(transaction.to);
4959
+ }
4955
4960
  // Todo: go trough all accounts
4956
- // @ts-ignore
4961
+ //@ts-ignore
4957
4962
  promises.push(this.#executeTransaction(transaction));
4958
4963
  }
4959
4964
  try {
@@ -4970,6 +4975,7 @@ class Chain extends VersionControl {
4970
4975
  // // await stateStore.put(contract, state)
4971
4976
  // console.log(state);
4972
4977
  // }
4978
+ // await this.machine.addLoadedBlock({ ...blockMessage.decoded, loaded: true, hash: await blockMessage.hash() })
4973
4979
  globalThis.pubsub.publish('block-processed', blockMessage.decoded);
4974
4980
  }
4975
4981
  catch (error) {
@@ -5026,15 +5032,12 @@ class Chain extends VersionControl {
5026
5032
  // exclude failing tx
5027
5033
  transactions = await this.promiseTransactions(transactions);
5028
5034
  transactions = transactions.sort((a, b) => a.nonce - b.nonce);
5035
+ const latestTransactions = await this.machine.latestTransactions();
5029
5036
  for (let transaction of transactions) {
5030
5037
  const hash = await transaction.hash();
5031
5038
  const doubleTransactions = [];
5032
- for (const block of this.blocks) {
5033
- for (const transaction of block.transactions) {
5034
- if (transaction.hash === hash) {
5035
- doubleTransactions.push(hash);
5036
- }
5037
- }
5039
+ if (latestTransactions.includes(hash)) {
5040
+ doubleTransactions.push(hash);
5038
5041
  }
5039
5042
  if (doubleTransactions.length > 0) {
5040
5043
  await globalThis.transactionPoolStore.delete(hash);
@@ -5105,12 +5108,13 @@ class Chain extends VersionControl {
5105
5108
  return validator;
5106
5109
  });
5107
5110
  // block.validators = calculateValidatorReward(block.validators, block.fees)
5108
- block.index = this.lastBlock?.index;
5111
+ const localBlock = await this.lastBlock;
5112
+ block.index = localBlock.index;
5109
5113
  if (block.index === undefined)
5110
5114
  block.index = 0;
5111
5115
  else
5112
5116
  block.index += 1;
5113
- block.previousHash = this.lastBlock?.hash || '0x0';
5117
+ block.previousHash = localBlock.hash || '0x0';
5114
5118
  // block.timestamp = Date.now()
5115
5119
  // block.reward = block.reward.toString()
5116
5120
  // block.fees = block.fees.toString()
@@ -5123,7 +5127,8 @@ class Chain extends VersionControl {
5123
5127
  const hash = await blockMessage.hash();
5124
5128
  await globalThis.peernet.put(hash, blockMessage.encoded, 'block');
5125
5129
  await this.updateState(blockMessage);
5126
- globalThis.debug(`created block: ${hash}`);
5130
+ await this.machine.addLoadedBlock({ ...blockMessage.decoded, loaded: true, hash: await blockMessage.hash() });
5131
+ globalThis.debug(`created block: ${hash} @${block.index}`);
5127
5132
  globalThis.peernet.publish('add-block', blockMessage.encoded);
5128
5133
  globalThis.pubsub.publish('add-block', blockMessage.decoded);
5129
5134
  }
@@ -21,7 +21,7 @@ const run = async (blocks) => {
21
21
  console.log(`loaded block: ${hash} @${index} ${formatBytes(size)}`);
22
22
  // todo we don't want this, need shared state
23
23
  block.decoded.transactions = block.decoded.transactions.sort((a, b) => a.nonce - b.nonce);
24
- resolve({ ...block.decoded, blockInfo: { hash, size, index } });
24
+ resolve({ ...block.decoded, hash, blockInfo: { hash, size, index } });
25
25
  })
26
26
  )
27
27
  );