Merge pull request #32 from stakwork/esp-idf-432

Esp idf 432
This commit is contained in:
Evan Feenstra
2022-06-16 14:27:55 -07:00
committed by GitHub
20 changed files with 352 additions and 493 deletions

View File

@@ -14,7 +14,7 @@ Find the path to your `riscv32-esp-elf-gcc` binary within the `.embuild` dir:
### flash test
`espflash target/riscv32imc-esp-espidf/debug/sphinx-key`
`espflash target/riscv32imc-esp-espidf/debug/sphinx-key --monitor`
### build release
@@ -22,7 +22,7 @@ Find the path to your `riscv32-esp-elf-gcc` binary within the `.embuild` dir:
### flash release
`espflash target/riscv32imc-esp-espidf/release/sphinx-key`
`espflash target/riscv32imc-esp-espidf/release/sphinx-key --monitor`
### monitor
@@ -84,8 +84,17 @@ after pressing the ok button, restart the sphinx key, and wait for a MQTT connec
### espflash notes
espflash save-image esp32-c3 target/riscv32imc-esp-espidf/debug/sphinx-key ./asdf-blah
espflash save-image esp32-c3 target/riscv32imc-esp-espidf/release/sphinx-key ./test-flash
espflash board-info
export CC=$PWD/.embuild/espressif/tools/riscv32-esp-elf/esp-2021r2-8.4.0/riscv32-esp-elf/bin/riscv32-esp-elf-gcc
cargo +nightly build --release
esptool.py --chip esp32c3 elf2image target/riscv32imc-esp-espidf/release/sphinx-key
esptool.py --chip esp32c3 -p /dev/tty.usbserial-1420 -b 460800 --before=default_reset --after=hard_reset write_flash --flash_mode dio --flash_freq 40m --flash_size 4MB 0x10000 target/riscv32imc-esp-espidf/release/sphinx-key.bin
espmonitor /dev/tty.usbserial-1420

View File

@@ -60,10 +60,18 @@ fn main() -> anyhow::Result<()> {
run_test::run_test();
} else {
let (tx, rx) = mpsc::channel(1000);
let (status_tx, _status_rx) = mpsc::channel(1000);
let (status_tx, mut status_rx) = mpsc::channel(1000);
log::info!("=> start broker");
let _runtime = start_broker(rx, status_tx, "sphinx-1");
log::info!("=> wait for connected status");
// wait for connection = true
let status = status_rx.blocking_recv().expect("couldnt receive");
log::info!("=> connection status: {}", status);
assert_eq!(status, true, "expected connected = true");
// runtime.block_on(async {
init::blocking_connect(tx.clone());
log::info!("=====> sent seed!");
// listen to reqs from CLN
let conn = UnixConnection::new(parent_fd);
let client = UnixClient::new(conn);

View File

@@ -17,7 +17,7 @@ const PUB_TOPIC: &str = "sphinx";
const USERNAME: &str = "sphinx-key";
const PASSWORD: &str = "sphinx-key-pass";
// must get a reply within this time, or disconnects
const REPLY_TIMEOUT_MS: u64 = 1000;
const REPLY_TIMEOUT_MS: u64 = 10000;
static CONNECTED: SyncLazy<Mutex<bool>> = SyncLazy::new(|| Mutex::new(false));
fn set_connected(b: bool) {

View File

@@ -6,11 +6,10 @@ edition = "2018"
[dependencies]
sphinx-key-parser = { path = "../parser" }
vls-protocol-signer = { git = "https://gitlab.com/lightning-signer/validating-lightning-signer", default-features = false, features = ["secp-lowmemory"] }
# vls-protocol-signer = { path = "../../../evanf/validating-lightning-signer/vls-protocol-signer", default-features = false, features = ["std", "secp-lowmemory"] }
# vls-protocol-signer = { git = "https://gitlab.com/lightning-signer/validating-lightning-signer", default-features = false, features = ["secp-lowmemory"] }
vls-protocol-signer = { git = "https://gitlab.com/Evanfeenstra/validating-lightning-signer", branch = "std-signer", default-features = false, features = ["std", "secp-lowmemory"] }
anyhow = {version = "1", features = ["backtrace"]}
log = "0.4"
[patch.crates-io]
# Low-memory version of secp256k1 with static precomputation
secp256k1 = { git = "https://github.com/devrandom/rust-secp256k1.git", rev = "4e745ebe7e4c9cd0a7e9c8d5c42e989522e52f71" }

View File

@@ -1,13 +1,13 @@
use lightning_signer::persist::{DummyPersister, Persist};
use lightning_signer::Arc;
// use lightning_signer::Arc;
use sphinx_key_parser::MsgDriver;
use std::sync::Arc;
use vls_protocol::model::PubKey;
use vls_protocol::msgs::{self, read_serial_request_header, write_serial_response_header, Message};
use vls_protocol::serde_bolt::WireString;
use vls_protocol_signer::lightning_signer;
use vls_protocol_signer::vls_protocol;
pub use vls_protocol::model::PubKey;
pub use vls_protocol_signer::handler::{Handler, RootHandler};
use vls_protocol_signer::handler::{Handler, RootHandler};
pub use vls_protocol_signer::lightning_signer;
pub use vls_protocol_signer::vls_protocol;
pub struct InitResponse {
pub root_handler: RootHandler,
@@ -27,8 +27,11 @@ pub fn init(bytes: Vec<u8>) -> anyhow::Result<InitResponse> {
.iter()
.map(|s| from_wire_string(s))
.collect::<Vec<_>>();
log::info!("allowlist {:?}", allowlist);
let seed = init.dev_seed.as_ref().map(|s| s.0).expect("no seed");
log::info!("create root handler now");
let root_handler = RootHandler::new(0, Some(seed), persister, allowlist);
log::info!("root_handler created");
let init_reply = root_handler
.handle(Message::HsmdInit2(init))
.expect("handle init");

View File

@@ -24,11 +24,11 @@ rustflags = ["-C", "default-linker-libraries"]
[unstable]
build-std = ["std", "panic_abort"]
#build-std-features = ["panic_immediate_abort"] # Required for older ESP-IDF versions without a realpath implementation
build-std-features = ["panic_immediate_abort"] # Required for older ESP-IDF versions without a realpath implementation
[env]
# Note: these variables are not used when using pio builder
# Enables the esp-idf-sys "native" build feature (`cargo build --features native`) to build against ESP-IDF stable (v4.4)
ESP_IDF_VERSION = { value = "branch:release/v4.4" }
#ESP_IDF_VERSION = { value = "branch:release/v4.4" }
# Enables the esp-idf-sys "native" build feature (`cargo build --features native`) to build against ESP-IDF master (mainline)
#ESP_IDF_VERSION = { value = "master" }

4
sphinx-key/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
/.vscode
/.embuild
/target
/Cargo.lock

View File

@@ -19,8 +19,8 @@ pio = ["esp-idf-sys/pio"]
pingpong = []
[dependencies]
sphinx-key-signer = { path = "../signer", optional = true }
esp-idf-sys = { version = "0.31.5", features = ["binstart"] }
sphinx-key-signer = { path = "../signer", optional = true }
embedded-svc = { version = "0.21.2" }
esp-idf-svc = "0.41"
esp-idf-hal = "0.37"
@@ -39,3 +39,4 @@ anyhow = "1"
[[bin]]
name = "clear"
path = "src/clear.rs"

View File

@@ -1,191 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="description" content="sphinxkey" />
<meta charset="utf-8">
<title>Sphinx Key</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" type="image/x-icon" href="data:image/x-icon;,">
<style>
html {
font-family: Arial, Helvetica, sans-serif;
color: white;
font-size: 20px;
}
body{
padding:0;
background: #292a2d;
display: flex;
flex-direction: column;
align-items: center;
}
#logo{
margin-top:25px;
}
input {
margin-top:10px;
height:32px;
width:230px;
padding-left:15px;
border-radius: 16px;
}
button {
margin-top:20px;
height:40px;
width:108px;
color:white;
font-weight: bold;
border-radius: 20px;
background: #618AFF;
cursor: pointer;
}
button:disabled {
cursor:default;
background:grey;
}
@keyframes spin {
from {
transform:rotate(0deg);
}
to {
transform:rotate(360deg);
}
}
#button svg {
animation-name: spin;
animation-duration: 600ms;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
#loading {
display: none;
}
</style>
</head>
<body>
<svg id="logo" width="194px" height="186px" viewBox="0 0 194 186" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path fill="white" transform="translate(-508.000000, -189.000000)" stroke-width="1" d="M667.21,214.51 C658.045169,206.151145 647.39915,199.578356 635.82,195.13 C625.907772,191.21621 615.366017,189.139033 604.71,189 L604.64,189 C593.983983,189.139033 583.442228,191.21621 573.53,195.13 C561.95085,199.578356 551.304831,206.151145 542.14,214.51 C526.56,228.7 508,254.87 508,299.01 C508.002384,301.229806 509.18759,303.280098 511.11,304.39 C511.3,304.5 529.85,315.39 533.38,336.77 C535.8,351.44 545.74,362.71 562.12,369.36 C569.522132,372.317389 577.318819,374.170534 585.26,374.86 C586.972704,374.964831 588.652634,374.357474 589.902326,373.181627 C591.152018,372.00578 591.860447,370.36591 591.86,368.65 L591.86,324.52 C595.931833,325.717067 600.155885,326.316653 604.4,326.3 C608.837411,326.319158 613.252794,325.675389 617.5,324.39 L617.5,368.65 C617.5,370.299647 618.15532,371.881728 619.321796,373.048204 C620.488272,374.21468 622.070353,374.87 623.72,374.87 L624.1,374.87 C632.041181,374.180534 639.837868,372.327389 647.24,369.37 C663.6,362.72 673.54,351.45 676,336.77 C677.588215,327.719728 681.863657,319.357004 688.27,312.77 C691.228816,309.557963 694.589929,306.74135 698.27,304.39 C700.19241,303.280098 701.377616,301.229806 701.38,299.01 C701.34,254.87 682.78,228.7 667.21,214.51 Z M604.64,201.43 L604.71,201.43 C617.38,201.43 635.81,205.99 652.35,218.35 L641.43,239.24 L567.63,239.24 L556.93,218.4 C573.49,206 592,201.43 604.64,201.43 Z M545.65,334.77 C542.12,313.39 527.11,300.48 520.48,295.72 C521.29,261.14 534.75,239.52 547.28,226.83 L557.6,246.93 L557.65,273.15 C557.6448,282.683193 559.914304,292.08004 564.27,300.56 C567.824721,307.643965 573.02275,313.774622 579.43,318.44 L579.43,361.54 C568.77,359.48 548.7,353.22 545.65,334.77 Z M575.3,294.77 C571.858657,288.054866 570.069114,280.615578 570.08,273.07 L570.079951,251.64 L639,251.64 L638.81,272.13 C638.761448,279.909114 636.94573,287.575481 633.5,294.55 C629.09,303.34 620.5,313.83 604.44,313.83 C587.69,313.87 579,301.93 575.3,294.77 Z M663.69,334.77 C662,345.01 654.98,352.77 642.82,357.77 C638.655184,359.452348 634.334139,360.718515 629.92,361.55 L629.92,318.12 C636.158361,313.363256 641.179183,307.194329 644.57,300.12 C648.863933,291.449073 651.131029,281.915644 651.2,272.24 L651.43,246.92 L662,226.77 C674.55,239.45 688.06,261.08 688.87,295.77 C682.23,300.46 667.22,313.37 663.69,334.77 Z" id="Shape"></path>
</svg>
<p style="max-width:260px;text-align:center;margin-top:32px;">
Enter your WiFi credentials and MQTT Broker to connect you Sphinx Key
</p>
<input id="ssid" placeholder="WiFi SSID" />
<input id="pass" placeholder="Password" />
<input id="broker" placeholder="Broker" />
<button id="button" type="submit">
<svg id="loading" height="16" width="16" viewbox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
<path fill="white" stroke="grey" d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 0 0-94.3-139.9 437.71 437.71 0 0 0-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z" />
</svg>
<span style="margin:0 8px;">OK</span>
</button>
<p id="msg" style="max-width:260px;text-align:center;margin-top:32px;"></p>
</body>
<script>
function get(id){
return document.getElementById(id)
}
const params = getParams()
const button = get('button')
button.disabled = true
const ssid = get('ssid')
const pass = get('pass')
const broker = get('broker')
const loading = get('loading')
const msg = get('msg')
if(params['ssid']) {
ssid.value = params.ssid
}
if(params['pass']) {
pass.value = params.pass
}
if(params['broker']) {
broker.value = params.broker
}
function checker() {
if(ssid.value && broker.value && button.disabled) {
button.disabled = false
} else if(!ssid.value || !broker.value) {
button.disabled = true
}
}
ssid.onchange = function(){
checker()
}
ssid.oninput = function(){
checker()
}
broker.onchange = function(){
checker()
}
broker.oninput = function(){
checker()
}
button.onclick = function(e) {
fetchWithTimeout('/config?config=' +
encodeURIComponent(JSON.stringify({
ssid: ssid.value,
pass: pass.value || '',
broker: broker.value,
})), {
method:'POST',
timeout:3000,
})
.then(r=> r.json())
.then(finish)
.catch(e=> {
console.log(e)
msg.innerHTML = 'Failed to post configuration to the Sphinx Key'
})
}
async function finish(r) {
console.log("done!", r)
loading.style.display = 'inline-block'
button.disabled = true
await sleep(2000)
loading.style.display = 'none'
button.disabled = false
msg.innerHTML = 'Please unplug your Sphinx Key and plug it back in'
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
function getParams() {
const ps = new URLSearchParams(window.location.search);
const r = {};
for (const [k, v] of ps) {
r[k] = v;
}
return r;
}
async function fetchWithTimeout(resource, options = {}) {
const { timeout = 5000 } = options;
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeout);
const response = await fetch(resource, {
...options,
signal: controller.signal
});
clearTimeout(id);
return response;
}
</script>
</html>

115
sphinx-key/docs/README.md Normal file
View File

@@ -0,0 +1,115 @@
# sphinx_key
## Dev Containers
This repository offers Dev Containers supports for:
- [Gitpod](https://gitpod.io/)
- ["Open in Gitpod" button](https://www.gitpod.io/docs/getting-started#open-in-gitpod-button)
- [VS Code Dev Containers](https://code.visualstudio.com/docs/remote/containers#_quick-start-open-an-existing-folder-in-a-container)
- [GitHub Codespaces](https://docs.github.com/en/codespaces/developing-in-codespaces/creating-a-codespace)
> **Note**
>
> In order to use Gitpod the project needs to be published in a GitLab, GitHub,
> or Bitbucket repository.
>
> In [order to use GitHub Codespaces](https://github.com/features/codespaces#faq)
> the project needs to be published in a GitHub repository and the user needs
> to be part of the Codespaces beta or have the project under an organization.
If using VS Code or GitHub Codespaces, you can pull the image instead of building it
from the Dockerfile by selecting the `image` property instead of `build` in
`.devcontainer/devcontainer.json`.
When using Dev Containers, some tooling to facilitate building, flashing and
simulating in Wokwi is also added.
### Build
- Terminal approach:
```
scripts/build.sh [debug | release]
```
> If no argument is passed, `release` will be used as default
- UI approach:
The default build task is already set to build the project, and it can be used
in VS Code and Gitpod:
- From the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) (`Ctrl-Shift-P` or `Cmd-Shift-P`) run the `Tasks: Run Build Task` command.
- `Terminal`-> `Run Build Task` in the menu.
- With `Ctrl-Shift-B` or `Cmd-Shift-B`.
- From the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) (`Ctrl-Shift-P` or `Cmd-Shift-P`) run the `Tasks: Run Task` command and
select `Build`.
- From UI: Press `Build` on the left side of the Status Bar.
### Flash
> **Note**
>
> When using GitHub Codespaces, we need to make the ports
> public, [see instructions](https://docs.github.com/en/codespaces/developing-in-codespaces/forwarding-ports-in-your-codespace#sharing-a-port).
- Terminal approach:
- Using `flash.sh` script:
```
scripts/flash.sh [debug | release]
```
> If no argument is passed, `release` will be used as default
- UI approach:
- From the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) (`Ctrl-Shift-P` or `Cmd-Shift-P`) run the `Tasks: Run Task` command and
select `Build & Flash`.
- From UI: Press `Build & Flash` on the left side of the Status Bar.
- Any alternative flashing method from host machine.
### Wokwi Simulation
When using a custom Wokwi project, please change the `WOKWI_PROJECT_ID` in
`run-wokwi.sh`. If no project id is specified, a DevKit for esp32c3 will be
used.
> **Warning**
>
> ESP32-S3 is not available in Wokwi
- Terminal approach:
```
scripts/run-wokwi.sh [debug | release]
```
> If no argument is passed, `release` will be used as default
- UI approach:
The default test task is already set to build the project, and it can be used
in VS Code and Gitpod:
- From the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) (`Ctrl-Shift-P` or `Cmd-Shift-P`) run the `Tasks: Run Test Task` command
- With `Ctrl-Shift-,` or `Cmd-Shift-,`
> **Note**
>
> This Shortcut is not available in Gitpod by default.
- From the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) (`Ctrl-Shift-P` or `Cmd-Shift-P`) run the `Tasks: Run Task` command and
select `Build & Run Wokwi`.
- From UI: Press `Build & Run Wokwi` on the left side of the Status Bar.
> **Warning**
>
> The simulation will pause if the browser tab is in the background.This may
> affect the execution, specially when debuging.
#### Debuging with Wokwi
Wokwi offers debugging with GDB.
- Terminal approach:
```
$HOME/.espressif/tools/riscv32-esp-elf/esp-2021r2-patch3-8.4.0/riscv32-esp-elf/bin/riscv32-esp-elf-gdb target/riscv32imc-esp-espidf/debug/sphinx_key -ex "target remote localhost:9333"
```
> [Wokwi Blog: List of common GDB commands for debugging.](https://blog.wokwi.com/gdb-avr-arduino-cheatsheet/?utm_source=urish&utm_medium=blog)
- UI approach:
1. Run the Wokwi Simulation in `debug` profile
2. Go to `Run and Debug` section of the IDE (`Ctrl-Shift-D or Cmd-Shift-D`)
3. Start Debugging by pressing the Play Button or pressing `F5`
4. Choose the proper user:
- `esp` when using VS Code or GitHub Codespaces
- `gitpod` when using Gitpod

View File

@@ -1,212 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>HMQ CLIENT</title>
<link rel="stylesheet" href="https://unpkg.com/bulma@0.6.1/css/bulma.css">
<style>
body{
min-height: 100vh;
background: #232327;
}
.title{
color:#26b1b2;
}
</style>
</head>
<body>
<section id="app">
<section class="section">
<div class="container">
<h1 class="title">Connection
<small v-bind:class="{'has-text-danger': connection.error, 'has-text-grey': !connection.error}">{{ connection.state }}
<span v-if="connection.error">({{ connection.error }})</span>
</small>
</h1>
<div class="field is-grouped">
<p class="control">
<input class="input" v-model="username" placeholder="Username">
</p>
<p class="control">
<input class="input" v-model="password" placeholder="Password">
</p>
<p class="control">
<button class="button is-primary" v-on:click="mqtt.connect()" v-bind:disabled="connected">Connect</button>
</p>
<p class="control">
<button class="button" v-on:click="mqtt.disconnect()" v-bind:disabled="!connected">Disconnect</button>
</p>
</div>
</div>
</section>
<section class="section">
<div class="container">
<h1 class="title">Subscriptions</h1>
<div class="field is-grouped">
<p class="control">
<input class="input" v-model="subscribe.filter" placeholder="Topic">
</p>
<p class="control">
<input class="input" v-model="subscribe.qos" placeholder="QoS">
</p>
<p class="control">
<button class="button" v-on:click="mqtt.subscribe(subscribe.filter, subscribe.qos)" v-bind:disabled="!connected">Subscribe</button>
</p>
</div>
<ul>
<li v-for="(info, filter) in subscriptions" class="field is-grouped">
<div class="control">
<div class="tags has-addons">
<span class="tag">QoS</span>
<span class="tag is-dark">{{ info.qos }}</span>
</div>
</div>
<div class="control">
<div class="tags has-addons">
<span class="tag">Topic</span>
<span class="tag is-primary">{{ filter }}</span>
</div>
</div>
<a class="tag is-delete is-danger" v-on:click="mqtt.unsubscribe(filter)" v-bind:disabled="!connected"></a>
</li>
</ul>
</div>
</section>
<section class="section">
<div class="container">
<h1 class="title">Messages</h1>
<div class="field is-grouped">
<p class="control">
<input class="input" v-model="publish.topic" placeholder="Topic">
</p>
<p class="control">
<input class="input" v-model="publish.payload" placeholder="Payload">
</p>
<p class="control">
<button class="button" v-on:click="mqtt.publish(publish.topic, publish.payload)" v-bind:disabled="!connected">Publish</button>
</p>
</div>
<ul>
<li v-for="message in messages">
<code>{{ message.topic }}</code>:
<code>{{ message.payload }}</code>
</li>
</ul>
</div>
</section>
</section>
<script src="https://unpkg.com/paho-mqtt@1.1.0"></script>
<script src="https://unpkg.com/vue@2.5.9"></script>
<script>
const params = getParams()
const IP = params.ip || '52.91.253.115'
const PORT = params.port || 1888
console.log(IP, PORT)
var app = new Vue({
el: '#app',
created() {
var mqtt = new Paho.Client(IP, Number(PORT), "/ws", "client1");
mqtt.onConnectionLost = ({ errorCode, errorMessage }) => {
this.connection.state = 'disconnected';
this.connection.error = (errorCode === 0) ? '' : errorMessage;
}
mqtt.onMessageArrived = ({ payloadBytes, destinationName, qos }) => {
this.messages.unshift({
received: new Date(),
payload: String.fromCharCode.apply(String, payloadBytes),
payload_raw: payloadBytes,
topic: destinationName,
qos,
})
this.messages = this.messages.slice(0, 10)
},
this.mqtt = {
connect: () => {
this.connection.state = 'connecting';
this.connection.error = '';
console.log(this.username, this.password)
mqtt.connect({
userName: this.username || '',
password: this.password || '',
onSuccess: () => {
this.connection.state = 'connected';
},
onFailure: ({ errorCode, errorMessage }) => {
this.connection.state = 'connection failed';
this.connection.error = errorMessage;
},
});
},
disconnect: () => {
mqtt.disconnect();
this.subscriptions = {};
},
publish: (topic, payload) => {
console.log('publish',topic,payload)
mqtt.send(topic, payload);
},
subscribe: (filter, qos) => {
qos = parseInt(qos);
Vue.set(this.subscriptions, filter, {
state: 'subscribing',
qos,
})
mqtt.subscribe(filter, {
qos,
onSuccess: () => {
this.subscriptions[filter].state = 'subscribed';
}
});
},
unsubscribe: (filter) => {
if (this.subscriptions[filter]) {
this.subscriptions[filter].state = 'unsubscribing';
mqtt.unsubscribe(filter, {
onSuccess: () => {
Vue.delete(this.subscriptions, filter);
}
});
}
},
}
},
data: {
username: '',
password: '',
connection: {
state: 'idle',
error: '',
},
subscribe: {
filter: '',
qos: 0,
},
publish: {
topic: '',
payload: '',
},
subscriptions: {},
messages: [],
},
computed: {
connected() { return this.connection.state == 'connected'; },
}
});
function getParams() {
const ps = new URLSearchParams(window.location.search);
const r = {};
for (const [k, v] of ps) {
r[k] = v;
}
return r;
}
</script>
</body>
</html>

View File

@@ -1,3 +0,0 @@
cargo build --features pingpong
espflash target/riscv32imc-esp-espidf/debug/sphinx-key
espmonitor /dev/tty.usbserial-1420

24
sphinx-key/scripts/build.sh Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/bash
# Gitpod and VsCode Codespaces tasks do not source the user environment
if [ "${USER}" == "gitpod" ]; then
which idf.py >/dev/null || {
source ~/export-esp.sh > /dev/null 2>&1
}
elif [ "${CODESPACE_NAME}" != "" ]; then
which idf.py >/dev/null || {
source ~/export-esp.sh > /dev/null 2>&1
}
fi
case "$1" in
""|"release")
cargo build --release
;;
"debug")
cargo build
;;
*)
echo "Wrong argument. Only \"debug\"/\"release\" arguments are supported"
exit 1;;
esac

22
sphinx-key/scripts/flash.sh Executable file
View File

@@ -0,0 +1,22 @@
#!/usr/bin/env bash
set -e
BUILD_MODE=""
case "$1" in
""|"release")
bash scripts/build.sh
BUILD_MODE="release"
;;
"debug")
bash scripts/build.sh debug
BUILD_MODE="debug"
;;
*)
echo "Wrong argument. Only \"debug\"/\"release\" arguments are supported"
exit 1;;
esac
export ESP_ARCH=riscv32imc-esp-espidf
web-flash --chip esp32c3 target/${ESP_ARCH}/${BUILD_MODE}/sphinx-key

