diff --git a/build.gradle.kts b/build.gradle.kts index 044b01225..d528be5dd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,5 @@ +import org.teavm.gradle.api.JSModuleType + plugins { id("java") id("war") @@ -28,6 +30,7 @@ teavm.js { addedToWebApp = true mainClass = "com.limechain.Main" targetFileName = "fruzhin.js" + moduleType = JSModuleType.ES2015 } //TODO: Debug only. Remove when doing release build diff --git a/src/main/java/com/limechain/Main.java b/src/main/java/com/limechain/Main.java index 8ff3b78eb..4843323ae 100644 --- a/src/main/java/com/limechain/Main.java +++ b/src/main/java/com/limechain/Main.java @@ -33,6 +33,6 @@ public static void main(String[] args) { } @JSBody(params = {"f", "apiName"}, script = "window[apiName] = f;" + - "isRpcExported = true;") + "window.fruzhin.HTTP.changeRpcExported(true);") private static native void exportAPI(Function f, JSString apiName); } \ No newline at end of file diff --git a/src/main/java/com/limechain/network/kad/KademliaService.java b/src/main/java/com/limechain/network/kad/KademliaService.java index 3e424564b..f2fddd09d 100644 --- a/src/main/java/com/limechain/network/kad/KademliaService.java +++ b/src/main/java/com/limechain/network/kad/KademliaService.java @@ -64,28 +64,28 @@ public void updateSuccessfulBootNodes() { successfulBootNodes = getPeerStoreSize(); } - @JSBody(params = {"bootNodes"}, script = "start(bootNodes)") + @JSBody(params = {"bootNodes"}, script = "window.fruzhin.startLibp2p(bootNodes)") public static native void startNetwork(String[] bootNodes); - @JSBody(script = "return getPeerId()") + @JSBody(script = "return window.fruzhin.libp?.peerId") public static native Object getPeerId(); - @JSBody(script = "return libp.peerId.privateKey") + @JSBody(script = "return window.fruzhin.libp.peerId.privateKey") public static native byte[] getPeerPrivateKey(); - @JSBody(script = "return libp.peerId.publicKey") + @JSBody(script = "return window.fruzhin.libp.peerId.publicKey") public static native byte[] getPeerPublicKey(); - @JSBody(script = "return libp.getConnections().length") + @JSBody(script = "return window.fruzhin.libp.getConnections().length") public static native int getPeerStoreSize(); /** * Populates Kademlia dht with peers closest in distance to a random id then makes connections with our node */ - @JSBody(script = "libp.peerStore.forEach( async (p) => {" + + @JSBody(script = "window.fruzhin.libp.peerStore.forEach( async (p) => {" + " for await (const foundPeer of dht.peerRouting.getClosestPeers(p.id.toBytes())){" + " if(foundPeer.peer?.multiaddrs?.length > 0){" + - " try{libp.dial(foundPeer.peer)}finally{}" + + " try{window.fruzhin.libp.dial(foundPeer.peer)}finally{}" + " }" + " }" + "});") diff --git a/src/main/java/com/limechain/network/protocol/warp/WarpSyncProtocol.java b/src/main/java/com/limechain/network/protocol/warp/WarpSyncProtocol.java index 4d202b741..9e7fe7e6a 100644 --- a/src/main/java/com/limechain/network/protocol/warp/WarpSyncProtocol.java +++ b/src/main/java/com/limechain/network/protocol/warp/WarpSyncProtocol.java @@ -54,8 +54,8 @@ public WarpSyncResponse send(WarpSyncRequest req, String protocolId) { } @JSBody(params = {"blockHash", "protocolId"}, script = "return (async () => {" + - " let peer = libp.getConnections()[0].remotePeer;" + - " let stream = await ItPbStream.pbStream(await libp.dialProtocol(peer, protocolId));" + + " let peer = window.fruzhin.libp.getConnections()[0].remotePeer;" + + " let stream = await ItPbStream.pbStream(await window.fruzhin.libp.dialProtocol(peer, protocolId));" + " stream.writeLP(new Uint8Array([...blockHash.matchAll(/../g)].map(m => parseInt(m[0], 16))));" + " let bytes = (await stream.readLP()).subarray();" + " return [...bytes].map(n => n.toString(16).padStart(2, '0')).join('');" + diff --git a/src/main/java/com/limechain/sync/JustificationVerifier.java b/src/main/java/com/limechain/sync/JustificationVerifier.java index e6a37cdf9..279b05168 100644 --- a/src/main/java/com/limechain/sync/JustificationVerifier.java +++ b/src/main/java/com/limechain/sync/JustificationVerifier.java @@ -134,7 +134,7 @@ private static byte[] getDataToVerify(Precommit precommit, BigInteger authoritie } @JSBody(params = {"publicKeyHex", "signatureHex", - "messageHex"}, script = "return verifyAsync(signatureHex, messageHex, publicKeyHex);") + "messageHex"}, script = "return window.fruzhin.ED25519.verifyAsync(signatureHex, messageHex, publicKeyHex);") public static native JSPromise verifyAsync(String publicKeyHex, String signatureHex, String messageHex); } diff --git a/src/main/java/com/limechain/teavm/HttpRequest.java b/src/main/java/com/limechain/teavm/HttpRequest.java index 1a13d204c..1f3ecdef2 100644 --- a/src/main/java/com/limechain/teavm/HttpRequest.java +++ b/src/main/java/com/limechain/teavm/HttpRequest.java @@ -23,10 +23,10 @@ private static void asyncHttpRequest(String method, String url, String body, Asy }); } - @JSBody(params = {"method", "url", "body", "callback"}, script = "return asyncHttpRequest(method, url, body, callback);") + @JSBody(params = {"method", "url", "body", "callback"}, script = "return window.fruzhin.HTTP.asyncHttpRequest(method, url, body, callback);") public static native void createAsyncHttpRequest(String method, String url, String body, TeaVMCallback callback); - @JSBody(params = {"method", "url", "body"}, script = "return httpRequestSync(method, url, body);") + @JSBody(params = {"method", "url", "body"}, script = "return window.fruzhin.HTTP.httpRequestSync(method, url, body);") public static native String createHttpRequest(String method, String url, String body); } diff --git a/src/main/java/com/limechain/utils/HashUtils.java b/src/main/java/com/limechain/utils/HashUtils.java index e2a895553..03a552dfc 100644 --- a/src/main/java/com/limechain/utils/HashUtils.java +++ b/src/main/java/com/limechain/utils/HashUtils.java @@ -1,6 +1,5 @@ package com.limechain.utils; -import com.limechain.polkaj.Hash256; import lombok.experimental.UtilityClass; import org.teavm.jso.JSBody; import org.teavm.jso.core.JSString; @@ -10,6 +9,6 @@ public class HashUtils { @JSBody(params = {"inputHex"}, script = "{" + "let bytes = new Uint8Array([...inputHex.matchAll(/../g)].map(m => parseInt(m[0], 16)));" + - "return Blake2b.hash(bytes,undefined,32);" + "}") + "return window.fruzhin.Blake2b.hash(bytes,undefined,32);" + "}") public static native JSString hashWithBlake2b(String inputHex); } diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html index cc2e06969..903582195 100644 --- a/src/main/webapp/index.html +++ b/src/main/webapp/index.html @@ -3,58 +3,11 @@ Fruzhin - + - \ No newline at end of file diff --git a/src/main/webapp/js/blake2b.js b/src/main/webapp/js/blake2b.js index 6b5de4354..d3a838e02 100644 --- a/src/main/webapp/js/blake2b.js +++ b/src/main/webapp/js/blake2b.js @@ -1,4 +1,4 @@ -var Blake2b = { +export var Blake2b = { v: new Uint32Array(32), m: new Uint32Array(32), BLAKE2B_IV32: new Uint32Array([4089235720, 1779033703, 2227873595, 3144134277, 4271175723, 1013904242, 1595750129, 2773480762, 2917565137, 1359893119, 725511199, 2600822924, 4215389547, 528734635, 327033209, 1541459225]), diff --git a/src/main/webapp/js/ed25519.js b/src/main/webapp/js/ed25519.js index a640b1019..d2707c609 100644 --- a/src/main/webapp/js/ed25519.js +++ b/src/main/webapp/js/ed25519.js @@ -254,7 +254,6 @@ const _verify = (sig, msg, pub, opts = dvo) => { }; return { hashable, finish }; }; -const verifyAsync = async (s, m, p, opts = dvo) => hashFinish(true, _verify(s, m, p, opts)); const cr = () => // We support: 1) browsers 2) node.js 19+ typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined; const etc = { @@ -316,4 +315,6 @@ const wNAF = (n) => { } } return { p, f }; // return both real and fake points for JIT -}; \ No newline at end of file +}; + +export const verifyAsync = async (s, m, p, opts = dvo) => hashFinish(true, _verify(s, m, p, opts)); \ No newline at end of file diff --git a/src/main/webapp/js/fruzhin-lib.js b/src/main/webapp/js/fruzhin-lib.js new file mode 100644 index 000000000..608f78ba3 --- /dev/null +++ b/src/main/webapp/js/fruzhin-lib.js @@ -0,0 +1,66 @@ +import 'https://unpkg.com/@chainsafe/libp2p-yamux/dist/index.min.js'; +import 'https://unpkg.com/@chainsafe/libp2p-noise/dist/index.min.js'; +import 'https://unpkg.com/@libp2p/websockets/dist/index.min.js'; +import 'https://unpkg.com/@libp2p/kad-dht/dist/index.min.js'; +import 'https://unpkg.com/@libp2p/identify/dist/index.min.js'; +import 'https://unpkg.com/@libp2p/bootstrap/dist/index.min.js'; +import 'https://unpkg.com/@libp2p/ping/dist/index.min.js'; +import 'https://unpkg.com/@chainsafe/libp2p-gossipsub/dist/index.min.js'; +import 'https://unpkg.com/libp2p/dist/index.min.js'; +import 'https://unpkg.com/it-pipe/dist/index.min.js'; +import 'https://unpkg.com/it-pb-stream/dist/index.min.js'; + +import * as Blake2b from './blake2b.js'; +import * as ED25519 from './ed25519.js'; +import * as HTTP from './http.js'; +import * as Fruzhin from './fruzhin.js' + +var startLibp2p = async (bootnodes) => { + console.log('Starting libp2p node'); + console.log(bootnodes); + let test = { + addresses: { + listen: [], + }, + transports: [ + Libp2PWebsockets.webSockets() + ], + streamMuxers: [ChainsafeLibp2PYamux.yamux()], + connectionEncryption: [ChainsafeLibp2PNoise.noise()], + peerDiscovery: [ + Libp2PBootstrap.bootstrap({ + list: bootnodes + }) + ], + services: { + identify: Libp2PIdentify.identify(), + ping: Libp2PPing.ping(), + dht: Libp2PKadDht.kadDHT({protocol: "/dot/kad"}), + pubsub: ChainsafeLibp2PGossipsub.gossipsub(), + } + }; + + window.fruzhin.libp = await Libp2P.createLibp2p(test); + window.fruzhin.libp.start(); + + // libp.addEventListener('peer:discovery', (evt) => console.log('Discovered:', evt.detail.id.toString())) + // libp.addEventListener('peer:connect', (evt) => console.log('Connected:', evt.detail.toString())) + // libp.addEventListener('peer:disconnect', (evt) => console.log('Disconnected:', evt.detail.toString())) + + // let pbStream = ItProtobufStream.pbStream; + // + // libp.handle('/dot/sync/warp', ({stream}) => { + // + // console.log('Received a warp sync request'); + // stream.write('Hello from the other side'); + // stream.end(); + // }); +} + +window.fruzhin = { + startLibp2p, + ED25519, + HTTP, + ...Blake2b, + ...Fruzhin, +} diff --git a/src/main/webapp/js/fruzhin.js b/src/main/webapp/js/fruzhin.js deleted file mode 100644 index dfcdd4591..000000000 --- a/src/main/webapp/js/fruzhin.js +++ /dev/null @@ -1,5 +0,0 @@ -import './lib/external.js'; - -import './blake2b.js'; -import './ed25519.js'; -import './http.js'; \ No newline at end of file diff --git a/src/main/webapp/js/http.js b/src/main/webapp/js/http.js index fec1de453..fc2974484 100644 --- a/src/main/webapp/js/http.js +++ b/src/main/webapp/js/http.js @@ -41,7 +41,7 @@ var isRpcExported = false; function sendRpcRequest(method, params) { return new Promise((resolve, reject) => { - if (isRpcExported === false) { + if (window.fruzhin.HTTP.getRpcExported() === false) { window.setTimeout(async () => { try { const result = await sendRpcRequest(method, params); @@ -60,3 +60,19 @@ function sendRpcRequest(method, params) { } }); } + +function changeRpcExported(newVal){ + isRpcExported = newVal; +} + +function getRpcExported(){ + return isRpcExported; +} + +export { + sendRpcRequest, + asyncHttpRequest, + httpRequestSync, + changeRpcExported, + getRpcExported +} \ No newline at end of file diff --git a/src/main/webapp/js/lib/external.js b/src/main/webapp/js/lib/external.js deleted file mode 100644 index a9619243f..000000000 --- a/src/main/webapp/js/lib/external.js +++ /dev/null @@ -1,11 +0,0 @@ -import 'https://unpkg.com/@chainsafe/libp2p-yamux/dist/index.min.js'; -import 'https://unpkg.com/@chainsafe/libp2p-noise/dist/index.min.js'; -import 'https://unpkg.com/@libp2p/websockets/dist/index.min.js'; -import 'https://unpkg.com/@libp2p/kad-dht/dist/index.min.js'; -import 'https://unpkg.com/@libp2p/identify/dist/index.min.js'; -import 'https://unpkg.com/@libp2p/bootstrap/dist/index.min.js'; -import 'https://unpkg.com/@libp2p/ping/dist/index.min.js'; -import 'https://unpkg.com/@chainsafe/libp2p-gossipsub/dist/index.min.js'; -import 'https://unpkg.com/libp2p/dist/index.min.js'; -import 'https://unpkg.com/it-pipe/dist/index.min.js'; -import 'https://unpkg.com/it-pb-stream/dist/index.min.js'; \ No newline at end of file