@leofcoin/chain 1.9.3 → 1.9.4

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.
@@ -1,4 +1,4 @@
1
- import { t as toBase58, T as TransactionMessage, C as ContractMessage, R as RawTransactionMessage, B as BlockMessage, u as utils, L as LastBlockMessage, P as PROTOCOL_VERSION, a as REACHED_ONE_ZERO_ZERO, b as BWMessage, c as BWRequestMessage } from './constants-BTdMMS4w.js';
1
+ import { t as toBase58, T as TransactionMessage, C as ContractMessage, R as RawTransactionMessage, B as BlockMessage, L as LastBlockMessage, P as PROTOCOL_VERSION, a as REACHED_ONE_ZERO_ZERO, b as PrevoteMessage, c as PrecommitMessage, d as ProposalMessage, e as BWMessage, S as StateMessage, f as BWRequestMessage } from './constants-D_XqG46B.js';
2
2
  import { log } from 'console';
3
3
  import { log as log$1 } from 'node:console';
4
4
 
@@ -5055,11 +5055,6 @@ class Jobber {
5055
5055
  }
5056
5056
  }
5057
5057
 
5058
- utils.addCodec({
5059
- name: 'last-block-message',
5060
- codec: 0x6c626d,
5061
- hashAlg: 'keccak-256'
5062
- });
5063
5058
  const debug$1 = createDebugger('leofcoin/state');