36
sphinx-key/scripts/run-wokwi.sh Executable file
View File

@@ -0,0 +1,36 @@
#!/usr/bin/env bash
set -e
BUILD_MODE=""
case "$1" in
""|"release")
bash scripts/build.sh
BUILD_MODE="release"
;;
"debug")
bash scripts/build.sh debug
BUILD_MODE="debug"
;;
*)
echo "Wrong argument. Only \"debug\"/\"release\" arguments are supported"
exit 1;;
esac
if [ "${USER}" == "gitpod" ];then
gp_url=$(gp url 9012)
echo "gp_url=${gp_url}"
export WOKWI_HOST=${gp_url:8}
elif [ "${CODESPACE_NAME}" != "" ];then
export WOKWI_HOST=${CODESPACE_NAME}-9012.githubpreview.dev
fi
export ESP_ARCH=riscv32imc-esp-espidf
# TODO: Update with your Wokwi Project
export WOKWI_PROJECT_ID=""
if [ "${WOKWI_PROJECT_ID}" == "" ]; then
wokwi-server --chip esp32c3 target/${ESP_ARCH}/${BUILD_MODE}/sphinx-key
else
wokwi-server --chip esp32c3 --id ${WOKWI_PROJECT_ID} target/${ESP_ARCH}/${BUILD_MODE}/sphinx-key
fi

