@leofcoin/chain 1.7.133 → 1.7.135

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.
@@ -4754,8 +4754,11 @@ class State extends Contract {
4754
4754
  });
4755
4755
  };
4756
4756
  this.#lastBlockHandler = async () => {
4757
+ const lastBlock = await this.lastBlock;
4758
+ // Don't advertise 0x0 as a valid block to other peers
4759
+ const response = lastBlock.hash !== '0x0' ? lastBlock : undefined;
4757
4760
  return new globalThis.peernet.protos['peernet-response']({
4758
- response: await this.lastBlock
4761
+ response
4759
4762
  });
4760
4763
  };
4761
4764
  this.#knownBlocksHandler = async () => {
@@ -5080,6 +5083,11 @@ class State extends Contract {
5080
5083
  }
5081
5084
  debug$1(`Local block height: ${localIndex}, remote block height: ${remoteIndex}`);
5082
5085
  debug$1(`Local state hash: ${localStateHash}, remote block hash: ${remoteBlockHash}`);
5086
+ // Skip syncing if remote block hash is 0x0 (invalid state)
5087
+ if (remoteBlockHash === '0x0') {
5088
+ debug$1(`Remote block hash is 0x0, skipping sync`);
5089
+ return;
5090
+ }
5083
5091
  // Use state hash comparison: only resolve if remote hash differs from local state hash
