Compare commits
No commits in common. "v0.1.0-develop.4" and "v0.1.0-develop.3" have entirely different histories.
v0.1.0-dev
...
v0.1.0-dev
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -1,16 +1,3 @@
|
||||||
# [0.1.0-develop.4](https://git.lumeweb.com/LumeWeb/libs5/compare/v0.1.0-develop.3...v0.1.0-develop.4) (2023-08-31)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* add getter for networkId and hashQueryRoutingTable ([6ebc477](https://git.lumeweb.com/LumeWeb/libs5/commit/6ebc477449ca8893a2e5e37310575e0c5e7dc444))
|
|
||||||
* ed25519.sign arguments are wrong order ([5585907](https://git.lumeweb.com/LumeWeb/libs5/commit/5585907591c0275de5a229db99584c6ea3eb12d2))
|
|
||||||
* fix object references ([e342982](https://git.lumeweb.com/LumeWeb/libs5/commit/e342982163fe957be516f9fc07afdedd440a76f9))
|
|
||||||
* missing p2p object on S5Config ([b5e491b](https://git.lumeweb.com/LumeWeb/libs5/commit/b5e491b01a7a91fa2dd518e0ea260ac0b50c3a60))
|
|
||||||
* need to store peer, set the id the pass it to onNewPeer ([7afc759](https://git.lumeweb.com/LumeWeb/libs5/commit/7afc759ece228b148f56d0e3203f0406f4820ffa))
|
|
||||||
* need to use unpacked data from signed message ([35ebf74](https://git.lumeweb.com/LumeWeb/libs5/commit/35ebf74f4ca55281c1a402d058aad79b7ca86199))
|
|
||||||
* update registered messages ([87d1e6b](https://git.lumeweb.com/LumeWeb/libs5/commit/87d1e6b0b4f4b7ec7ae9af85b9afae5c4eaa8630))
|
|
||||||
|
|
||||||
# [0.1.0-develop.3](https://git.lumeweb.com/LumeWeb/libs5/compare/v0.1.0-develop.2...v0.1.0-develop.3) (2023-08-31)
|
# [0.1.0-develop.3](https://git.lumeweb.com/LumeWeb/libs5/compare/v0.1.0-develop.2...v0.1.0-develop.3) (2023-08-31)
|
||||||
|
|
||||||
# [0.1.0-develop.2](https://git.lumeweb.com/LumeWeb/libs5/compare/v0.1.0-develop.1...v0.1.0-develop.2) (2023-08-31)
|
# [0.1.0-develop.2](https://git.lumeweb.com/LumeWeb/libs5/compare/v0.1.0-develop.1...v0.1.0-develop.2) (2023-08-31)
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@lumeweb/libs5",
|
"name": "@lumeweb/libs5",
|
||||||
"version": "0.1.0-develop.4",
|
"version": "0.1.0-develop.3",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@lumeweb/libs5",
|
"name": "@lumeweb/libs5",
|
||||||
"version": "0.1.0-develop.4",
|
"version": "0.1.0-develop.3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@noble/curves": "^1.1.0",
|
"@noble/curves": "^1.1.0",
|
||||||
"@noble/hashes": "^1.3.1",
|
"@noble/hashes": "^1.3.1",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@lumeweb/libs5",
|
"name": "@lumeweb/libs5",
|
||||||
"version": "0.1.0-develop.4",
|
"version": "0.1.0-develop.3",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|
|
@ -10,7 +10,6 @@ export default async function (
|
||||||
data: Unpacker,
|
data: Unpacker,
|
||||||
rawData: Uint8Array,
|
rawData: Uint8Array,
|
||||||
) {
|
) {
|
||||||
const p2p = node.services.p2p;
|
|
||||||
const p = new Packer();
|
const p = new Packer();
|
||||||
p.packInt(protocolMethodHandshakeDone);
|
p.packInt(protocolMethodHandshakeDone);
|
||||||
p.packBinary(data.unpackBinary());
|
p.packBinary(data.unpackBinary());
|
||||||
|
@ -19,16 +18,16 @@ export default async function (
|
||||||
peerNetworkId = data.unpackString();
|
peerNetworkId = data.unpackString();
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
if (node.services.p2p.networkId && peerNetworkId !== p2p.networkId) {
|
if (this.networkId && peerNetworkId !== this.networkId) {
|
||||||
throw `Peer is in different network: ${peerNetworkId}`;
|
throw `Peer is in different network: ${peerNetworkId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
p.packInt(supportedFeatures);
|
p.packInt(supportedFeatures);
|
||||||
p.packInt(p2p.selfConnectionUris.length);
|
p.packInt(node.services.p2p.selfConnectionUris.length);
|
||||||
for (const uri of p2p.selfConnectionUris) {
|
for (const uri of this.selfConnectionUris) {
|
||||||
p.packString(uri.toString());
|
p.packString(uri.toString());
|
||||||
}
|
}
|
||||||
// TODO Protocol version
|
// TODO Protocol version
|
||||||
// p.packInt(protocolVersion);
|
// p.packInt(protocolVersion);
|
||||||
peer.sendMessage(await p2p.signMessageSimple(p.takeBytes()));
|
peer.sendMessage(await this.signMessageSimple(p.takeBytes()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,9 @@
|
||||||
import { P2PMessageHandler } from "#types.js";
|
import { P2PMessageHandler } from "#types.js";
|
||||||
import handshakeOpen from "#messages/handshakeOpen.js";
|
import handshakeOpen from "#messages/handshakeOpen.js";
|
||||||
import {
|
|
||||||
protocolMethodHandshakeOpen,
|
|
||||||
protocolMethodRegistryQuery,
|
|
||||||
protocolMethodSignedMessage,
|
|
||||||
recordTypeRegistryEntry,
|
|
||||||
recordTypeStorageLocation,
|
|
||||||
} from "#constants.js";
|
|
||||||
import registryQuery from "#messages/registryQuery.js";
|
|
||||||
import registryEntry from "#messages/registryEntry.js";
|
|
||||||
import storageLocation from "#messages/storageLocation.js";
|
|
||||||
import signedMessage from "#messages/signedMessage.js";
|
|
||||||
|
|
||||||
const messages = new Map<number, P2PMessageHandler>(
|
const messages = new Map<number, P2PMessageHandler>(
|
||||||
Object.entries({
|
Object.entries({
|
||||||
[protocolMethodHandshakeOpen]: handshakeOpen,
|
protocolMethodHandshakeOpen: handshakeOpen,
|
||||||
[protocolMethodRegistryQuery]: registryQuery,
|
|
||||||
[recordTypeRegistryEntry]: registryEntry,
|
|
||||||
[recordTypeStorageLocation]: storageLocation,
|
|
||||||
[protocolMethodSignedMessage]: signedMessage,
|
|
||||||
}).map(([key, value]) => [Number(key), value]),
|
}).map(([key, value]) => [Number(key), value]),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ export default async function (
|
||||||
) {
|
) {
|
||||||
const sm = await node.services.p2p.unpackAndVerifySignature(data);
|
const sm = await node.services.p2p.unpackAndVerifySignature(data);
|
||||||
const u = Unpacker.fromPacked(sm.message);
|
const u = Unpacker.fromPacked(sm.message);
|
||||||
const method = u.unpackInt();
|
const method = data.unpackInt();
|
||||||
|
|
||||||
if (method !== null && messages.has(method)) {
|
if (method !== null && messages.has(method)) {
|
||||||
await messages.get(method)?.(node, peer, u, sm, verifyId);
|
await messages.get(method)?.(node, peer, u, sm, verifyId);
|
||||||
|
|
|
@ -14,7 +14,6 @@ export default async function (
|
||||||
) {
|
) {
|
||||||
const length = data.unpackInt() as number;
|
const length = data.unpackInt() as number;
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
const p2p = node.services.p2p;
|
|
||||||
const peerIdBinary = data.unpackBinary();
|
const peerIdBinary = data.unpackBinary();
|
||||||
const id = new NodeId(peerIdBinary);
|
const id = new NodeId(peerIdBinary);
|
||||||
|
|
||||||
|
@ -32,8 +31,8 @@ export default async function (
|
||||||
// TODO Fully support multiple connection uris
|
// TODO Fully support multiple connection uris
|
||||||
const uri = new URL(connectionUris[0].toString());
|
const uri = new URL(connectionUris[0].toString());
|
||||||
uri.username = id.toBase58();
|
uri.username = id.toBase58();
|
||||||
if (!p2p.reconnectDelay.has(NodeId.decode(uri.username).toString())) {
|
if (!this.reconnectDelay.has(NodeId.decode(uri.username).toString())) {
|
||||||
p2p.connectToNode([uri]);
|
node.services.p2p.connectToNode([uri]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ export default async function (
|
||||||
message: SignedMessage,
|
message: SignedMessage,
|
||||||
verifyId: boolean,
|
verifyId: boolean,
|
||||||
) {
|
) {
|
||||||
const p2p = node.services.p2p;
|
|
||||||
const challenge = data.unpackBinary();
|
const challenge = data.unpackBinary();
|
||||||
|
|
||||||
if (!equalBytes(peer.challenge, challenge)) {
|
if (!equalBytes(peer.challenge, challenge)) {
|
||||||
|
@ -36,8 +35,8 @@ export default async function (
|
||||||
throw "Remote node does not support required features";
|
throw "Remote node does not support required features";
|
||||||
}
|
}
|
||||||
|
|
||||||
p2p.peers.set(peer.id.toString(), peer);
|
node.services.p2p.peers.set(peer.id.toString(), peer);
|
||||||
p2p.reconnectDelay.set(peer.id.toString(), 1);
|
node.services.p2p.reconnectDelay.set(peer.id.toString(), 1);
|
||||||
|
|
||||||
const connectionUrisCount = data.unpackInt() as number;
|
const connectionUrisCount = data.unpackInt() as number;
|
||||||
|
|
||||||
|
@ -46,18 +45,21 @@ export default async function (
|
||||||
peer.connectionUris.push(new URL(data.unpackString() as string));
|
peer.connectionUris.push(new URL(data.unpackString() as string));
|
||||||
}
|
}
|
||||||
|
|
||||||
node.logger.info(
|
this.logger.info(
|
||||||
`[+] ${peer.id.toString()} (${peer.renderLocationUri().toString()})`,
|
`[+] ${peer.id.toString()} (${peer.renderLocationUri().toString()})`,
|
||||||
);
|
);
|
||||||
|
|
||||||
p2p.sendPublicPeersToPeer(peer, Array.from(p2p.peers.values()));
|
node.services.p2p.sendPublicPeersToPeer(
|
||||||
for (const p of p2p.peers.values()) {
|
peer,
|
||||||
|
Array.from(node.services.p2p.peers.values()),
|
||||||
|
);
|
||||||
|
for (const p of this._peers.values()) {
|
||||||
if (p.id.equals(peer.id)) {
|
if (p.id.equals(peer.id)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p.isConnected) {
|
if (p.isConnected) {
|
||||||
p2p.sendPublicPeersToPeer(p, [peer]);
|
this.sendPublicPeersToPeer(p, [peer]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,9 @@
|
||||||
import { P2PSignedMessageHandler } from "#types.js";
|
import { P2PSignedMessageHandler } from "#types.js";
|
||||||
import handshakeDone from "#messages/signedMessages/handshakeDone.js";
|
import handshakeDone from "#messages/signedMessages/handshakeDone.js";
|
||||||
import {
|
|
||||||
protocolMethodAnnouncePeers,
|
|
||||||
protocolMethodHandshakeDone,
|
|
||||||
} from "#constants.js";
|
|
||||||
import announcePeers from "#messages/signedMessages/announcePeers.js";
|
|
||||||
|
|
||||||
const messages = new Map<number, P2PSignedMessageHandler>(
|
const messages = new Map<number, P2PSignedMessageHandler>(
|
||||||
Object.entries({
|
Object.entries({
|
||||||
[protocolMethodHandshakeDone]: handshakeDone,
|
protocolMethodHandshakeOpen: handshakeDone,
|
||||||
[protocolMethodAnnouncePeers]: announcePeers,
|
|
||||||
}).map(([key, value]) => [Number(key), value]),
|
}).map(([key, value]) => [Number(key), value]),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ export default async function (
|
||||||
data: Unpacker,
|
data: Unpacker,
|
||||||
rawData: Uint8Array,
|
rawData: Uint8Array,
|
||||||
) {
|
) {
|
||||||
const p2p = node.services.p2p;
|
|
||||||
const hash = new Multihash(rawData.subarray(1, 34));
|
const hash = new Multihash(rawData.subarray(1, 34));
|
||||||
const type = rawData[34];
|
const type = rawData[34];
|
||||||
const expiry = decodeEndian(rawData.subarray(35, 39));
|
const expiry = decodeEndian(rawData.subarray(35, 39));
|
||||||
|
@ -54,10 +53,10 @@ export default async function (
|
||||||
nodeId,
|
nodeId,
|
||||||
location: new StorageLocation(type, parts, expiry),
|
location: new StorageLocation(type, parts, expiry),
|
||||||
message: rawData,
|
message: rawData,
|
||||||
config: node.config,
|
config: this.node.config,
|
||||||
});
|
});
|
||||||
|
|
||||||
const list = p2p.hashQueryRoutingTable.get(hash) || new Set<NodeId>();
|
const list = this.hashQueryRoutingTable.get(hash) || new Set<NodeId>();
|
||||||
for (const peerId of list) {
|
for (const peerId of list) {
|
||||||
if (peerId.equals(nodeId)) {
|
if (peerId.equals(nodeId)) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -66,11 +65,11 @@ export default async function (
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p2p.peers.has(peerId.toString())) {
|
if (this._peers.has(peerId.toString())) {
|
||||||
try {
|
try {
|
||||||
p2p.peers.get(peerId.toString())?.sendMessage(rawData);
|
this._peers.get(peerId.toString())?.sendMessage(event);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
node.logger.catched(e);
|
this.logger.catched(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,6 @@ export class S5Node {
|
||||||
logger: this._nodeConfig.logger ?? DEFAULT_LOGGER,
|
logger: this._nodeConfig.logger ?? DEFAULT_LOGGER,
|
||||||
cacheDb: this._nodeConfig.db.sublevel("s5-object-cache", {}),
|
cacheDb: this._nodeConfig.db.sublevel("s5-object-cache", {}),
|
||||||
services: {} as any,
|
services: {} as any,
|
||||||
p2p: this._nodeConfig.p2p,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const p2p = new P2PService(this);
|
const p2p = new P2PService(this);
|
||||||
|
|
|
@ -31,34 +31,24 @@ export class P2PService {
|
||||||
private logger: Logger;
|
private logger: Logger;
|
||||||
private nodeKeyPair: KeyPairEd25519;
|
private nodeKeyPair: KeyPairEd25519;
|
||||||
private localNodeId?: NodeId;
|
private localNodeId?: NodeId;
|
||||||
|
private networkId?: string;
|
||||||
private nodesDb?: AbstractSublevel<
|
private nodesDb?: AbstractSublevel<
|
||||||
AbstractLevel<Uint8Array, string, Uint8Array>,
|
AbstractLevel<Uint8Array, string, Uint8Array>,
|
||||||
Uint8Array,
|
Uint8Array,
|
||||||
string,
|
string,
|
||||||
Uint8Array
|
Uint8Array
|
||||||
>;
|
>;
|
||||||
|
private hashQueryRoutingTable: Map<Multihash, Set<NodeId>> = new Map();
|
||||||
|
|
||||||
constructor(node: S5Node) {
|
constructor(node: S5Node) {
|
||||||
this._node = node;
|
this._node = node;
|
||||||
this._networkId = node.config.p2p?.network;
|
this.networkId = node.config.p2p?.network;
|
||||||
this.nodeKeyPair = node.config.keyPair;
|
this.nodeKeyPair = node.config.keyPair;
|
||||||
this.logger = node.logger;
|
this.logger = node.logger;
|
||||||
|
|
||||||
node.config.services.p2p = this;
|
node.config.services.p2p = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _hashQueryRoutingTable: Map<Multihash, Set<NodeId>> = new Map();
|
|
||||||
|
|
||||||
get hashQueryRoutingTable(): Map<Multihash, Set<NodeId>> {
|
|
||||||
return this._hashQueryRoutingTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _networkId?: string;
|
|
||||||
|
|
||||||
get networkId(): string {
|
|
||||||
return this._networkId as string;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _node: S5Node;
|
private _node: S5Node;
|
||||||
|
|
||||||
get node(): S5Node {
|
get node(): S5Node {
|
||||||
|
@ -102,8 +92,8 @@ export class P2PService {
|
||||||
const initialAuthPayloadPacker = new Packer();
|
const initialAuthPayloadPacker = new Packer();
|
||||||
initialAuthPayloadPacker.packInt(protocolMethodHandshakeOpen);
|
initialAuthPayloadPacker.packInt(protocolMethodHandshakeOpen);
|
||||||
initialAuthPayloadPacker.packBinary(Buffer.from(peer.challenge));
|
initialAuthPayloadPacker.packBinary(Buffer.from(peer.challenge));
|
||||||
if (this._networkId) {
|
if (this.networkId) {
|
||||||
initialAuthPayloadPacker.packString(this._networkId);
|
initialAuthPayloadPacker.packString(this.networkId);
|
||||||
}
|
}
|
||||||
|
|
||||||
const completer = defer<void>();
|
const completer = defer<void>();
|
||||||
|
@ -234,7 +224,7 @@ export class P2PService {
|
||||||
async signMessageSimple(message: Uint8Array): Promise<Uint8Array> {
|
async signMessageSimple(message: Uint8Array): Promise<Uint8Array> {
|
||||||
const packer = new Packer();
|
const packer = new Packer();
|
||||||
|
|
||||||
const signature = ed25519.sign(message, this.nodeKeyPair.extractBytes());
|
const signature = ed25519.sign(this.nodeKeyPair.extractBytes(), message);
|
||||||
|
|
||||||
packer.packInt(protocolMethodSignedMessage);
|
packer.packInt(protocolMethodSignedMessage);
|
||||||
packer.packBinary(Buffer.from(this.localNodeId!.bytes));
|
packer.packBinary(Buffer.from(this.localNodeId!.bytes));
|
||||||
|
@ -319,10 +309,10 @@ export class P2PService {
|
||||||
this.logger.verbose(`[connect] ${connectionUri}`);
|
this.logger.verbose(`[connect] ${connectionUri}`);
|
||||||
|
|
||||||
const socket = await createTransportSocket(protocol, connectionUri);
|
const socket = await createTransportSocket(protocol, connectionUri);
|
||||||
const peer = createTransportPeer(protocol, socket, [connectionUri]);
|
await this.onNewPeer(
|
||||||
|
createTransportPeer(protocol, socket, [connectionUri]),
|
||||||
peer.id = id;
|
true,
|
||||||
await this.onNewPeer(peer, true);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (retried) {
|
if (retried) {
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue