Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
e832fd3
handle auth headers with ucrypto
cwilvx May 7, 2025
d8e161c
refactor inter-node comms with ucrypto
cwilvx May 7, 2025
82426bd
refactor consensus routine
cwilvx May 9, 2025
88097f6
refactor web2 identities with ucrypto
cwilvx May 12, 2025
37213d5
update genesis block signatures
cwilvx May 13, 2025
50c24a7
fix: await tx signature validation
cwilvx May 18, 2025
9e0c149
add PQC identity routines and enhance identity verification
cwilvx May 21, 2025
ffee04b
add PQC identity handling in GCRIdentityRoutines
cwilvx May 21, 2025
fca5e63
handle multi sign and pqc identities
cwilvx May 26, 2025
2529b6e
store xm identity signature alongside the xm address
cwilvx May 29, 2025
96136bc
update pqc signature verification
cwilvx Jun 2, 2025
0474d29
Merge branch 'testnet' into ucrypto
cwilvx Jun 3, 2025
6b78d58
fix: gcr web2 identity remove data destructure
cwilvx Jun 3, 2025
5bcbd73
refactor tx.ed25519_address to tx.from_ed25519_address
cwilvx Jun 3, 2025
fb56ed1
upgrade sdk
cwilvx Jun 3, 2025
f5d90e5
upgrade sdk
cwilvx Jun 3, 2025
1c98613
fix: revert xm message verification
cwilvx Jun 4, 2025
2d0e687
upgrade sdk
cwilvx Jun 4, 2025
b71a206
update points system to read new xm identity structure correctly
cwilvx Jun 4, 2025
97ab982
update isFirstConnection queries to match agaist object properties
cwilvx Jun 4, 2025
5646e20
remove log.only
cwilvx Jun 4, 2025
1828f9a
add test log only
cwilvx Jun 5, 2025
15df204
add exit
cwilvx Jun 5, 2025
6f723eb
revert debug prints
cwilvx Jun 5, 2025
12479a6
upgrade twitter sdk
cwilvx Jun 5, 2025
97ad3aa
Merge branch 'testnet' into ucrypto
cwilvx Jun 9, 2025
2187751
cleanup
cwilvx Jun 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
TWITTER_USERNAME=
TWITTER_PASSWORD=
TWITTER_EMAIL=