5084
5092
  if (localStateHash !== remoteBlockHash) {
5085
5093
  // Remote block hash differs from our local state, need to resolve
@@ -5251,7 +5259,7 @@ class State extends Contract {
5251
5259
  promiseRequests(promises) {
5252
5260
  return new Promise(async (resolve, reject) => {
5253
5261
  const timeout = setTimeout(() => {
5254
- resolve([{ index: 0, hash: '0x0' }]);
5262
+ resolve([]);
5255
5263
  debug$1('sync timed out');
5256
5264
  }, this.requestTimeout);
5257
5265
  promises = await Promise.allSettled(promises);
@@ -5945,8 +5953,30 @@ class Chain extends VersionControl {
5945
5953
  }
5946
5954
  }
5947
5955
  async #addBlock(block) {
5956
+ // Store the original received encoded bytes for validation
5957
+ const receivedEncoded = block instanceof BlockMessage ? block.encoded : block;
5948
5958
  const blockMessage = await new BlockMessage(block);
5949
5959
  const hash = await blockMessage.hash();
5960
+ // Verify data integrity: re-encode should produce the same bytes
5961
+ const canonicalEncoded = blockMessage.encoded;
5962
+ if (receivedEncoded.length === canonicalEncoded.length) {
5963
+ let mismatch = false;
5964
+ for (let i = 0; i < receivedEncoded.length; i++) {
5965
+ if (receivedEncoded[i] !== canonicalEncoded[i]) {
5966
+ mismatch = true;
5967
+ break;
5968
+ }
5969
+ }
5970
+ if (mismatch) {
5971
+ console.warn(`[chain] ⚠️ Block data corrupted in transit: encoded bytes don't match canonical form for block #${blockMessage.decoded.index}`);
5972
+ }
5973
+ else {
5974
+ console.log(`[chain] ✅ Block data integrity verified via codec: ${hash}`);
5975
+ }
5976
+ }
5977
+ else {
5978
+ console.warn(`[chain] ⚠️ Block data size mismatch: received ${receivedEncoded.length} bytes but canonical is ${canonicalEncoded.length} bytes for block #${blockMessage.decoded.index}`);
5979
+ }
5950
5980
  const transactions = await Promise.all(blockMessage.decoded.transactions
5951
5981
  // @ts-ignore
5952
5982
  .map(async (hash) => {
@@ -6163,6 +6193,8 @@ class Chain extends VersionControl {
6163
6193
  await this.machine.addLoadedBlock({ ...blockMessage.decoded, loaded: true, hash: await blockMessage.hash() });
6164
6194
  await this.updateState(blockMessage);
6165
6195
  debug(`created block: ${hash} @${block.index}`);
6196
+ // Publish canonical encoded form via codec interface
6197
+ console.log(`[chain] 📤 Publishing block #${block.index} | hash: ${hash} | encoded bytes: ${blockMessage.encoded.length}`);
6166
6198
  globalThis.peernet.publish('add-block', blockMessage.encoded);
6167
6199
  globalThis.pubsub.publish('add-block', blockMessage.decoded);
6168
6200
  }
package/exports/chain.js CHANGED
@@ -881,8 +881,11 @@ class State extends Contract {
881
881
  });
882
882
  };
883
883
  this.#lastBlockHandler = async () => {
884
+ const lastBlock = await this.lastBlock;
885
+ // Don't advertise 0x0 as a valid block to other peers
886
+ const response = lastBlock.hash !== '0x0' ? lastBlock : undefined;
884
887
  return new globalThis.peernet.protos['peernet-response']({
885
- response: await this.lastBlock
888
+ response
886
889
  });
887
890
  };
888
891
  this.#knownBlocksHandler = async () => {
@@ -1207,6 +1210,11 @@ class State extends Contract {
1207
1210
  }
1208
1211
  debug$1(`Local block height: ${localIndex}, remote block height: ${remoteIndex}`);
1209
1212
  debug$1(`Local state hash: ${localStateHash}, remote block hash: ${remoteBlockHash}`);
1213
+ // Skip syncing if remote block hash is 0x0 (invalid state)
1214
+ if (remoteBlockHash === '0x0') {
1215
+ debug$1(`Remote block hash is 0x0, skipping sync`);
1216
+ return;
1217
+ }
1210
1218
  // Use state hash comparison: only resolve if remote hash differs from local state hash
1211
1219
  if (localStateHash !== remoteBlockHash) {
1212
1220
  // Remote block hash differs from our local state, need to resolve
@@ -1378,7 +1386,7 @@ class State extends Contract {
1378
1386
  promiseRequests(promises) {
1379
1387
  return new Promise(async (resolve, reject) => {
1380
1388
  const timeout = setTimeout(() => {
1381
- resolve([{ index: 0, hash: '0x0' }]);
1389
+ resolve([]);
1382
1390
  debug$1('sync timed out');
1383
1391
  }, this.requestTimeout);
1384
1392
  promises = await Promise.allSettled(promises);
@@ -2072,8 +2080,30 @@ class Chain extends VersionControl {
2072
2080
  }
2073
2081
  }
2074
2082
  async #addBlock(block) {
2083
+ // Store the original received encoded bytes for validation
2084
+ const receivedEncoded = block instanceof BlockMessage ? block.encoded : block;
2075
2085
  const blockMessage = await new BlockMessage(block);
2076
2086
  const hash = await blockMessage.hash();
2087
+ // Verify data integrity: re-encode should produce the same bytes
2088
+ const canonicalEncoded = blockMessage.encoded;
2089
+ if (receivedEncoded.length === canonicalEncoded.length) {
2090
+ let mismatch = false;
2091
+ for (let i = 0; i < receivedEncoded.length; i++) {
2092
+ if (receivedEncoded[i] !== canonicalEncoded[i]) {
2093
+ mismatch = true;
2094
+ break;
2095
+ }
2096
+ }
2097
+ if (mismatch) {
2098
+ console.warn(`[chain] ⚠️ Block data corrupted in transit: encoded bytes don't match canonical form for block #${blockMessage.decoded.index}`);
2099
+ }
2100
+ else {
2101
+ console.log(`[chain] ✅ Block data integrity verified via codec: ${hash}`);
2102
+ }
2103
+ }
2104
+ else {
2105
+ console.warn(`[chain] ⚠️ Block data size mismatch: received ${receivedEncoded.length} bytes but canonical is ${canonicalEncoded.length} bytes for block #${blockMessage.decoded.index}`);
2106
+ }
2077
2107
  const transactions = await Promise.all(blockMessage.decoded.transactions
2078
2108
  // @ts-ignore
2079
2109
  .map(async (hash) => {
@@ -2290,6 +2320,8 @@ class Chain extends VersionControl {
2290
2320
  await this.machine.addLoadedBlock({ ...blockMessage.decoded, loaded: true, hash: await blockMessage.hash() });
2291
2321
  await this.updateState(blockMessage);
2292
2322
  debug(`created block: ${hash} @${block.index}`);
2323
+ // Publish canonical encoded form via codec interface
2324
+ console.log(`[chain] 📤 Publishing block #${block.index} | hash: ${hash} | encoded bytes: ${blockMessage.encoded.length}`);
2293
2325
  globalThis.peernet.publish('add-block', blockMessage.encoded);
2294
2326
  globalThis.pubsub.publish('add-block', blockMessage.decoded);
2295
2327
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leofcoin/chain",
3
- "version": "1.7.133",
3
+ "version": "1.7.135",
4
4
  "description": "Official javascript implementation",
5
5
  "private": false,
6
6
  "exports": {