fortify working and verifying
This commit is contained in:
parent
9e4a57605d
commit
dee1da6fb1
@ -174,6 +174,8 @@ export class Region {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.Region = Region;
|
||||||
|
|
||||||
const EAST = new Continent("East");
|
const EAST = new Continent("East");
|
||||||
const WEST = new Continent("West");
|
const WEST = new Continent("West");
|
||||||
|
|
||||||
|
@ -103,11 +103,11 @@ export class Packet {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static createFortify(fortify, verification) {
|
static createFortify(fortify) {
|
||||||
return this._sign({
|
return this._sign({
|
||||||
...this._createBase("ACT"),
|
...this._createBase("ACT"),
|
||||||
|
action: "FORTIFY",
|
||||||
fortify: fortify,
|
fortify: fortify,
|
||||||
verification: verification,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,13 @@ import { RsaPubKey } from "../crypto/rsa.js";
|
|||||||
import { PaillierPubKey, ReadOnlyCiphertext } from "../crypto/paillier.js";
|
import { PaillierPubKey, ReadOnlyCiphertext } from "../crypto/paillier.js";
|
||||||
import { Region } from "./map.js";
|
import { Region } from "./map.js";
|
||||||
import { showDefenseDom } from "./dom.js";
|
import { showDefenseDom } from "./dom.js";
|
||||||
import { proveFortify, proveRange, proveRegions, verifyRegions } from "./proofs.js";
|
import {
|
||||||
|
proveFortify,
|
||||||
|
proveRange,
|
||||||
|
proveRegions,
|
||||||
|
verifyFortify,
|
||||||
|
verifyRegions,
|
||||||
|
} from "./proofs.js";
|
||||||
|
|
||||||
// Timeout to consider a player disconnected
|
// Timeout to consider a player disconnected
|
||||||
const TIMEOUT = 30_000;
|
const TIMEOUT = 30_000;
|
||||||
@ -184,22 +190,40 @@ export class Player {
|
|||||||
* @param data Data received via socket
|
* @param data Data received via socket
|
||||||
*/
|
*/
|
||||||
fortify(data) {
|
fortify(data) {
|
||||||
let sender = Region.getRegion(data.startRegion);
|
if (!verifyFortify(data.fortify, this.paillierPubKey)) {
|
||||||
let receiver = Region.getRegion(data.endRegion);
|
console.log("Failed to verify fortify!");
|
||||||
let strength = parseInt(data.strength);
|
|
||||||
|
|
||||||
if (
|
|
||||||
sender.owner === this &&
|
|
||||||
receiver.owner === this &&
|
|
||||||
sender.strength > strength &&
|
|
||||||
strength > 0
|
|
||||||
) {
|
|
||||||
receiver.reinforce(strength);
|
|
||||||
sender.strength -= strength;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!Object.keys(data.fortify.fortify).reduce(
|
||||||
|
(c, r) => c && Region.getRegion(r).owner === this,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
console.log("Invalid fortify");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let regionName of Object.keys(data.fortify.fortify)) {
|
||||||
|
let region = Region.getRegion(regionName);
|
||||||
|
|
||||||
|
region.reinforce(
|
||||||
|
new ReadOnlyCiphertext(
|
||||||
|
this.paillierPubKey,
|
||||||
|
BigInt(data.fortify.fortify[regionName])
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// request proofs
|
||||||
|
for (let region of this.getRegions()) {
|
||||||
|
if ([...region.neighbours.values()].find((r) => r.owner === game.us)) {
|
||||||
|
region.requestProof();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
sendFortify(startRegion, endRegion, amount) {
|
sendFortify(startRegion, endRegion, amount) {
|
||||||
@ -209,12 +233,16 @@ export class Player {
|
|||||||
};
|
};
|
||||||
|
|
||||||
for (let r of this.getRegions()) {
|
for (let r of this.getRegions()) {
|
||||||
if (!fortify.hasOwnProperty(r)) {
|
if (!fortify.hasOwnProperty(r.name)) {
|
||||||
fortify[r] = new Ciphertext(this.paillierPubKey, 0n);
|
fortify[r.name] = new Ciphertext(this.paillierPubKey, 0n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.emit("message", Packet.createFortify(fortify, proveFortify(fortify)));
|
for (let r of Object.keys(fortify)) {
|
||||||
|
Region.getRegion(r).reinforce(fortify[r]);
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit("message", Packet.createFortify(proveFortify(fortify)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -253,7 +281,7 @@ export class Player {
|
|||||||
|
|
||||||
if (data.action === "FORTIFY") {
|
if (data.action === "FORTIFY") {
|
||||||
if (this === game.us) {
|
if (this === game.us) {
|
||||||
return;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return this.fortify(data);
|
return this.fortify(data);
|
||||||
}
|
}
|
||||||
|
@ -549,16 +549,18 @@ export function proveFortify(fortify) {
|
|||||||
|
|
||||||
// Show pair is joined by edge
|
// Show pair is joined by edge
|
||||||
let pairName = pair.sort();
|
let pairName = pair.sort();
|
||||||
verification.pairEdgeSalt = input.edges.find(
|
verification.pairEdgeSalt =
|
||||||
(e) => e.edge[0] === pairName[0] && e.edge[1] === pairName[1]
|
"0x" +
|
||||||
).salt;
|
input.edges
|
||||||
|
.find((e) => e.edge[0] === pairName[0] && e.edge[1] === pairName[1])
|
||||||
|
.salt.toString(16);
|
||||||
|
|
||||||
verifications.push(verification);
|
verifications.push(verification);
|
||||||
} else {
|
} else {
|
||||||
// Show isomorphism
|
// Show isomorphism
|
||||||
let edges = {};
|
let edges = {};
|
||||||
for (let e of input.edges) {
|
for (let e of input.edges) {
|
||||||
edges[e.edge[0] + e.edge[1]] = e.salt;
|
edges[e.edge[0] + e.edge[1]] = "0x" + e.salt.toString(16);
|
||||||
}
|
}
|
||||||
|
|
||||||
let zeroProofs = {};
|
let zeroProofs = {};
|
||||||
@ -618,7 +620,7 @@ export function verifyFortify(obj, key) {
|
|||||||
// Check remaining pair sums to zero
|
// Check remaining pair sums to zero
|
||||||
let pair = [...regions.values()].sort();
|
let pair = [...regions.values()].sort();
|
||||||
let c = new ReadOnlyCiphertext(key, BigInt(proof.regions[pair[0]]));
|
let c = new ReadOnlyCiphertext(key, BigInt(proof.regions[pair[0]]));
|
||||||
c.update(proof.regions[pair[1]]);
|
c.update(new ReadOnlyCiphertext(key, BigInt(proof.regions[pair[1]])));
|
||||||
let p = c.verifyNI(verification.pairCipherText);
|
let p = c.verifyNI(verification.pairCipherText);
|
||||||
if (p !== 0n) {
|
if (p !== 0n) {
|
||||||
return false;
|
return false;
|
||||||
@ -628,7 +630,7 @@ export function verifyFortify(obj, key) {
|
|||||||
let hasher = new jsSHA("SHA3-256", "TEXT");
|
let hasher = new jsSHA("SHA3-256", "TEXT");
|
||||||
hasher.update(pair[0]);
|
hasher.update(pair[0]);
|
||||||
hasher.update(pair[1]);
|
hasher.update(pair[1]);
|
||||||
hasher.update(verification.pairEdgeSalt.toString(16));
|
hasher.update(BigInt(verification.pairEdgeSalt).toString(16));
|
||||||
let hash = hasher.getHash("HEX");
|
let hash = hasher.getHash("HEX");
|
||||||
|
|
||||||
if (!proof.edges.includes(hash)) {
|
if (!proof.edges.includes(hash)) {
|
||||||
@ -652,7 +654,7 @@ export function verifyFortify(obj, key) {
|
|||||||
// Ciphertexts match?
|
// Ciphertexts match?
|
||||||
for (let r of regionNames) {
|
for (let r of regionNames) {
|
||||||
let c = new ReadOnlyCiphertext(key, BigInt(proof.regions[r]));
|
let c = new ReadOnlyCiphertext(key, BigInt(proof.regions[r]));
|
||||||
c.update(fortify[psiMap[r]]);
|
c.update(new ReadOnlyCiphertext(key, BigInt(fortify[psiMap[r]])));
|
||||||
let p = c.verifyNI(verification.zeroProofs[r]);
|
let p = c.verifyNI(verification.zeroProofs[r]);
|
||||||
|
|
||||||
if (p !== 0n) {
|
if (p !== 0n) {
|
||||||
@ -674,7 +676,7 @@ export function verifyFortify(obj, key) {
|
|||||||
let hasher = new jsSHA("SHA3-256", "TEXT");
|
let hasher = new jsSHA("SHA3-256", "TEXT");
|
||||||
hasher.update(psiRegion);
|
hasher.update(psiRegion);
|
||||||
hasher.update(psiNeighbour);
|
hasher.update(psiNeighbour);
|
||||||
hasher.update(edgeSalt.toString(16));
|
hasher.update(BigInt(edgeSalt).toString(16));
|
||||||
let hash = hasher.getHash("HEX");
|
let hash = hasher.getHash("HEX");
|
||||||
|
|
||||||
if (proverEdges.has(hash)) {
|
if (proverEdges.has(hash)) {
|
||||||
|
Binary file not shown.
@ -806,6 +806,8 @@ Validating $E(m)$ is done with the proof of zero. Then it remains to prove that
|
|||||||
\end{enumerate}
|
\end{enumerate}
|
||||||
\end{protocol}
|
\end{protocol}
|
||||||
|
|
||||||
|
The downside of this proof over the BCDG proof \cite{bcdg1987} is that the time to perform and verify this proof grows linearly with $|m|$. However, in most cases $|m|$ should be small: i.e, $|m| \leq 5$.
|
||||||
|
|
||||||
Range proof is used in points (3), (4), and (5). In (3), this is to convince other players that the number of units is sufficient for the action. In (4), this is to show that the region is not totally depleted. In (5), this is to ensure the number of units being fortified is less than the strength of the region. All of these are performed using \hyperref[protocol4]{Protocol~\ref*{protocol4}} and by using the additive homomorphic property to subtract the lower range from $m$ first.
|
Range proof is used in points (3), (4), and (5). In (3), this is to convince other players that the number of units is sufficient for the action. In (4), this is to show that the region is not totally depleted. In (5), this is to ensure the number of units being fortified is less than the strength of the region. All of these are performed using \hyperref[protocol4]{Protocol~\ref*{protocol4}} and by using the additive homomorphic property to subtract the lower range from $m$ first.
|
||||||
|
|
||||||
\subsection{Proving fortifications}
|
\subsection{Proving fortifications}
|
||||||
|
Loading…
Reference in New Issue
Block a user