GITHUB_TOKEN=
2 changes: 2 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ module.exports = {
{
selector: "variableLike",
format: ["camelCase"],
leadingUnderscore: "allow",
trailingUnderscore: "allow",
},
{
selector: "function",
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@
"@fastify/cors": "^9.0.1",
"@fastify/swagger": "^8.15.0",
"@fastify/swagger-ui": "^4.1.0",
"@kynesyslabs/demosdk": "^2.2.49",
"@kynesyslabs/demosdk": "^2.2.51",
"@octokit/core": "^6.1.5",
"@the-convocation/twitter-scraper": "^0.16.6",
"@the-convocation/twitter-scraper": "^0.17.0",
"@types/express": "^4.17.21",
"@types/http-proxy": "^1.17.14",
"@types/lodash": "^4.17.4",
Expand Down
4 changes: 2 additions & 2 deletions run
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,14 @@ cd $PG_FOLDER
if [ "$CLEAN" == "true" ]; then
echo "Cleaning the database"
sleep 1
sudo rm -rf data_*
rm -rf data_*
mkdir data_${PG_PORT}
fi

# Suppressing errors if the database is not running
docker compose down > /dev/null 2>&1
if [ "$CLEAN" == "true" ]; then
rm -rf data_${PG_PORT} || sudo rm -rf data_${PG_PORT}
rm -rf data_${PG_PORT} || rm -rf data_${PG_PORT}
mkdir data_${PG_PORT}
fi
# Finally starting the database
Expand Down
8 changes: 4 additions & 4 deletions src/features/incentive/PointSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ export class PointSystem {
const subChainKeys = Object.keys(subChains)

for (const subChain of subChainKeys) {
const addresses = subChains[subChain]
const identities = subChains[subChain]

if (Array.isArray(addresses)) {
addresses.forEach(address => {
const walletId = `${chain}:${address}`
if (Array.isArray(identities)) {
identities.forEach(identity => {
const walletId = `${chain}:${identity.address}`
linkedWallets.push(walletId)
})
}
Expand Down
58 changes: 33 additions & 25 deletions src/features/web2/Web2RequestManager.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import Cryptography from "src/libs/crypto/cryptography"
import Hashing from "src/libs/crypto/hashing"
import { PeerManager } from "src/libs/peer"
import required from "src/utilities/required"
import SharedState from "src/utilities/sharedState"
import SharedState, { getSharedState } from "src/utilities/sharedState"

import {
IWeb2Attestation,
Expand All @@ -12,6 +11,11 @@ import {
import { DAHR } from "./dahr/DAHR"

import terminalKit from "terminal-kit"
import {
hexToUint8Array,
ucrypto,
uint8ArrayToHex,
} from "@kynesyslabs/demosdk/encryption"

const term = terminalKit.terminal

Expand Down Expand Up @@ -49,8 +53,10 @@ export class Web2RequestManager {
* @param {IWeb2Result} web2Result - The result of the Web2 request to be attested.
* @returns {IWeb2Attestation} The combined attestation for the Web2 request and result.
*/
getAttestedResult(web2Result: IWeb2Result): IWeb2Attestation {
const combinedAttestation = this.validateWeb2RequestAndResult(
async getAttestedResult(
web2Result: IWeb2Result,
): Promise<IWeb2Attestation> {
const combinedAttestation = await this.validateWeb2RequestAndResult(
this.dahr.web2Request,
web2Result,
)
Expand All @@ -63,10 +69,10 @@ export class Web2RequestManager {
return combinedAttestation
}

private validateWeb2RequestAndResult(
private async validateWeb2RequestAndResult(
web2Request: IWeb2Request,
web2Result: IWeb2Result,
): IWeb2Attestation {
): Promise<IWeb2Attestation> {
term.yellow.bold("[Web2Parser] Validating request and result...\n")

// Combine request and result into a single object
Expand All @@ -81,31 +87,35 @@ export class Web2RequestManager {
term.bold("[Web2Parser] Combined hash:\n")
console.log(hashedCombined)

const signature = Cryptography.sign(
hashedCombined,
SharedState.getInstance().identity.ed25519.privateKey,
const signature = await ucrypto.sign(
getSharedState.signingAlgorithm,
new TextEncoder().encode(hashedCombined),
)

const attestation: IWeb2Attestation = {
hash: hashedCombined,
timestamp: Date.now(),
identity: SharedState.getInstance().identity.ed25519.publicKey,
signature: signature,
identity: getSharedState.keypair.publicKey,
signature: {
type: getSharedState.signingAlgorithm,
data: uint8ArrayToHex(signature.signature),
},
valid: null,
}
term.bold("[Web2Parser] Combined Attestation:\n")
console.log(attestation)

const hexKey = SharedState
.getInstance()
.identity.ed25519.publicKey.toString("hex")
const hexKey = getSharedState.publicKeyHex

// Store the attestation in the web2Request
web2Request.attestations[hexKey] = attestation

// Update the hash and signature of the web2Request
web2Request.hash = hashedCombined
web2Request.signature = signature
web2Request.signature = {
type: getSharedState.signingAlgorithm,
data: uint8ArrayToHex(signature.signature),
}

// Store the result in the web2Request if it's not already set
if (web2Request.result === undefined) {
Expand All @@ -117,7 +127,7 @@ export class Web2RequestManager {
return attestation
}

private verifyWeb2RequestAndResult(): boolean {
private async verifyWeb2RequestAndResult(): Promise<boolean> {
required(this.dahr.web2Request, "Missing request")
let valid = true

Expand All @@ -127,11 +137,12 @@ export class Web2RequestManager {
const hash = Hashing.sha256(stringifiedContent)

const hashIsValid = hash === attestation.hash
const signatureIsValid = Cryptography.verify(
attestation.signature.toString("hex"),
attestation.hash,
attestation.identity,
)
const signatureIsValid = await ucrypto.verify({
algorithm: attestation.signature.type,
publicKey: attestation.identity as Uint8Array,
signature: hexToUint8Array(attestation.signature.signature),
message: new TextEncoder().encode(attestation.hash),
})
const isValid = hashIsValid && signatureIsValid
attestation.valid = isValid

Expand Down Expand Up @@ -169,10 +180,7 @@ export class Web2RequestManager {
* @param {number} timeout - The timeout.
* @returns {Promise<boolean>} Whether the quorum is reached.
*/
async quorumIsReached(
quorum = 10,
timeout = 9000,
): Promise<boolean> {
async quorumIsReached(quorum = 10, timeout = 9000): Promise<boolean> {
let reachedQuorum = false
let timer = 0
// NOTE We wait for timeout seconds before surrendering
Expand Down
2 changes: 1 addition & 1 deletion src/features/web2/dahr/DAHR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export class DAHR {
})

const attestedResult =
web2RequestManager.getAttestedResult(web2Response)
await web2RequestManager.getAttestedResult(web2Response)

return {
...attestedResult,
Expand Down
18 changes: 10 additions & 8 deletions src/features/web2/handleWeb2.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import Cryptography from "src/libs/crypto/cryptography"
import Hashing from "src/libs/crypto/hashing"
import required from "src/utilities/required"
import SharedState from "src/utilities/sharedState"
import SharedState, { getSharedState } from "src/utilities/sharedState"
import { IWeb2Request } from "@kynesyslabs/demosdk/types"
import { Web2RequestManager } from "./Web2RequestManager"
import { DAHRFactory } from "src/features/web2/dahr/DAHRFactory"

import terminalKit from "terminal-kit"
import { DAHR } from "./dahr/DAHR"
import { ucrypto, uint8ArrayToHex } from "@kynesyslabs/demosdk/encryption"

const term = terminalKit.terminal

Expand Down Expand Up @@ -77,26 +77,28 @@ export async function handleWeb2(
const hashedAttestations = Hashing.sha256(
JSON.stringify(dahr.web2Request.attestations),
)
const ourPrivateKey =
SharedState.getInstance().identity.ed25519.privateKey
const signedAttestations = Cryptography.sign(
hashedAttestations,
ourPrivateKey,
const signature = await ucrypto.sign(
getSharedState.signingAlgorithm,
new TextEncoder().encode(hashedAttestations),
)

term.green(
"[handleWeb2] [*] Compiling and certifying the result on our side...",
)

dahr.web2Request.hash = hashedAttestations
dahr.web2Request.signature = signedAttestations
dahr.web2Request.signature = {
type: getSharedState.signingAlgorithm,
signature: uint8ArrayToHex(signature.signature),
}
} catch (error) {
console.log("[handleWeb2] Error: " + JSON.stringify(error))
return JSON.stringify(error)
}
} else {
/* TODO Activate the below on production */
// First, we have to validate the attestations
// NOTE: (For Massouji) web2RequestManager.web2ResultIsValid now returns a Promise<boolean>
// web2RequestManager.web2ResultIsValid
// Now that our web2request.request object is updated,
// TODO we have to merge the attestations' arrays with valid values
Expand Down
21 changes: 17 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import getTimestampCorrection from "./libs/utils/calibrateTime"
import net from "net"
import { SignalingServer } from "./features/InstantMessagingProtocol/signalingServer/signalingServer"
import { serverRpcBun } from "./libs/network/server_rpc"
import { hexToUint8Array, ucrypto, uint8ArrayToHex } from "@kynesyslabs/demosdk/encryption"

const term = terminalkit.terminal

Expand Down Expand Up @@ -224,21 +225,33 @@ async function preMainLoop() {

// ANCHOR The whole first part of main ensures the environment is ready to run
await getSharedState.identity.ensureIdentity() // ? Should we generate the identity option based too? (see SERVER_PORT and others )
const id = getSharedState.identity
// INFO: Initialize Unified Crypto with ed25519 private key
await ucrypto.generateAllIdentities(
getSharedState.identity.ed25519.privateKey as Uint8Array,
)
getSharedState.keypair = await ucrypto.getIdentity(
getSharedState.signingAlgorithm,
)

// const id = getSharedState.identity
term.green("[BOOTSTRAP] Our identity is ready\n")
// Log identity
const publicKeyHex = uint8ArrayToHex(getSharedState.keypair.publicKey as Uint8Array)
term.green(
"\n[MAIN] 🔗 WE ARE " + id.ed25519.publicKey.toString("hex") + " 🔗 \n",
"\n[MAIN] 🔗 WE ARE " + publicKeyHex + " 🔗 \n",
)
// Creating ourselves as a peer // ? Should this be removed in production?
const ourselves = "http://127.0.0.1:" + indexState.SERVER_PORT
getSharedState.connectionString = ourselves
log.info("Our connection string is: " + ourselves)
// And saves the public key file
const publicKeyHex = id.ed25519.publicKey.toString("hex")
fs.writeFileSync("publickey_" + publicKeyHex, publicKeyHex + "\n")
fs.writeFileSync(
"publickey_" + getSharedState.signingAlgorithm + "_" + publicKeyHex,
publicKeyHex + "\n",
)
log.info("Our public key is: " + publicKeyHex)


// ANCHOR Preparing the peer manager and loading the peer list
PeerManager.getInstance().loadPeerList()
indexState.PeerList = PeerManager.getInstance().getPeers()
Expand Down
31 changes: 19 additions & 12 deletions src/libs/abstraction/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { GithubProofParser } from "./web2/github"
import { TwitterProofParser } from "./web2/twitter"
import { type Web2ProofParser } from "./web2/parsers"
import { Web2CoreTargetIdentityPayload } from "@kynesyslabs/demosdk/abstraction"
import { forgeToHex } from "../crypto/forgeUtils"
import { hexToUint8Array, ucrypto } from "@kynesyslabs/demosdk/encryption"

/**
* Fetches the proof data using the appropriate parser and verifies the signature
Expand Down Expand Up @@ -34,24 +34,31 @@ export async function verifyWeb2Proof(
const instance = await parser.getInstance()

try {
const { message, publicKey, signature } = await instance.readData(
const { message, type, signature } = await instance.readData(
payload.proof,
)
try {
const verified = await ucrypto.verify({
algorithm: type,
message: new TextEncoder().encode(message),
publicKey: hexToUint8Array(sender),
signature: hexToUint8Array(signature),
})

sender = forgeToHex(sender)
if (sender !== publicKey) {
return {
success: verified,
message: verified
? `Verified ${payload.context} proof`
: `Failed to verify ${payload.context} proof`,
}
} catch (error: any) {
return {
success: false,
message:
"Unable to verify proof: public key does not match sender",
message: `Failed to verify ${
payload.context
} proof: ${error.toString()}`,
}
}
const verified = Cryptography.verify(message, signature, publicKey)

return {
success: verified,
message: `Verified ${payload.context} proof`,
}
} catch (error: any) {
console.error(error)
return {
Expand Down
11 changes: 3 additions & 8 deletions src/libs/abstraction/web2/github.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import axios from "axios"
import { Octokit } from "@octokit/core"
import { Web2ProofParser } from "./parsers"
import log from "@/utilities/logger"
import { SigningAlgorithm } from "@kynesyslabs/demosdk/types"

export class GithubProofParser extends Web2ProofParser {
private static instance: GithubProofParser
Expand Down Expand Up @@ -39,7 +39,7 @@ export class GithubProofParser extends Web2ProofParser {

async readData(
proofUrl: string,
): Promise<{ message: string; signature: string; publicKey: string }> {
): Promise<{ message: string; type: SigningAlgorithm; signature: string }> {
this.verifyProofFormat(proofUrl, "github")
const { username, gistId } = this.parseGistDetails(proofUrl)
let content: string
Expand Down Expand Up @@ -90,12 +90,7 @@ export class GithubProofParser extends Web2ProofParser {
static async getInstance() {
if (!this.instance) {
this.instance = new this()

try {
await this.instance.login()
} catch (error) {
log.error("Failed to login to github: " + error)
}
await this.instance.login()
}

return this.instance
Expand Down
Loading