@hive-p2p/server 1.0.53 → 1.0.55
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.
- package/core/arbiter.mjs +9 -6
- package/core/gossip.mjs +2 -1
- package/core/node.mjs +9 -0
- package/core/peer-store.mjs +2 -2
- package/core/unicast.mjs +2 -1
- package/package.json +1 -1
- package/services/cryptos.mjs +2 -2
package/core/arbiter.mjs
CHANGED
|
@@ -84,8 +84,8 @@ export class Arbiter {
|
|
|
84
84
|
/** Call from HiveP2P module only! @param {string} from @param {any} message @param {Uint8Array} serialized @param {number} [powCheckFactor] default: 0.01 (1%) */
|
|
85
85
|
async digestMessage(from, message, serialized, powCheckFactor = .01) {
|
|
86
86
|
const { senderId, pubkey, topic, expectedEnd } = message; // avoid powControl() on banished peers
|
|
87
|
-
this.#signatureControl(from, message, serialized);
|
|
88
|
-
if (!this.#lengthControl(topic ? 'gossip' : 'unicast', serialized, expectedEnd)) return;
|
|
87
|
+
if (!this.#signatureControl(from, message, serialized)) return;
|
|
88
|
+
if (!this.#lengthControl(from, topic ? 'gossip' : 'unicast', serialized, expectedEnd)) return;
|
|
89
89
|
|
|
90
90
|
if (topic) this.#hopsControl(from, message);
|
|
91
91
|
else this.#routeLengthControl(from, message);
|
|
@@ -93,9 +93,10 @@ export class Arbiter {
|
|
|
93
93
|
if (this.isBanished(from) || this.isBanished(senderId)) return;
|
|
94
94
|
if (this.trustBalances[senderId] > TRUST_VALUES.VALID_POW) return;
|
|
95
95
|
if (Math.random() < powCheckFactor) await this.#powControl(senderId, pubkey);
|
|
96
|
+
return true;
|
|
96
97
|
}
|
|
97
|
-
/** @param {'gossip' | 'unicast'} type */
|
|
98
|
-
#lengthControl(type, serialized, expectedEnd) {
|
|
98
|
+
/** @param {string} from @param {'gossip' | 'unicast'} type */
|
|
99
|
+
#lengthControl(from, type, serialized, expectedEnd) {
|
|
99
100
|
if (!expectedEnd || serialized.length === expectedEnd) return true;
|
|
100
101
|
this.adjustTrust(from, TRUST_VALUES.WRONG_LENGTH, `${type} message length mismatch`);
|
|
101
102
|
}
|
|
@@ -105,9 +106,11 @@ export class Arbiter {
|
|
|
105
106
|
const { pubkey, signature, signatureStart } = message;
|
|
106
107
|
const signedData = serialized.subarray(0, signatureStart);
|
|
107
108
|
const signatureValid = this.cryptoCodex.verifySignature(pubkey, signature, signedData);
|
|
108
|
-
if (signatureValid)
|
|
109
|
+
if (!signatureValid) throw new Error('Gossip signature invalid');
|
|
110
|
+
this.adjustTrust(from, TRUST_VALUES.VALID_SIGNATURE, 'Gossip signature valid');
|
|
111
|
+
return true;
|
|
109
112
|
} catch (error) {
|
|
110
|
-
if (this.verbose > 1) console.error(`%c(Arbiter: ${this.id}) Error during signature verification from ${from}
|
|
113
|
+
if (this.verbose > 1) console.error(`%c(Arbiter: ${this.id}) Error during signature verification from ${from}: ${error.stack}`, LOG_CSS.ARBITER);
|
|
111
114
|
if (this.verbose > 2) console.log(`%c(Arbiter) signatureControl() error details: ${message}`, LOG_CSS.ARBITER);
|
|
112
115
|
}
|
|
113
116
|
this.adjustTrust(from, TRUST_VALUES.WRONG_SIGNATURE, 'Gossip signature invalid');
|
package/core/gossip.mjs
CHANGED
|
@@ -131,7 +131,8 @@ export class Gossip {
|
|
|
131
131
|
|
|
132
132
|
const message = this.cryptoCodex.readGossipMessage(serialized);
|
|
133
133
|
if (!message) return this.arbiter.countPeerAction(from, 'WRONG_SERIALIZATION');
|
|
134
|
-
await this.arbiter.digestMessage(from, message, serialized);
|
|
134
|
+
const isOk = await this.arbiter.digestMessage(from, message, serialized);
|
|
135
|
+
if (!isOk) return; // invalid message or from banished peer
|
|
135
136
|
if (this.arbiter.isBanished(from)) return; // ignore messages from banished peers
|
|
136
137
|
if (this.arbiter.isBanished(message.senderId)) return; // ignore messages from banished peers
|
|
137
138
|
|
package/core/node.mjs
CHANGED
|
@@ -211,4 +211,13 @@ export class Node {
|
|
|
211
211
|
/** Triggered when a new signal answer is received from another peer.
|
|
212
212
|
* @param {function} callback can use arguments: (senderId:string, data:SignalData) */
|
|
213
213
|
onSignalAnswer(callback) { this.messager.on('signal_answer', callback); }
|
|
214
|
+
|
|
215
|
+
/** Kick a peer. @param {string} peerId @param {string} [reason] */
|
|
216
|
+
kickPeer(peerId, reason = 'kicked_by_node') { this.peerStore.kickPeer(peerId, 0, reason); }
|
|
217
|
+
|
|
218
|
+
/** Ban a peer for a certain duration (ms). @param {string} peerId @param {number} [duration] default: 60_000ms @param {string} [reason] */
|
|
219
|
+
banPeer(peerId, duration = 60_000, reason = 'banished_by_node') {
|
|
220
|
+
this.arbiter.trustBalances[peerId] = 0; // reset trust balance
|
|
221
|
+
this.arbiter.adjustTrust(peerId, -duration, reason);
|
|
222
|
+
}
|
|
214
223
|
}
|
package/core/peer-store.mjs
CHANGED
|
@@ -219,8 +219,8 @@ export class PeerStore { // Manages all peers informations and connections (WebS
|
|
|
219
219
|
this.connecting[remoteId][direction] = new PeerConnection(remoteId, instance, direction);
|
|
220
220
|
return true;
|
|
221
221
|
}
|
|
222
|
-
/** @param {string} remoteId @param {{type: 'offer' | 'answer', sdp: Record<string, string>}} signal @param {string} [offerHash] answer only @param {number} timestamp Answer reception timestamp */
|
|
223
|
-
assignSignal(remoteId, signal, offerHash, timestamp) {
|
|
222
|
+
/** @param {string} remoteId @param {{type: 'offer' | 'answer', sdp: Record<string, string>}} signal @param {string} [offerHash] answer only @param {number} [timestamp] Answer reception timestamp */
|
|
223
|
+
assignSignal(remoteId, signal, offerHash, timestamp = CLOCK.time) {
|
|
224
224
|
const peerConn = this.connecting[remoteId]?.[signal.type === 'offer' ? 'in' : 'out'];
|
|
225
225
|
try {
|
|
226
226
|
if (peerConn?.isWebSocket) throw new Error(`Cannot assign signal for ID ${remoteId}. (WebSocket)`);
|
package/core/unicast.mjs
CHANGED
|
@@ -114,7 +114,8 @@ export class UnicastMessager {
|
|
|
114
114
|
|
|
115
115
|
const message = this.cryptoCodex.readUnicastMessage(serialized);
|
|
116
116
|
if (!message) return this.arbiter.countPeerAction(from, 'WRONG_SERIALIZATION');
|
|
117
|
-
await this.arbiter.digestMessage(from, message, serialized);
|
|
117
|
+
const isOk = await this.arbiter.digestMessage(from, message, serialized);
|
|
118
|
+
if (!isOk) return; // invalid message or from banished peer
|
|
118
119
|
if (this.arbiter.isBanished(from)) return; // ignore messages from banished peers
|
|
119
120
|
if (this.arbiter.isBanished(message.senderId)) return; // ignore messages from banished peers
|
|
120
121
|
|
package/package.json
CHANGED
package/services/cryptos.mjs
CHANGED
|
@@ -3,8 +3,8 @@ const IS_BROWSER = typeof window !== 'undefined';
|
|
|
3
3
|
|
|
4
4
|
// ED25519 EXPOSURE NODEJS/BROWSER COMPATIBLE ---------------------------------
|
|
5
5
|
const [ed_, {sha512}] = await Promise.all([
|
|
6
|
-
import(IS_BROWSER ? '../libs/ed25519-custom.js' : '@noble/ed25519'),
|
|
7
|
-
import(IS_BROWSER ? '../libs/ed25519-custom.js' : '@noble/hashes/sha2.js')
|
|
6
|
+
import(IS_BROWSER ? '../libs/ed25519-custom.min.js' : '@noble/ed25519'),
|
|
7
|
+
import(IS_BROWSER ? '../libs/ed25519-custom.min.js' : '@noble/hashes/sha2.js')
|
|
8
8
|
]);
|
|
9
9
|
/** @type {import('@noble/ed25519')} */
|
|
10
10
|
const ed25519 = ed_.default || ed_;
|