View File

@@ -1,10 +1,10 @@
# Rust often needs a bit of an extra main task stack size compared to C (the default is 3K)
CONFIG_ESP_MAIN_TASK_STACK_SIZE=7000
CONFIG_ESP_MAIN_TASK_STACK_SIZE=24000
# Use this to set FreeRTOS kernel tick frequency to 1000 Hz (100 Hz by default).
# This allows to use 1 ms granuality for thread sleeps (10 ms by default).
#CONFIG_FREERTOS_HZ=1000
# Workaround for https://github.com/espressif/esp-idf/issues/7631
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=n
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=n
#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=n
#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=n

View File

@@ -1,16 +1,16 @@
use crate::core::events::Event as CoreEvent;
use embedded_svc::mqtt::client::utils::ConnState;
use embedded_svc::mqtt::client::{Connection, MessageImpl, QoS, Event, Message as MqttMessage};
use embedded_svc::mqtt::client::utils::Connection as MqttConnection;
use esp_idf_svc::mqtt::client::*;
use anyhow::Result;
use log::*;
use std::thread;
use esp_idf_sys::{self};
use esp_idf_sys::EspError;
use embedded_svc::mqtt::client::utils::ConnState;
use embedded_svc::mqtt::client::utils::Connection as MqttConnection;
use embedded_svc::mqtt::client::{Connection, Event, Message as MqttMessage, MessageImpl, QoS};
use esp_idf_hal::mutex::Condvar;
use std::sync::{mpsc};
use esp_idf_svc::mqtt::client::*;
use esp_idf_sys::EspError;
use esp_idf_sys::{self};
use log::*;
use std::sync::mpsc;
use std::thread;
pub const TOPIC: &str = "sphinx";
pub const RETURN_TOPIC: &str = "sphinx-return";
@@ -18,13 +18,17 @@ pub const USERNAME: &str = "sphinx-key";
pub const PASSWORD: &str = "sphinx-key-pass";
pub const QOS: QoS = QoS::AtMostOnce;
pub fn make_client(broker: &str, client_id: &str) -> Result<(
pub fn make_client(
broker: &str,
client_id: &str,
) -> Result<(
EspMqttClient<ConnState<MessageImpl, EspError>>,
MqttConnection<Condvar, MessageImpl, EspError>,
)> {
log::info!("make_client with id {}", client_id);
let conf = MqttClientConfiguration {
client_id: Some(client_id),
buffer_size: 2048,
buffer_size: 4096,
task_stack: 12288,
username: Some(USERNAME),
password: Some(PASSWORD),
@@ -47,39 +51,38 @@ pub fn start_listening(
mut connection: MqttConnection<Condvar, MessageImpl, EspError>,
tx: mpsc::Sender<CoreEvent>,
) -> Result<EspMqttClient<ConnState<MessageImpl, EspError>>> {
// must start pumping before subscribe or publish will not work
thread::spawn(move || {
info!("MQTT Listening for messages");
loop {
match connection.next() {
Some(msg) => {
match msg {
Some(msg) => match msg {
Err(e) => match e.to_string().as_ref() {
"ESP_FAIL" => {
error!("ESP_FAIL msg!");
},
}
_ => error!("Unknown error: {}", e),
},
Ok(msg) => {
match msg {
Ok(msg) => match msg {
Event::BeforeConnect => info!("RECEIVED BeforeConnect MESSAGE"),
Event::Connected(_flag) => {
info!("RECEIVED Connected MESSAGE");
tx.send(CoreEvent::Connected).expect("couldnt send Event::Connected");
},
tx.send(CoreEvent::Connected)
.expect("couldnt send Event::Connected");
}
Event::Disconnected => {
warn!("RECEIVED Disconnected MESSAGE");
tx.send(CoreEvent::Disconnected).expect("couldnt send Event::Disconnected");
},
tx.send(CoreEvent::Disconnected)
.expect("couldnt send Event::Disconnected");
}
Event::Subscribed(_mes_id) => info!("RECEIVED Subscribed MESSAGE"),
Event::Unsubscribed(_mes_id) => info!("RECEIVED Unsubscribed MESSAGE"),
Event::Published(_mes_id) => info!("RECEIVED Published MESSAGE"),
Event::Received(msg) => tx.send(CoreEvent::Message(msg.data().to_vec())).expect("couldnt send Event::Message"),
Event::Received(msg) => tx
.send(CoreEvent::Message(msg.data().to_vec()))
.expect("couldnt send Event::Message"),
Event::Deleted(_mes_id) => info!("RECEIVED Deleted MESSAGE"),
}
},
}
},
None => break,
}

View File

@@ -1,31 +1,49 @@
use crate::conn::mqtt::{RETURN_TOPIC, TOPIC, QOS};
use sphinx_key_signer::{self, InitResponse, PubKey};
use crate::conn::mqtt::{QOS, RETURN_TOPIC, TOPIC};
use sphinx_key_signer::vls_protocol::model::PubKey;
use sphinx_key_signer::{self, InitResponse};
use std::sync::mpsc;
use esp_idf_sys;
use embedded_svc::mqtt::client::Client;
use embedded_svc::httpd::Result;
use embedded_svc::mqtt::client::utils::ConnState;
use embedded_svc::mqtt::client::Client;
use embedded_svc::mqtt::client::{MessageImpl, Publish};
use esp_idf_svc::mqtt::client::*;
use esp_idf_sys;
use esp_idf_sys::EspError;
pub enum Event {
Connected,
Disconnected,
Message(Vec<u8>)
Message(Vec<u8>),
}
#[cfg(not(feature = "pingpong"))]
pub fn make_event_loop(mut mqtt: EspMqttClient<ConnState<MessageImpl, EspError>>, rx: mpsc::Receiver<Event>, do_log: bool) -> Result<()> {
pub fn make_event_loop(
mut mqtt: EspMqttClient<ConnState<MessageImpl, EspError>>,
rx: mpsc::Receiver<Event>,
do_log: bool,
) -> Result<()> {
// initialize the RootHandler
let root_handler = loop {
if let Ok(event) = rx.recv() {
if let Event::Message(msg_bytes) = event {
let InitResponse { root_handler, init_reply } = sphinx_key_signer::init(msg_bytes).expect("failed to init signer");
mqtt.publish(RETURN_TOPIC, QOS, false, init_reply).expect("could not publish init response");
break root_handler
match event {
Event::Connected => {
log::info!("SUBSCRIBE to {}", TOPIC);
mqtt.subscribe(TOPIC, QOS)
.expect("could not MQTT subscribe");
}
Event::Message(ref msg_bytes) => {
let InitResponse {
root_handler,
init_reply,
} = sphinx_key_signer::init(msg_bytes.clone()).expect("failed to init signer");
mqtt.publish(RETURN_TOPIC, QOS, false, init_reply)
.expect("could not publish init response");
break root_handler;
}
Event::Disconnected => {
log::info!("GOT an early Event::Disconnected msg!");
}
}
}
};
@@ -36,14 +54,22 @@ pub fn make_event_loop(mut mqtt: EspMqttClient<ConnState<MessageImpl, EspError>>
match event {
Event::Connected => {
log::info!("SUBSCRIBE TO {}", TOPIC);
mqtt.subscribe(TOPIC, QOS).expect("could not MQTT subscribe");
},
mqtt.subscribe(TOPIC, QOS)
.expect("could not MQTT subscribe");
}
Event::Message(ref msg_bytes) => {
let _ret = match sphinx_key_signer::handle(&root_handler, msg_bytes.clone(), dummy_peer.clone(), do_log) {
Ok(b) => mqtt.publish(RETURN_TOPIC, QOS, false, b).expect("could not publish init response"),
let _ret = match sphinx_key_signer::handle(
&root_handler,
msg_bytes.clone(),
dummy_peer.clone(),
do_log,
) {
Ok(b) => mqtt
.publish(RETURN_TOPIC, QOS, false, b)
.expect("could not publish init response"),
Err(e) => panic!("HANDLE FAILED {:?}", e),
};
},
}
Event::Disconnected => {
log::info!("GOT A Event::Disconnected msg!");
}
@@ -54,22 +80,27 @@ pub fn make_event_loop(mut mqtt: EspMqttClient<ConnState<MessageImpl, EspError>>
}
#[cfg(feature = "pingpong")]
pub fn make_event_loop(mut mqtt: EspMqttClient<ConnState<MessageImpl, EspError>>, rx: mpsc::Receiver<Event>, do_log: bool) -> Result<()> {
pub fn make_event_loop(
mut mqtt: EspMqttClient<ConnState<MessageImpl, EspError>>,
rx: mpsc::Receiver<Event>,
do_log: bool,
) -> Result<()> {
log::info!("About to subscribe to the mpsc channel");
while let Ok(event) = rx.recv() {
match event {
Event::Connected => {
log::info!("SUBSCRIBE TO {}", TOPIC);
mqtt.subscribe(TOPIC, QOS).expect("could not MQTT subscribe");
},
mqtt.subscribe(TOPIC, QOS)
.expect("could not MQTT subscribe");
}
Event::Message(msg_bytes) => {
let b = sphinx_key_signer::parse_ping_and_form_response(msg_bytes);
if do_log {
log::info!("GOT A PING MESSAGE! returning pong now...");
}
mqtt.publish(RETURN_TOPIC, QOS, false, b).expect("could not publish ping response");
},
mqtt.publish(RETURN_TOPIC, QOS, false, b)
.expect("could not publish ping response");
}
Event::Disconnected => {
log::info!("GOT A Event::Disconnected msg!");
}

9
sphinx-key/src/test.rs Normal file
View File

@@ -0,0 +1,9 @@
use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported
fn main() {
// Temporary. Will disappear once ESP-IDF 4.4 is released, but for now it is necessary to call this function once,
// or else some patches to the runtime implemented by esp-idf-sys might not link properly.
esp_idf_sys::link_patches();
println!("Hello, world!");
}

View File

@@ -2,7 +2,8 @@ use sphinx_key_parser as parser;
use clap::{App, AppSettings, Arg};
use rumqttc::{self, AsyncClient, Event, MqttOptions, Packet, QoS};
use sphinx_key_signer::{self, InitResponse, PubKey};
use sphinx_key_signer::{self, InitResponse};
use sphinx_key_signer::vls_protocol::model::PubKey;
use std::error::Error;
use std::time::Duration;
use vls_protocol::msgs;