Added encoding and decoding technique for keygen protocol, using packed bytes instead of raw JSON

This commit is contained in:
Kirill Fedoseev 2019-08-25 00:26:16 +03:00
parent 3098b0ef80
commit fc03632e20
9 changed files with 197 additions and 22 deletions

4
.gitignore vendored
View File

@ -8,8 +8,8 @@ data/
demo/validator*/db
demo/validator*/keys
demo/validator*/queue
demo/ganache_home
demo/ganache_side
demo/ganache_home_db/
demo/ganache_side_db/
src/deploy/deploy-home/build/
src/deploy/deploy-side/build/
src/deploy/deploy-test/build/

View File

@ -6,27 +6,27 @@ cd $(dirname "$0")
echo "Starting side test blockchain"
mntpoint=`pwd`/ganache_side_db
if [ ! -d ${mntpoint} ]; then
mkdir ${mntpoint}
mntpoint="$(pwd)/ganache_side_db"
if [ ! -d "$mntpoint" ]; then
mkdir "$mntpoint"
fi
docker kill ganache_side > /dev/null 2>&1 || true
docker network create blockchain_side > /dev/null 2>&1 || true
docker run -d --network blockchain_side --rm --name ganache_side -v ${mntpoint}:/app/db \
docker run -d --network blockchain_side --rm --name ganache_side -v "$mntpoint:/app/db" \
trufflesuite/ganache-cli:latest \
-m "shrug dwarf easily blade trigger lucky reopen cage lake scatter desk boat" -i 33 -q --db /app/db
echo "Starting home test blockchain"
mntpoint=`pwd`/ganache_home_db
if [ ! -d ${mntpoint} ]; then
mkdir ${mntpoint}
mntpoint="$(pwd)/ganache_home_db"
if [ ! -d "$mntpoint" ]; then
mkdir "$mntpoint"
fi
docker kill ganache_home > /dev/null 2>&1 || true
docker network create blockchain_home > /dev/null 2>&1 || true
docker run -d --network blockchain_home --rm --name ganache_home -v ${mntpoint}:/app/db \
docker run -d --network blockchain_home --rm --name ganache_home -v "$mntpoint:/app/db" \
trufflesuite/ganache-cli:latest \
-m "shrug dwarf easily blade trigger lucky reopen cage lake scatter desk boat" -i 44 -q --db /app/db

View File

@ -6,6 +6,6 @@ COPY package.json /proxy/
RUN npm install
COPY index.js /proxy/
COPY index.js encode.js decode.js /proxy/
ENTRYPOINT ["node", "index.js"]

View File

@ -0,0 +1,90 @@
const BN = require('bn.js')
function parseBuffer (buffer, base = 10) {
return new BN(buffer).toString(base)
}
const keygenDecoders = [
// round 1
function (value) {
const res = {
e: {
n: parseBuffer(value.slice(0, 256))
},
com: parseBuffer(value.slice(256, 256 + 32), 16),
correct_key_proof: {
sigma_vec: []
}
}
for (let i = 256 + 32; i < value.length; i += 256) {
res.correct_key_proof.sigma_vec.push(parseBuffer(value.slice(i, i + 256)))
}
return JSON.stringify(res)
},
// round 2
function (value) {
const res = {
blind_factor: parseBuffer(value.slice(0, 32), 16),
y_i: {
x: parseBuffer(value.slice(32, 64), 16),
y: parseBuffer(value.slice(64, 96), 16)
}
}
return JSON.stringify(res)
},
// round 3
function (value) {
const res = {
ciphertext: [],
tag: []
}
for (let i = 0; i < 32; i++) {
res.ciphertext.push(value[i])
}
for (let i = 32; i < 48; i++) {
res.tag.push(value[i])
}
return JSON.stringify(res)
},
// round 4
function (value) {
const res = {
parameters: {
threshold: value[0],
share_count: value[1]
},
commitments: []
}
for (let i = 2; i < value.length; i += 64) {
res.commitments.push({
x: parseBuffer(value.slice(i, i + 32), 16),
y: parseBuffer(value.slice(i + 32, i + 64), 16),
})
}
return JSON.stringify(res)
},
// round 5
function (value) {
const res = {
pk: {
x: parseBuffer(value.slice(0, 32), 16),
y: parseBuffer(value.slice(32, 64), 16)
},
pk_t_rand_commitment: {
x: parseBuffer(value.slice(64, 96), 16),
y: parseBuffer(value.slice(96, 128), 16)
},
challenge_response: parseBuffer(value.slice(128, 160), 16)
}
return JSON.stringify(res)
}
]
module.exports = function (isKeygen, round, value) {
value = Buffer.from(value.substr(2), 'hex')
if (isKeygen) {
return keygenDecoders[parseInt(round[round.length - 1]) - 1](value)
}
}

View File

