Skip to content

Commit d8bedec

Browse files
authored
SpacesVM (#73)
* change name to spacesvm-rs Signed-off-by: Sam Batschelet <[email protected]>
1 parent 15678d2 commit d8bedec

38 files changed

+350
-232
lines changed

.github/workflows/test-and-release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,9 @@ jobs:
114114
uses: actions-rs/cargo@v1
115115
with:
116116
command: build
117-
args: --release --bin mini-kvvm
117+
args: --release --bin spacesvm
118118
- name: Run e2e tests
119-
run: VM_PLUGIN_PATH=/home/runner/work/mini-kvvm-rs/mini-kvvm-rs/target/release/mini-kvvm scripts/tests.e2e.sh
119+
run: VM_PLUGIN_PATH=/home/runner/work/spacesvm-rs/spacesvm-rs/target/release/spacesvm scripts/tests.e2e.sh
120120

121121
release:
122122
name: Release ${{ matrix.job.target }} (${{ matrix.job.os }})

.gitmodules

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +0,0 @@
1-
[submodule "proto/protos/avalanchego"]
2-
path = crates/avalanche-proto/protos/avalanchego
3-
url = https://github.com/ava-labs/avalanchego.git

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
[workspace]
22
members = [
3-
"mini-kvvm",
3+
"spacesvm",
44
"tests/e2e",
5-
"cli",
5+
"spaces-cli",
66
]
77

88
[patch.crates-io]

README.md

Lines changed: 124 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,132 @@
1+
[<img alt="crates.io" src="https://img.shields.io/crates/v/spacesvm.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/spacesvm)
2+
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-spacesvm-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/spacesvm)
3+
![Github Actions](https://github.com/ava-labs/spacesvm-rs/actions/workflows/test-and-release.yml/badge.svg)
14

2-
![Github Actions](https://github.com/ava-labs/mini-kvvm-rs/actions/workflows/test-and-release.yml/badge.svg)
5+
# `spacesvm-rs`
36

4-
# mini-kvvm-rs
7+
### status: experimental
58

6-
Mini key-value store VM in Rust for Avalanche
9+
`spacesvm-rs` is a (EIP-712)[https://eips.ethereum.org/EIPS/eip-712] compatible Rust port of the (SpacesVm)[https://github.com/ava-labs/spacesvm] virtual machine using the Avalanche [Rust SDK](https://github.com/ava-labs/avalanche-types-rs). Although the goal is to achieve feature parity with its Golang counterpart, it is not yet compatible with the existing spaces network.
710

8-
## Rust Version
11+
## Core features
12+
### Authentication
13+
Any mutations to the key space require the signature of the owner.
14+
### EIP-712 Compatibility
15+
Typed structured data hashing and signing.
916

10-
`mini-kvvm-rs` currently works on Rust `1.60+` and requires support for the `2021` edition.
17+
## Current Functionality
18+
### Claim
19+
Interacting with the SpacesVM starts with a `ClaimTx`. This reserves your own
20+
"space" and associates your address with it (so that only you can make changes
21+
to it and/or the keys in it).
1122

23+
### Set/Delete
24+
Once you have a space, you can then use `SetTx` and `DeleteTx` actions to
25+
add/modify/delete keys in it.
26+
27+
### Resolve
28+
When you want to view data stored in SpacesVM, you call `Resolve` on the value
29+
path: `<space>/<key>`. If you stored a file at a particular path, use this
30+
command to retrieve it: `spaces-cli resolve-file <path> <destination
31+
filepath>`.
32+
33+
#### Getting Started
34+
The easiest way to test and interact with spacesvm is with the included e2e scripts.
35+
36+
```bash
37+
# build the spacesvm plugin, run e2e tests, and keep the network running
38+
./scripts/build.release.sh \
39+
&& VM_PLUGIN_PATH=$(pwd)/target/release/spacesvm \
40+
./scripts/tests.e2e.sh
41+
42+
# or, specify the custom avalanchego binary
43+
./scripts/build.release.sh \
44+
&& VM_PLUGIN_PATH=$(pwd)/target/release/spacesvm \
45+
./scripts/tests.e2e.sh ~/go/src/github.com/ava-labs/avalanchego/build/avalanchego
46+
47+
# (optional) set NETWORK_RUNNER_ENABLE_SHUTDOWN=1 in "tests.e2e.sh"
48+
# to shut down the network afterwards
49+
```
50+
#### Compile from source.
51+
52+
```bash
53+
cargo build \
54+
--release \
55+
--bin spacesvm
56+
57+
./target/release/spaces-vm
58+
```
59+
60+
```bash
61+
cargo build \
62+
--release \
63+
--bin spaces-cli
64+
65+
./target/release/spaces-cli
66+
67+
```
68+
69+
To test `spacesvm` APIs, try the following commands with the CLI or shell commands:
1270
```bash
13-
cd ${HOME}/go/src/github.com/ava-labs/subnet-cli
14-
go install -v .
15-
subnet-cli create VMID minikvvmrs
16-
# qBnAKUQ2mxjMHCneWjq5nFuhntoWrsKsCjaYSouFjpuCB2o5d
17-
18-
cd ${HOME}/mini-kvvm-rs
19-
./scripts/build.x86_64-linux-musl.sh
20-
cp \
21-
./target/x86_64-unknown-linux-musl/release/mini-kvvm-rs \
22-
${HOME}/go/src/github.com/ava-labs/avalanchego/build/plugins/qBnAKUQ2mxjMHCneWjq5nFuhntoWrsKsCjaYSouFjpuCB2o5d
71+
SpacesVM CLI for issuing RPC commands
72+
73+
Usage: spacescli [OPTIONS] --endpoint <ENDPOINT> <COMMAND>
74+
75+
Commands:
76+
claim
77+
set
78+
delete
79+
get
80+
help Print this message or the help of the given subcommand(s)
81+
82+
Options:
83+
--endpoint <ENDPOINT> Endpoint for RPC calls
84+
--private-key-file <PRIVATE_KEY_FILE> Private key file [default: .spacesvm-cli-pk]
85+
-h, --help Print help information
86+
-V, --version Print version information
2387
```
24-
##
88+
89+
## Client
90+
#### Public Endpoints (`/public`)
91+
92+
#### spacesvm.ping
93+
```bash
94+
# "2FdEyx8mgicqvQaGN3HGkDwo7NbhKAY6pgTXUB1UkHW4meySUv" is the blockchain Id
95+
curl -X POST --data '{
96+
"jsonrpc": "2.0",
97+
"id" : 1,
98+
"method" : "spaces.ping",
99+
"params" : []
100+
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/2FdEyx8mgicqvQaGN3HGkDwo7NbhKAY6pgTXUB1UkHW4meySUv/public
101+
102+
# {"jsonrpc":"2.0","result":{"success":true},"id":1}
103+
```
104+
#### spacesvm.issueTx
105+
```bash
106+
# "2FdEyx8mgicqvQaGN3HGkDwo7NbhKAY6pgTXUB1UkHW4meySUv" is the blockchain Id
107+
curl -X POST --data '{
108+
"jsonrpc": "2.0",
109+
"method": "spacesvm.issueTx",
110+
"params":{
111+
"typedData":<EIP-712 compliant typed data>,
112+
"signature":<hex-encoded sig>
113+
},
114+
"id": 1
115+
}'
116+
# IssueTxResponse {"tx_id":<ID>}
117+
```
118+
#### spacesvm.resolve
119+
```bash
120+
curl -X POST --data '{
121+
"jsonrpc": "2.0",
122+
"method": "spacesvm.resolve",
123+
"params":{
124+
"path":<string | ex:jim/twitter>
125+
},
126+
"id": 1
127+
}'
128+
# ResolveResponse {"exists":<bool>, "value":<base64 encoded>, "valueMeta":<chain.ValueMeta>}
129+
```
130+
131+
## License
132+
`spacesvm-rs` is under the BSD 3.0 license. See the [LICENSE](LICENSE) file for details.

scripts/build.release.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ fi
99
# "--bin" can be specified multiple times for each directory in "bin/*" or workspaces
1010
cargo build \
1111
--release \
12-
--bin mini-kvvm
12+
--bin spacesvm
1313

14-
./target/release/mini-kvvm -V
14+
./target/release/spacesvm -V

scripts/build.x86_64-linux-musl.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ docker pull clux/muslrust
1111
docker run -v $PWD:/volume --rm -t clux/muslrust \
1212
cargo build \
1313
--release \
14-
--bin mini-kvvm \
14+
--bin spacesvm \
1515
--target x86_64-unknown-linux-musl
1616

1717
BIN_PATH=./target/x86_64-unknown-linux-musl/release
18-
${BIN_PATH}/mini-kvvm-rs --help || true
18+
${BIN_PATH}/spacesvm --help || true
File renamed without changes.
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
[package]
2-
name = "cli"
3-
version = "0.0.0"
2+
name = "spacesvm_cli"
3+
version = "0.0.1"
44
edition = "2021"
55
rust-version = "1.65"
66
publish = false
7-
description = "cli for issuing simple rpc commands to mini-kvvm"
7+
description = "spacesvm_cli_for_issuing_RPC_commands"
88
license = "BSD-3-Clause"
99
homepage = "https://avax.network"
1010

1111
[dependencies]
12-
avalanche-types = { version = "0.0.132", features = ["rpcchainvm"] }
12+
avalanche-types = { version = "0.0.135", features = ["subnet"] }
1313
clap = { version = "4.0", features = ["derive"] }
1414
hex = "0.4.3"
1515
jsonrpc-core = "18.0.0"
1616
jsonrpc-core-client = { version = "18.0.0" }
1717
jsonrpc-client-transports = "18.0.0"
1818
jsonrpc-derive = "18.0"
1919
log = "0.4.17"
20-
mini-kvvm = {path = "../mini-kvvm"}
20+
spacesvm = { path = "../spacesvm" }
2121
serde = { version = "1.0.147", features = ["derive"] }
2222
serde_json = "1.0.87"
2323
tokio = { version = "1.21.2", features = ["full"] }

cli/src/main.rs renamed to spaces-cli/src/main.rs

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
use avalanche_types::key;
2-
use clap::{Parser, Subcommand};
3-
use jsonrpc_client_transports::{transports, RpcError};
4-
use jsonrpc_core::futures;
5-
use mini_kvvm::api::ServiceClient as Client;
6-
use mini_kvvm::api::{DecodeTxArgs, IssueTxArgs, ResolveArgs};
7-
use mini_kvvm::chain::tx::{decoder, tx::TransactionType, unsigned::TransactionData};
81
use std::error;
92
use std::fs::File;
103
use std::io::{Result, Write};
114
use std::path::Path;
125

6+
use avalanche_types::key;
7+
use clap::{Parser, Subcommand};
8+
use jsonrpc_client_transports::{transports, RpcError};
9+
use jsonrpc_core::futures;
10+
use spacesvm::{
11+
api::{DecodeTxArgs, IssueTxArgs, ResolveArgs, ServiceClient as Client},
12+
chain::tx::{decoder, tx::TransactionType, unsigned::TransactionData},
13+
};
14+
1315
#[derive(Parser)]
1416
#[command(version, about, long_about = None)]
1517
struct Cli {
@@ -18,7 +20,7 @@ struct Cli {
1820
endpoint: String,
1921

2022
/// Private key file.
21-
#[clap(long, default_value = ".mini-kvvm-cli-pk")]
23+
#[clap(long, default_value = ".spacesvm-cli-pk")]
2224
private_key_file: String,
2325

2426
/// Which subcommand to call.
@@ -28,20 +30,20 @@ struct Cli {
2830

2931
#[derive(Subcommand, Debug)]
3032
enum Command {
31-
Bucket {
32-
bucket: String,
33+
Claim {
34+
space: String,
3335
},
3436
Set {
35-
bucket: String,
37+
space: String,
3638
key: String,
3739
value: String,
3840
},
3941
Delete {
40-
bucket: String,
42+
space: String,
4143
key: String,
4244
},
4345
Get {
44-
bucket: String,
46+
space: String,
4547
key: String,
4648
},
4749
}
@@ -55,9 +57,9 @@ async fn main() -> std::result::Result<(), Box<dyn error::Error>> {
5557
let client = futures::executor::block_on(connection)?;
5658
ping(&client).await?;
5759

58-
if let Command::Get { bucket, key } = &cli.command {
60+
if let Command::Get { space, key } = &cli.command {
5961
futures::executor::block_on(client.resolve(ResolveArgs {
60-
bucket: bucket.as_bytes().to_vec(),
62+
space: space.as_bytes().to_vec(),
6163
key: key.as_bytes().to_vec(),
6264
}))
6365
.map_err(|e| e.to_string())?;
@@ -71,9 +73,9 @@ async fn main() -> std::result::Result<(), Box<dyn error::Error>> {
7173

7274
fn command_to_tx(command: Command) -> Result<TransactionData> {
7375
match command {
74-
Command::Bucket { bucket } => Ok(bucket_tx(bucket)),
75-
Command::Set { bucket, key, value } => Ok(set_tx(bucket, key, value.as_bytes().to_vec())),
76-
Command::Delete { bucket, key } => Ok(delete_tx(bucket, key)),
76+
Command::Claim { space } => Ok(claim_tx(space)),
77+
Command::Set { space, key, value } => Ok(set_tx(space, key, value.as_bytes().to_vec())),
78+
Command::Delete { space, key } => Ok(delete_tx(space, key)),
7779
_ => Err(std::io::Error::new(
7880
std::io::ErrorKind::Other,
7981
"not a supported tx",
@@ -96,28 +98,28 @@ fn get_or_create_pk(path: &str) -> Result<key::secp256k1::private_key::Key> {
9698
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))
9799
}
98100

99-
fn bucket_tx(bucket: String) -> TransactionData {
101+
fn claim_tx(space: String) -> TransactionData {
100102
TransactionData {
101-
typ: TransactionType::Bucket,
102-
bucket,
103+
typ: TransactionType::Claim,
104+
space,
103105
key: "".to_string(),
104106
value: vec![],
105107
}
106108
}
107109

108-
fn set_tx(bucket: String, key: String, value: Vec<u8>) -> TransactionData {
110+
fn set_tx(space: String, key: String, value: Vec<u8>) -> TransactionData {
109111
TransactionData {
110112
typ: TransactionType::Set,
111-
bucket,
113+
space,
112114
key,
113115
value,
114116
}
115117
}
116118

117-
fn delete_tx(bucket: String, key: String) -> TransactionData {
119+
fn delete_tx(space: String, key: String) -> TransactionData {
118120
TransactionData {
119121
typ: TransactionType::Delete,
120-
bucket,
122+
space,
121123
key,
122124
value: vec![],
123125
}

mini-kvvm/Cargo.toml renamed to spacesvm/Cargo.toml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
11
[package]
2-
name = "mini-kvvm"
2+
name = "spacesvm"
33
version = "0.0.0"
44
edition = "2021"
55
rust-version = "1.65"
66
publish = false
7-
description = "Mini key-value store VM for Avalanche in Rust"
7+
description = "Authenticated, hierarchical key-value store w/EIP-712 compatibility"
88
license = "BSD-3-Clause"
99
homepage = "https://avax.network"
1010
readme = "README.md"
1111

1212
[[bin]]
13-
name = "mini-kvvm"
14-
path = "src/bin/mini-kvvm/main.rs"
13+
name = "spacesvm"
14+
path = "src/bin/spaces/main.rs"
1515

1616
[dependencies]
17-
avalanche-proto = { version = "0.19.0" }
18-
avalanche-types = { version = "0.0.132", features = ["rpcchainvm"] }
17+
avalanche-types = { version = "0.0.135", features = ["subnet"] }
1918
byteorder = "1.4.3"
2019
chrono = "0.4.19"
2120
crossbeam-channel = "0.5.6"

mini-kvvm/src/api/mod.rs renamed to spacesvm/src/api/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ pub struct DecodeTxResponse {
6666

6767
#[derive(Deserialize, Serialize, Debug)]
6868
pub struct ResolveArgs {
69-
pub bucket: Vec<u8>,
69+
pub space: Vec<u8>,
7070
pub key: Vec<u8>,
7171
}
7272

spacesvm/src/api/rpc.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
use serde::{Deserialize, Serialize};
2+
3+
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
4+
struct Request {
5+
jsonrpc: String,
6+
method: String,
7+
#[serde(skip_serializing_if = "Option::is_none")]
8+
params: Option<serde_json::Value>,
9+
id: serde_json::Value,
10+
}
11+
12+
#[cfg(test)]
13+
mod tests {
14+
#[test]
15+
fn test_request() {}
16+
}

0 commit comments

Comments
 (0)