Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add datastruct #3

Merged
merged 5 commits into from
Jun 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion config.sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ data_sig:
tlv_key: 293345193 # replace with desired TLV key to insert DataSig structure into

data_struct:
tlv_key: 293345191 # replace with desired TLV key to insert DataStruct structure into
tlv_key: 293345191 # replace with desired TLV key to insert DataStruct structure into
max_fragment_size: 1024 # replace with desired maximum size per fragment
min_fragment_size: 512 # replace with desired minimum size per fragment
36 changes: 23 additions & 13 deletions src/handle-command.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
const { randomBytes } = require('crypto')
const { sendDataToAddress } = require('./write-sats')
const {
sendDataToAddress,
setDestinationAddress,
getDestinationAddress } = require('./write-sats')
const { encodeDataSig, decodeDataSig } = require('./utils/data-sig/data-sig')
const { encodeDataStruct, decodeDataStruct, dataToDataStructArray } = require('./utils/data-struct/data-struct')

let handlers = {}

Expand All @@ -11,25 +15,31 @@ const commandHandler = (line) => {
handlers[args[0]](args)
}

handlers['speak'] = (args) => {
if (args.length < 3) {
console.log('Too few arguments')
handlers['set'] = (args) => {
if (args.length < 2) {
console.log('Specify address')
return
}
sendDataToAddress(args[1], Buffer.from(args[2], 'utf-8'))
setDestinationAddress(args[1])
}

handlers['sig'] = (args) => {
encodeDataSig({
version: 1,
sig: randomBytes(32)
})
.then((res) => decodeDataSig(res))
.then((ob) => console.log(ob))
handlers['speak'] = (args) => {
if (args.length < 2) {
console.log('Specify data')
return
}
const dataStructs = dataToDataStructArray(Buffer.from(args[1], 'utf-8'))

dataStructs.forEach(
(dataStruct) => {
encodeDataStruct(dataStruct)
.then((buf) => {
sendDataToAddress(getDestinationAddress(), buf)
})
}
)
}


module.exports = {
commandHandler
}
15 changes: 3 additions & 12 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
const readline = require('readline');
const configLoader = require('./config/config-loader')

const { handleReceivedRecords } = require('./listen-sats')
const { defaultListenHandler } = require('./utils/default-listen-handler')
const { commandHandler } = require('./handle-command')

const config = configLoader.getConfig()

const listenHandler = (records) => {
for (const key in records) {
if (Number(key) == Number(config.data_struct.tlv_key)) {
console.log(records[key].toString('utf-8'))
}
}
}

handleReceivedRecords(listenHandler)
handleReceivedRecords(defaultListenHandler)

const rl = readline.createInterface({
input: process.stdin,
Expand Down
30 changes: 27 additions & 3 deletions src/utils/data-sig/data-sig.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const { signer } = require('../../lnd-rpc/signer')
const { getMyAddress } = require('../../utils/generic')
var protobuf = require("protobufjs")

const generateDataSig = (version, data, destinationAddress, senderAddress) => {
Expand All @@ -15,7 +16,7 @@ const generateDataSig = (version, data, destinationAddress, senderAddress) => {
let request = {
msg: destDataBuffer,
double_hash: false,
compact_sig: true,
compact_sig: false,
key_loc: {
key_family: 6,
key_index: 0
Expand All @@ -32,7 +33,7 @@ const generateDataSig = (version, data, destinationAddress, senderAddress) => {
}
if (senderAddress !== undefined
&& typeof senderAddress == 'string') {
dataSig['senderPK'] = senderAddress
dataSig['senderPK'] = Buffer.from(senderAddress, 'hex')
}
resolve(dataSig)
}
Expand Down Expand Up @@ -81,9 +82,32 @@ const decodeDataSig = (dataSigBuffer) => {
})
}

const verifyDataSig = (dataSigBuf, dataBuf) => {
return new Promise(async function (resolve, reject) {
const dataSig = await decodeDataSig(dataSigBuf)

const myAddr = await getMyAddress()
const myAddrBuf = Buffer.from(myAddr, 'hex')

const destDataBuf = Buffer.concat([myAddrBuf, dataBuf])

let request = {
msg: destDataBuf,
signature: dataSig.sig,
pubkey: dataSig.senderPK
};

signer.verifyMessage(request, function (err, response) {
if(err) reject(err)
if(response) resolve(response.valid)
});
})
}


module.exports = {
encodeDataSig,
decodeDataSig,
generateDataSig
generateDataSig,
verifyDataSig
}
87 changes: 87 additions & 0 deletions src/utils/data-struct/data-struct.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
const configLoader = require('../../config/config-loader')

const config = configLoader.getConfig()

var protobuf = require("protobufjs")

const DATA_STRUCT_VERSION = 1

const dataToDataStructArray = (dataBuffer) => {
const totalSize = dataBuffer.length
const fragmentationId = Math.floor(Math.random() * Math.pow(10, 9));
const fragmentSize = config.data_struct.max_fragment_bytes

let fragmentCount = Math.floor(dataBuffer.length / fragmentSize)
if (dataBuffer.length % fragmentSize !== 0) {
fragmentCount++
}

let dataStructArray = []

for (var i = 0; i < fragmentCount; i++) {
let tempBuf
if (i == (fragmentCount - 1)) {
tempBuf = dataBuffer.subarray(i * fragmentSize, totalSize)
} else {
tempBuf = dataBuffer.subarray(i * fragmentSize, (i + 1) * fragmentSize)
}

dataStructArray.push(
{
version: DATA_STRUCT_VERSION,
payload: tempBuf,
fragment: {
fragmentationId: fragmentationId,
totalSize: totalSize,
offset: (i * fragmentSize)
}
}
)
}

return dataStructArray
}

const encodeDataStruct = (dataStruct) => {
return new Promise(function (resolve, reject) {
protobuf.load(__dirname + '/data-struct.proto', function (err, root) {
if (err)
reject(err);

var DataStructMessage = root.lookupType("datastruct.DataStruct");

var errMsg = DataStructMessage.verify(dataStruct);
if (errMsg)
reject(Error(errMsg));

var message = DataStructMessage.create(dataStruct);

var buffer = DataStructMessage.encode(message).finish();

resolve(buffer)
})
})
}

const decodeDataStruct = (dataStructBuffer) => {
return new Promise(function (resolve, reject) {
protobuf.load(__dirname + '/data-struct.proto', function (err, root) {
if (err)
reject(err);

var DataStructMessage = root.lookupType("datastruct.DataStruct");

var message = DataStructMessage.decode(dataStructBuffer);
console.log('Received Message:', message)
var object = DataStructMessage.toObject(message);

resolve(object)
});
})
}

module.exports = {
encodeDataStruct,
decodeDataStruct,
dataToDataStructArray
}
14 changes: 14 additions & 0 deletions src/utils/data-struct/data-struct.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package datastruct;
syntax = "proto3";

message DataStruct {
uint32 version = 1;
bytes payload = 2;
FragmentInfo fragment = 3;
}

message FragmentInfo {
uint32 fragmentation_id = 1;
uint32 total_size = 2;
uint32 offset = 3;
}
28 changes: 28 additions & 0 deletions src/utils/default-listen-handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const configLoader = require('../config/config-loader')
const { verifyDataSig } = require('./data-sig/data-sig')
const { signer } = require('../lnd-rpc/signer')
const { lightning } = require('../lnd-rpc/lightning')
const config = configLoader.getConfig()

const defaultListenHandler = async (records) => {
let dataSigBuf
let dataStructBuf
for (const key in records) {
if (Number(key) == Number(config.data_struct.tlv_key)) {
dataStructBuf = records[key]
}
if (Number(key) == Number(config.data_sig.tlv_key)) {
dataSigBuf = records[key]
}
}

const valid = await verifyDataSig(dataSigBuf, dataStructBuf)
if (!valid) return
console.log("DataSig Verified Data Received: ")
console.log(config.data_struct.tlv_key, ':', dataStructBuf)

}

module.exports = {
defaultListenHandler
}
19 changes: 19 additions & 0 deletions src/utils/generic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const { lightning } = require('../lnd-rpc/lightning');

let myAddress = ""

const getMyAddress = () => {
return new Promise(function(resolve, reject) {
if (myAddress != "") {
resolve(myAddress)
}
lightning.getInfo({}, function (err, response) {
if(err) reject(err)
if(response) resolve(response.identity_pubkey)
});
})
}

module.exports = {
getMyAddress
}
31 changes: 25 additions & 6 deletions src/write-sats.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
const { router } = require('./lnd-rpc/router')
const { lightning } = require('./lnd-rpc/lightning');
const { randomBytes, createHash } = require('crypto')
const configLoader = require('./config/config-loader')

const { getMyAddress } = require('./utils/generic')
const { generateDataSig, encodeDataSig } = require('./utils/data-sig/data-sig')

const config = configLoader.getConfig()

const PREIMAGE_TLV_KEY = 5482373484

let destinationAddress = ""

const setDestinationAddress = (addr) => {
destinationAddress = addr
}

const getDestinationAddress = () => {
return destinationAddress
}

const sendPayment = (address, dataBuffer, dataSigBuffer) => {
const preimage = randomBytes(32)
const hash = createHash('sha256').update(preimage).digest()
Expand All @@ -17,7 +29,7 @@ const sendPayment = (address, dataBuffer, dataSigBuffer) => {
const sigKey = Number(config.data_sig.tlv_key)

let records = {}
records[5482373484] = preimage
records[PREIMAGE_TLV_KEY] = preimage
records[dataKey] = dataBuffer
if (dataSigBuffer !== undefined
&& Buffer.isBuffer(dataSigBuffer)) {
Expand All @@ -36,7 +48,11 @@ const sendPayment = (address, dataBuffer, dataSigBuffer) => {
let call = router.sendPaymentV2(request);
call.on('data', function (response) {
// A response was received from the server.
console.log(response);
if (response.status === 'SUCCEEDED') {
console.log("Fragment sent for", response.value_sat, "sat(s)");
console.log("\tDataSig sent over TLV:\t\t", sigKey)
console.log("\tDataStruct sent over TLV:\t", dataKey)
}
});
call.on('error', function (err) {
console.error(err)
Expand All @@ -49,8 +65,9 @@ const sendPayment = (address, dataBuffer, dataSigBuffer) => {
});
}

const sendDataToAddress = (address, data) => {
generateDataSig(1, data, address, undefined)
const sendDataToAddress = async (address, data) => {
myAddress = await getMyAddress()
generateDataSig(1, data, address, myAddress)
.then((res) => encodeDataSig(res))
.then((sigBuf) => sendPayment(
address,
Expand All @@ -60,5 +77,7 @@ const sendDataToAddress = (address, data) => {
}

module.exports = {
sendDataToAddress
sendDataToAddress,
setDestinationAddress,
getDestinationAddress
}