-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from bigmarh/sim-ln-js
Added the ability to generate executables so that users will not need to have nodejs to run. But it also provides flexibility to build from source.
- Loading branch information
Showing
215 changed files
with
183,475 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,6 @@ | ||
/target | ||
*/config.json | ||
node_modules | ||
config.json | ||
package-lock.json | ||
activity-generator/releases/* | ||
.DS_Store |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
export const DefaultConfig = { | ||
"HIGH_VOLUME_TRANSACTIONS": { | ||
name: "High Volume Keysend Payments", | ||
frequency: 5, | ||
amount: 100000, | ||
action: "keysend" | ||
}, | ||
"LOW_VOLUME_TRANSACTIONS": { | ||
name: "Low Volume Keysend Payments", | ||
frequency: 5, | ||
amount: 100, | ||
action: "keysend" | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
#! /usr/bin/env node | ||
|
||
|
||
import LndGrpc from 'lnd-grpc'; | ||
import fs from 'fs'; | ||
import path from 'path'; | ||
import { program } from 'commander'; | ||
import { select, input, confirm } from '@inquirer/prompts'; | ||
import { v4 } from 'uuid'; | ||
import { parse } from 'json2csv'; | ||
import { getFrequency, getAmountInSats, verifyPubKey } from './validation/inputGetters.js'; | ||
import { DefaultConfig } from './default_activities_config.js'; | ||
program.requiredOption('--config <file>'); | ||
program.option('--csv'); | ||
program.parse(); | ||
|
||
const options = program.opts(); | ||
const configFile = options.config; | ||
|
||
// Blocking example with fs.readFileSync | ||
const fileName = configFile; | ||
const config = JSON.parse(fs.readFileSync(fileName, 'utf-8')); | ||
let nodeObj = {}; | ||
const controlNodes = config.nodes.map(node => node); | ||
|
||
|
||
|
||
console.log(`Setting up ${config.nodes.length} Controlled Nodes...`) | ||
async function buildControlNodes() { | ||
if (!controlNodes.length) return promptForActivities(); | ||
|
||
let node = controlNodes.shift() | ||
const grpc = new LndGrpc({ | ||
host: node.ip, | ||
cert: node.cert, | ||
macaroon: node.macaroon, | ||
protoDir:path.join(__dirname,"proto") | ||
}) | ||
|
||
grpc.connect(); | ||
(async function() { | ||
|
||
const { WalletUnlocker, Lightning } = grpc.services | ||
// Do something cool if we detect that the wallet is locked. | ||
grpc.on(`connected`, () => console.log('wallet connected!')) | ||
// Do something cool if we detect that the wallet is locked. | ||
grpc.on(`locked`, async () => { | ||
await grpc.activateLightning() | ||
}) | ||
|
||
// Do something cool when the wallet gets unlocked. | ||
grpc.on(`active`, async () => { | ||
const current_node = await Lightning.getInfo(); | ||
const nodeGraph = await Lightning.describeGraph(); | ||
|
||
if (nodeGraph.nodes < 1) { | ||
console.log(`Node: ${node.alias} has no graph`) | ||
return console.error("Please check that controlled nodes have open channels to other nodes") | ||
} | ||
|
||
//dump graph information | ||
nodeObj[current_node.identity_pubkey] = current_node; | ||
nodeObj[current_node.identity_pubkey].graph = nodeGraph; | ||
node.id = current_node.identity_pubkey; | ||
|
||
//create array of possible destintations for node | ||
nodeObj[current_node.identity_pubkey].possible_dests = nodeGraph.nodes.filter((n) => { | ||
return n.pub_key != current_node.identity_pubkey | ||
}) | ||
grpc.disconnect() | ||
}) | ||
// Do something cool when the connection gets disconnected. | ||
grpc.on(`disconnected`, () => { | ||
|
||
if (Object.keys(nodeObj).length == config.nodes.length) promptForActivities(); | ||
else buildControlNodes(); | ||
}) | ||
|
||
|
||
})() | ||
|
||
} | ||
|
||
buildControlNodes(); | ||
|
||
let activities = []; | ||
async function promptForActivities() { | ||
|
||
console.log("\nCreate a New Activity"); | ||
console.log("_________________________________\n"); | ||
let activity = {}; | ||
activity.uuid = v4(); | ||
|
||
const predefinedActivity = await select({ | ||
message: " \n", | ||
choices: [ | ||
{name: "Select a predefined activity", value: true}, | ||
{name: "Manually create an activity", value: false} | ||
] | ||
}) | ||
|
||
if (predefinedActivity) { | ||
const selectedPredefinedActivity = await select({ | ||
message: " \n", | ||
choices: Object.keys(DefaultConfig).map((config) => { | ||
return { | ||
name: DefaultConfig[config].name, | ||
value: config | ||
} | ||
}) | ||
}) | ||
activity.freq = DefaultConfig[selectedPredefinedActivity].frequency | ||
activity.amt = DefaultConfig[selectedPredefinedActivity].amount | ||
activity.action = DefaultConfig[selectedPredefinedActivity].action | ||
activity.src = Object.values(nodeObj)[Math.floor(Math.random() * Object.values(nodeObj).length)].identity_pubkey | ||
activity.dest = nodeObj[activity.src].possible_dests[Math.floor(Math.random() * nodeObj[activity.src].possible_dests.length)].pub_key | ||
} else { | ||
let sourceArray = [{ | ||
name: '(choose random)', | ||
value: Object.values(nodeObj)[Math.floor(Math.random() * Object.values(nodeObj).length)].identity_pubkey | ||
}, { | ||
name: '(input pubkey)', | ||
value: false | ||
}] | ||
|
||
activity.src = await select({ | ||
message: "Choose a source? \n", | ||
choices: sourceArray.concat(Object.keys(nodeObj).map(key => { | ||
let node = nodeObj[key]; | ||
return { | ||
name: `${node.alias}: (${node.identity_pubkey})`, | ||
value: node.identity_pubkey | ||
} | ||
})) | ||
}) | ||
|
||
if (!activity.src) { | ||
activity.src = await input({ message: 'Enter pubkey:' }); | ||
} | ||
|
||
let destArray = [{ | ||
name: `(choose random)`, | ||
value: nodeObj[activity.src].possible_dests[Math.floor(Math.random() * nodeObj[activity.src].possible_dests.length)].pub_key | ||
}, { | ||
name: '(input pubkey)', | ||
value: false | ||
}] | ||
|
||
activity.dest = await select({ | ||
message: "Choose a destination? \n", | ||
choices: destArray.concat(nodeObj[activity.src].possible_dests.map(dest => { | ||
return { | ||
name: `${dest.alias}: (${dest.pub_key})`, | ||
value: dest.pub_key | ||
} | ||
})) | ||
|
||
}) | ||
|
||
if (!activity.dest) { | ||
const singleNodeGraph = Object.values(nodeObj).find((node) => { | ||
return node.graph.nodes | ||
}).graph | ||
|
||
const allPossibleNodes = singleNodeGraph.nodes.map((node) => node.pub_key) | ||
activity.dest = await verifyPubKey(allPossibleNodes) | ||
} | ||
|
||
activity.action = await input({ message: 'What action?', default: "keysend" }); | ||
|
||
activity.frequency = await getFrequency() | ||
activity.amount = await getAmountInSats() | ||
} | ||
|
||
activities.push(activity); | ||
|
||
console.log( | ||
`\n------------------------\nCreated: ${activity.uuid}\nTotal activities: ${activities.length}\n------------------------\n` | ||
) | ||
|
||
const anotherOne = await confirm({ message: 'Create another one?', default: false }); | ||
if (anotherOne) { | ||
promptForActivities(); | ||
} else { | ||
if (options.csv) activities = parse(activities, { header: true }); | ||
config.activity = activities; | ||
console.log(config); | ||
} | ||
} |
80 changes: 80 additions & 0 deletions
80
activity-generator/bin/proto/0.10.0-beta/autopilotrpc/autopilot.proto
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
syntax = "proto3"; | ||
|
||
package autopilotrpc; | ||
|
||
option go_package = "github.com/lightningnetwork/lnd/lnrpc/autopilotrpc"; | ||
|
||
// Autopilot is a service that can be used to get information about the current | ||
// state of the daemon's autopilot agent, and also supply it with information | ||
// that can be used when deciding where to open channels. | ||
service Autopilot { | ||
/** | ||
Status returns whether the daemon's autopilot agent is active. | ||
*/ | ||
rpc Status (StatusRequest) returns (StatusResponse); | ||
|
||
/** | ||
ModifyStatus is used to modify the status of the autopilot agent, like | ||
enabling or disabling it. | ||
*/ | ||
rpc ModifyStatus (ModifyStatusRequest) returns (ModifyStatusResponse); | ||
|
||
/** | ||
QueryScores queries all available autopilot heuristics, in addition to any | ||
active combination of these heruristics, for the scores they would give to | ||
the given nodes. | ||
*/ | ||
rpc QueryScores (QueryScoresRequest) returns (QueryScoresResponse); | ||
|
||
/** | ||
SetScores attempts to set the scores used by the running autopilot agent, | ||
if the external scoring heuristic is enabled. | ||
*/ | ||
rpc SetScores (SetScoresRequest) returns (SetScoresResponse); | ||
} | ||
|
||
message StatusRequest { | ||
} | ||
|
||
message StatusResponse { | ||
/// Indicates whether the autopilot is active or not. | ||
bool active = 1; | ||
} | ||
|
||
message ModifyStatusRequest { | ||
/// Whether the autopilot agent should be enabled or not. | ||
bool enable = 1; | ||
} | ||
|
||
message ModifyStatusResponse { | ||
} | ||
|
||
message QueryScoresRequest { | ||
repeated string pubkeys = 1; | ||
|
||
/// If set, we will ignore the local channel state when calculating scores. | ||
bool ignore_local_state = 2; | ||
} | ||
|
||
message QueryScoresResponse { | ||
message HeuristicResult { | ||
string heuristic = 1; | ||
map<string, double> scores = 2; | ||
} | ||
|
||
repeated HeuristicResult results = 1; | ||
} | ||
|
||
message SetScoresRequest { | ||
/// The name of the heuristic to provide scores to. | ||
string heuristic = 1; | ||
|
||
/** | ||
A map from hex-encoded public keys to scores. Scores must be in the range | ||
[0.0, 1.0]. | ||
*/ | ||
map<string, double> scores = 2; | ||
} | ||
|
||
message SetScoresResponse { | ||
} |
Oops, something went wrong.