@ -0,0 +1,71 @@
const BN = require('bignumber.js')
function padZeros (s, len) {
while (s.length < len)
s = '0' + s
return s
}
function makeBuffer (value, length, base = 10) {
return Buffer.from(padZeros(new BN(value, base).toString(16), length * 2), 'hex')
}
const keygenEncoders = [
// round 1
function (value) {
const buffers = []
buffers.push(makeBuffer(value.e.n, 256))
buffers.push(makeBuffer(value.com, 32, 16))
for (let x of value.correct_key_proof.sigma_vec) {
buffers.push(makeBuffer(x, 256))
}
return Buffer.concat(buffers)
},
// round 2
function (value) {
const buffers = []
buffers.push(makeBuffer(value.blind_factor, 32, 16))
buffers.push(makeBuffer(value.y_i.x, 32, 16))
buffers.push(makeBuffer(value.y_i.y, 32, 16))
return Buffer.concat(buffers)
},
// round 3
function (value) {
const buffers = []
buffers.push(Buffer.from(value.ciphertext)) // 32 bytes
buffers.push(Buffer.from(value.tag)) // 16 bytes
return Buffer.concat(buffers)
},
// round 4
function (value) {
const buffers = []
buffers.push(Buffer.from([ value.parameters.threshold ])) // 1 byte
buffers.push(Buffer.from([ value.parameters.share_count ])) // 1 byte
for (let x of value.commitments) {
buffers.push(makeBuffer(x.x, 32, 16))
buffers.push(makeBuffer(x.y, 32, 16))
}
return Buffer.concat(buffers)
},
// round 5
function (value) {
const buffers = []
buffers.push(makeBuffer(value.pk.x, 32, 16))
buffers.push(makeBuffer(value.pk.y, 32, 16))
buffers.push(makeBuffer(value.pk_t_rand_commitment.x, 32, 16))
buffers.push(makeBuffer(value.pk_t_rand_commitment.y, 32, 16))
buffers.push(makeBuffer(value.challenge_response, 32, 16))
return Buffer.concat(buffers)
}
]
module.exports = function (isKeygen, round, value) {
const parsedValue = JSON.parse(value)
if (isKeygen) {
const encoded = keygenEncoders[parseInt(round[round.length - 1]) - 1](parsedValue)
console.log(`Raw data: ${value.length} bytes, encoded data: ${encoded.length} bytes`)
return encoded
}
}

View File

@ -6,6 +6,9 @@ const bech32 = require('bech32')
const axios = require('axios')
const BN = require('bignumber.js')
const encode = require('./encode')
const decode = require('./decode')
const {
HOME_RPC_URL, HOME_BRIDGE_ADDRESS, SIDE_RPC_URL, SIDE_SHARED_DB_ADDRESS, VALIDATOR_PRIVATE_KEY, HOME_CHAIN_ID,
SIDE_CHAIN_ID, HOME_TOKEN_ADDRESS, FOREIGN_URL, FOREIGN_ASSET
@ -91,9 +94,12 @@ async function get (req, res) {
const data = await sharedDb.methods.getData(from, sideWeb3.utils.sha3(uuid), key).call()
const result = homeWeb3.utils.hexToUtf8(data)
if (result.length)
res.send(Ok({ key: req.body.key, value: result }))
if (data.length > 2) {
console.log(data)
const decoded = decode(uuid[0] === 'k', round, data)
console.log(decoded)
res.send(Ok({ key: req.body.key, value: decoded }))
}
else {
setTimeout(() => res.send(Err(null)), 1000)
}
@ -108,7 +114,11 @@ async function set (req, res) {
const to = Number(req.body.key.fourth)
const key = homeWeb3.utils.sha3(`${round}_${to}`)
const query = sharedDb.methods.setData(sideWeb3.utils.sha3(uuid), key, sideWeb3.utils.utf8ToHex(req.body.value))
console.log(req.body.value)
const encoded = encode(uuid[0] === 'k', round, req.body.value)
console.log(encoded.toString('hex'))
const query = sharedDb.methods.setData(sideWeb3.utils.sha3(uuid), key, encoded)
await sideSendQuery(query)
res.send(Ok(null))
@ -299,7 +309,7 @@ async function voteRemoveValidator (req, res) {
async function info (req, res) {
console.log('Info start')
const [x, y, epoch, nextEpoch, threshold, nextThreshold, validators, nextValidators, homeBalance, status] = await Promise.all([
const [ x, y, epoch, nextEpoch, threshold, nextThreshold, validators, nextValidators, homeBalance, status ] = await Promise.all([
bridge.methods.getX().call().then(x => new BN(x).toString(16)),
bridge.methods.getY().call().then(x => new BN(x).toString(16)),
bridge.methods.epoch().call().then(x => x.toNumber()),
@ -335,7 +345,7 @@ async function transfer (req, res) {
const { hash, to, value } = req.body
if (homeWeb3.utils.isAddress(to)) {
console.log(`Calling transfer to ${to}, ${value} tokens`)
const query = bridge.methods.transfer(hash, to, '0x'+(new BN(value).toString(16)))
const query = bridge.methods.transfer(hash, to, '0x' + (new BN(value).toString(16)))
await homeSendQuery(query)
} else {
// return funds ?

View File

@ -7,6 +7,7 @@
"express": "4.17.1",
"async-lock": "1.2.0",
"axios": "0.19.0",
"bignumber.js": "9.0.0"
"bignumber.js": "9.0.0",
"bn.js": "5.0.0"
}
}

View File

@ -206,8 +206,11 @@ function sendTx (tx) {
.catch(err => {
if (err.response.data.message.includes('Tx already exists in cache'))
console.log('Tx already exists in cache')
else
else {
console.log(err.response)
console.log('Something failed, restarting')
return new Promise(resolve => setTimeout(() => resolve(sendTx(tx)), 1000))
}
})
}

View File

@ -14,14 +14,14 @@ async function main () {
let to = process.argv[2]
if (to == "bridge") {
if (to === "bridge") {
to = HOME_BRIDGE_ADDRESS
}
}
const amount = parseInt(process.argv[3])
let coins = process.argv[4]
if (amount != 0) {
if (amount !== 0) {
console.log(`Transfer from ${sender} to ${to}, ${amount} tokens`)
const query = token.methods.transfer(to, '0x'+(new BN(amount).toString(16)))