5064
5059
  class State extends Contract {
5065
5060
  #resolveErrored;
@@ -6154,7 +6149,7 @@ class ConnectionMonitor {
6154
6149
  const networkName = globalThis.peernet?.network;
6155
6150
  if (networkName && typeof networkName === 'string') {
6156
6151
  // Try to import network config
6157
- const { default: networks } = await import('./constants-BTdMMS4w.js').then(function (n) { return n.n; });
6152
+ const { default: networks } = await import('./constants-D_XqG46B.js').then(function (n) { return n.n; });
6158
6153
  const [mainKey, subKey] = networkName.split(':');
6159
6154
  const networkConfig = networks?.[mainKey]?.[subKey];
6160
6155
  if (networkConfig?.stars && Array.isArray(networkConfig.stars)) {
@@ -6246,16 +6241,6 @@ class ConnectionMonitor {
6246
6241
  }
6247
6242
  }
6248
6243
 
6249
- utils.addCodec({
6250
- name: 'last-block-message',
6251
- codec: 0x6c626d,
6252
- hashAlg: 'keccak-256'
6253
- });
6254
- utils.addCodec({
6255
- name: 'last-block-request-message',
6256
- codec: 0x6c62726d,
6257
- hashAlg: 'keccak-256'
6258
- });
6259
6244
  const debug = createDebugger('leofcoin/chain');
6260
6245
  // check if browser or local
6261
6246
  class Chain extends VersionControl {
@@ -6349,7 +6334,10 @@ class Chain extends VersionControl {
6349
6334
  return;
6350
6335
  this.#castedVotes.add(voteKey);
6351
6336
  const from = peernet.selectedAccount;
6352
- const payload = new TextEncoder().encode(JSON.stringify({ blockHash, index, round, from }));
6337
+ const voteData = { blockHash, index: BigInt(index), round: BigInt(round), from };
6338
+ const Message = type === 'prevote' ? PrevoteMessage : PrecommitMessage;
6339
+ const message = new Message(voteData);
6340
+ const payload = message.encoded;
6353
6341
  try {
6354
6342
  globalThis.peernet.publish(`consensus:${type}`, payload);
6355
6343
  }
@@ -6364,16 +6352,17 @@ class Chain extends VersionControl {
6364
6352
  */
6365
6353
  this.#handleProposal = async (payload) => {
6366
6354
  try {
6367
- const msg = JSON.parse(new TextDecoder().decode(payload));
6355
+ const message = new ProposalMessage(payload);
6356
+ const msg = message.decoded;
6368
6357
  const { blockHash, index, round, from } = msg;
6369
- const validators = await this.#getConsensusValidators(index);
6370
- const expectedProposerIdx = (index + round) % validators.length;
6358
+ const validators = await this.#getConsensusValidators(Number(index));
6359
+ const expectedProposerIdx = Number((index + round) % BigInt(validators.length));
6371
6360
  if (!validators[expectedProposerIdx] || validators[expectedProposerIdx] !== from) {
6372
6361
  debug(`[consensus] Proposal from wrong proposer at height ${index} round ${round}`);
6373
6362
  return;
6374
6363
  }
6375
6364
  const localBlock = await this.lastBlock;
6376
- const localIndex = localBlock?.index !== undefined ? Number(localBlock.index) : -1;
6365
+ const localIndex = localBlock?.index !== undefined ? localBlock.index : -1n;
6377
6366
  if (index <= localIndex) {
6378
6367
  debug(`[consensus] Ignoring stale proposal at height ${index} (local: ${localIndex})`);
6379
6368
  return;
@@ -6392,13 +6381,13 @@ class Chain extends VersionControl {
6392
6381
  debug(`[consensus] Cannot fetch proposed block ${blockHash}:`, e?.message);
6393
6382
  return;
6394
6383
  }
6395
- this.#consensusRound = round;
6384
+ this.#consensusRound = Number(round);
6396
6385
  if (this.#roundTimer) {
6397
6386
  clearTimeout(this.#roundTimer);
6398
6387
  this.#roundTimer = null;
6399
6388
  }
6400
6389
  if (validators.includes(peernet.selectedAccount) && !this.#isJailed(peernet.selectedAccount)) {
6401
- await this.#castVote('prevote', blockHash, index, round);
6390
+ await this.#castVote('prevote', blockHash, Number(index), Number(round));
6402
6391
  }
6403
6392
  }
6404
6393
  catch (e) {
@@ -6411,13 +6400,14 @@ class Chain extends VersionControl {
6411
6400
  */
6412
6401
  this.#handlePrevote = async (payload) => {
6413
6402
  try {
6414
- const msg = JSON.parse(new TextDecoder().decode(payload));
6403
+ const message = new PrevoteMessage(payload);
6404
+ const msg = message.decoded;
6415
6405
  const { blockHash, index, round, from } = msg;
6416
- const validators = await this.#getConsensusValidators(index);
6406
+ const validators = await this.#getConsensusValidators(Number(index));
6417
6407
  if (!validators.includes(from))
6418
6408
  return;
6419
6409
  const localBlock = await this.lastBlock;
6420
- const localIndex = localBlock?.index !== undefined ? Number(localBlock.index) : -1;
6410
+ const localIndex = localBlock?.index !== undefined ? localBlock.index : -1n;
6421
6411
  if (index <= localIndex)
6422
6412
  return;
6423
6413
  const voteKey = `${index}:${round}:${blockHash}`;
@@ -6430,7 +6420,7 @@ class Chain extends VersionControl {
6430
6420
  if (voteCount >= threshold &&
6431
6421
  validators.includes(peernet.selectedAccount) &&
6432
6422
  !this.#isJailed(peernet.selectedAccount)) {
6433
- await this.#castVote('precommit', blockHash, index, round);
6423
+ await this.#castVote('precommit', blockHash, Number(index), Number(round));
6434
6424
  }
6435
6425
  }
6436
6426
  catch (e) {
@@ -6444,12 +6434,13 @@ class Chain extends VersionControl {
6444
6434
  */
6445
6435
  this.#handlePrecommit = async (payload) => {
6446
6436
  try {
6447
- const msg = JSON.parse(new TextDecoder().decode(payload));
6437
+ const message = new PrecommitMessage(payload);
6438
+ const msg = message.decoded;
6448
6439
  const { blockHash, index, round, from } = msg;
6449
- const validators = await this.#getConsensusValidators(index);
6440
+ const validators = await this.#getConsensusValidators(Number(index));
6450
6441
  if (!validators.includes(from))
6451
6442
  return;
6452
- if (index <= this.#committedHeight)
6443
+ if (index <= BigInt(this.#committedHeight))
6453
6444
  return;
6454
6445
  const voteKey = `${index}:${round}:${blockHash}`;
6455
6446
  if (!this.#precommits.has(voteKey))
@@ -6458,27 +6449,27 @@ class Chain extends VersionControl {
6458
6449
  const threshold = Math.ceil((2 * validators.length) / 3);
6459
6450
  const voteCount = this.#precommits.get(voteKey).size;
6460
6451
  debug(`[consensus] Precommits ${voteKey}: ${voteCount}/${validators.length} (need ${threshold})`);
6461
- if (voteCount >= threshold && index > this.#committedHeight) {
6462
- this.#committedHeight = index;
6452
+ if (voteCount >= threshold && index > BigInt(this.#committedHeight)) {
6453
+ this.#committedHeight = Number(index);
6463
6454
  this.#consensusRound = 0;
6464
6455
  // Prune vote state for committed and older heights
6465
6456
  for (const key of [...this.#prevotes.keys()]) {
6466
- if (Number(key.split(':')[0]) <= index)
6457
+ if (BigInt(key.split(':')[0]) <= index)
6467
6458
  this.#prevotes.delete(key);
6468
6459
  }
6469
6460
  for (const key of [...this.#precommits.keys()]) {
6470
- if (Number(key.split(':')[0]) <= index)
6461
+ if (BigInt(key.split(':')[0]) <= index)
6471
6462
  this.#precommits.delete(key);
6472
6463
  }
6473
6464
  for (const key of [...this.#castedVotes]) {
6474
- if (Number(key.split(':')[1]) <= index)
6465
+ if (BigInt(key.split(':')[1]) <= index)
6475
6466
  this.#castedVotes.delete(key);
6476
6467
  }
6477
6468
  // Non-proposers add the block to local state now.
6478
6469
  // Proposers already committed state in #createBlock() and their
6479
6470
  // lastBlock.index === index, so the guard below skips them.
6480
6471
  const currentBlock = await this.lastBlock;
6481
- const currentIndex = currentBlock?.index !== undefined ? Number(currentBlock.index) : -1;
6472
+ const currentIndex = currentBlock?.index !== undefined ? currentBlock.index : -1n;
6482
6473
  if (index > currentIndex) {
6483
6474
  debug(`[consensus] ✅ Committing block ${blockHash} at height ${index}`);
6484
6475
  try {
@@ -6751,7 +6742,9 @@ class Chain extends VersionControl {
6751
6742
  await globalThis.peernet.addRequestHandler('transactionPool', this.#transactionPoolHandler.bind(this));
6752
6743
  await globalThis.peernet.addRequestHandler('version', this.#versionHandler.bind(this));
6753
6744
  await globalThis.peernet.addRequestHandler('stateInfo', () => {
6754
- return new globalThis.peernet.protos['peernet-response']({ response: this.machine.states.info });
6745
+ return new globalThis.peernet.protos['peernet-response']({
6746
+ response: new StateMessage(this.machine.states.info).encoded
6747
+ });
6755
6748
  });
6756
6749
  globalThis.peernet.subscribe('add-block', this.#addBlock.bind(this));
6757
6750
  globalThis.peernet.subscribe('invalid-transaction', this.#invalidTransaction.bind(this));
@@ -6839,13 +6832,8 @@ class Chain extends VersionControl {
6839
6832
  async getPeerTransactionPool(peer) {
6840
6833
  let transactionsInPool = await this.#makeRequest(peer, 'transactionPool');
6841
6834
  if (transactionsInPool instanceof Uint8Array) {
6842
- try {
6843
- const text = new TextDecoder().decode(transactionsInPool);
6844
- transactionsInPool = JSON.parse(text);
6845
- }
6846
- catch (e) {
6847
- return [];
6848
- }
6835
+ debug('transactionPool response must be decoded array payload');
6836
+ return [];
6849
6837
  }
6850
6838
  if (!Array.isArray(transactionsInPool))
6851
6839
  return [];
@@ -6877,13 +6865,7 @@ class Chain extends VersionControl {
6877
6865
  try {
6878
6866
  let versionResponse = await this.#makeRequest(peer, 'version');
6879
6867
  if (versionResponse instanceof Uint8Array) {
6880
- const decoded = new TextDecoder().decode(versionResponse);
6881
- try {
6882
- versionResponse = JSON.parse(decoded);
6883
- }
6884
- catch {
6885
- versionResponse = decoded;
6886
- }
6868
+ versionResponse = new TextDecoder().decode(versionResponse);
6887
6869
  }
6888
6870
  if (typeof versionResponse === 'string') {
6889
6871
  peer.version = versionResponse;
@@ -6893,6 +6875,12 @@ class Chain extends VersionControl {
6893
6875
  typeof versionResponse.version === 'string') {
6894
6876
  peer.version = versionResponse.version;
6895
6877
  }
6878
+ if (!peer.version || typeof peer.version !== 'string') {
6879
+ const reason = `invalid version response from peer ${peerId}`;
6880
+ debug(reason);
6881
+ await this.#recordPeerFailure(peerId, reason);
6882
+ return;
6883
+ }
6896
6884
  }
6897
6885
  catch (error) {
6898
6886
  debug(`failed to request version from peer ${peerId}:`, error?.message ?? error);
@@ -6901,7 +6889,9 @@ class Chain extends VersionControl {
6901
6889
  }
6902
6890
  debug(`peer connected with version ${peer.version}`);
6903
6891
  if (!this.isVersionCompatible(peer.version)) {
6904
- debug(`versions don't match`);
6892
+ const mismatchReason = `incompatible peer version ${peer.version} (local: ${this.version})`;
6893
+ console.error(`[chain] ${mismatchReason}`);
6894
+ await this.#recordPeerFailure(peerId, mismatchReason);
6905
6895
  return;
6906
6896
  }
6907
6897
  let lastBlock;
@@ -6921,7 +6911,7 @@ class Chain extends VersionControl {
6921
6911
  // This prevents Byzantine nodes from claiming a fake chain length to steer our sync
6922
6912
  const localBlock = await this.lastBlock;
6923
6913
  const MAX_SYNC_AHEAD = 100_000;
6924
- if (lastBlock?.index > (localBlock?.index ?? 0) + MAX_SYNC_AHEAD) {
6914
+ if (lastBlock?.index > BigInt(localBlock?.index ?? 0) + BigInt(MAX_SYNC_AHEAD)) {
6925
6915
  const peerName = peer?.peerId || peer?.id || peer?.address || peerId || 'unknown';
6926
6916
  debug(`Peer ${peerName} claims unreasonable block height ${lastBlock.index} (local: ${localBlock?.index ?? 0})`);
6927
6917
  await this.#recordPeerFailure(peerId, `unreasonable lastBlock index: ${lastBlock.index}`);
@@ -6937,15 +6927,13 @@ class Chain extends VersionControl {
6937
6927
  try {
6938
6928
  let knownBlocksResponse = await this.#makeRequest(peer, 'knownBlocks');
6939
6929
  if (knownBlocksResponse instanceof Uint8Array) {
6940
- try {
6941
- knownBlocksResponse = JSON.parse(new TextDecoder().decode(knownBlocksResponse));
6942
- }
6943
- catch (e) {
6944
- console.log(e);
6945
- }
6930
+ const reason = `knownBlocks must be object response, got raw bytes from ${peerId}`;
6931
+ debug(reason);
6932
+ await this.#recordPeerFailure(peerId, reason);
6933
+ return;
6946
6934
  }
6947
6935
  const MAX_WANTLIST_SIZE = 1000;
6948
- if (knownBlocksResponse.blocks) {
6936
+ if (knownBlocksResponse && Array.isArray(knownBlocksResponse.blocks)) {
6949
6937
  const remaining = MAX_WANTLIST_SIZE - this.wantList.length;
6950
6938
  if (remaining > 0) {
6951
6939
  for (const hash of knownBlocksResponse.blocks.slice(0, remaining)) {
@@ -6987,12 +6975,7 @@ class Chain extends VersionControl {
6987
6975
  try {
6988
6976
  let stateInfo = await this.#makeRequest(peer, 'stateInfo');
6989
6977
  if (stateInfo instanceof Uint8Array) {
6990
- try {
6991
- stateInfo = JSON.parse(new TextDecoder().decode(stateInfo));
6992
- }
6993
- catch (e) {
6994
- console.log(e);
6995
- }
6978
+ stateInfo = new StateMessage(stateInfo).decoded;
6996
6979
  }
6997
6980
  await this.syncChain(lastBlock);
6998
6981
  this.machine.states.info = stateInfo;
@@ -7010,7 +6993,7 @@ class Chain extends VersionControl {
7010
6993
  return new globalThis.peernet.protos['peernet-response']({ response: pool });
7011
6994
  }
7012
6995
  async #versionHandler() {
7013
- return new globalThis.peernet.protos['peernet-response']({ response: { version: this.version } });
6996
+ return new globalThis.peernet.protos['peernet-response']({ response: this.version });
7014
6997
  }
7015
6998
  async #executeTransaction({ hash, from, to, method, params, nonce }) {
7016
6999
  try {
@@ -7362,12 +7345,14 @@ class Chain extends VersionControl {
7362
7345
  debug(`created block: ${hash} @${block.index}`);
7363
7346
  // Phase 2: announce proposal for consensus voting instead of direct add-block
7364
7347
  console.log(`[consensus] 📤 Proposing block #${block.index} | hash: ${hash} | round: ${this.#consensusRound}`);
7365
- const proposalPayload = new TextEncoder().encode(JSON.stringify({
7348
+ const proposalData = {
7366
7349
  blockHash: hash,
7367
- index: block.index,
7368
- round: this.#consensusRound,
7350
+ index: BigInt(block.index),
7351
+ round: BigInt(this.#consensusRound),
7369
7352
  from: peernet.selectedAccount
7370
- }));
7353
+ };
7354
+ const proposalMessage = new ProposalMessage(proposalData);
7355
+ const proposalPayload = proposalMessage.encoded;
7371
7356
  try {
7372
7357
  globalThis.peernet.publish('consensus:propose', proposalPayload);
7373
7358
  }