Initial commit
This commit is contained in:
commit
0f27dc05f4
12 changed files with 6681 additions and 0 deletions
100
g1bridge/src/blockchain.rs
Normal file
100
g1bridge/src/blockchain.rs
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
use crate::{DebtG2B, Opt};
|
||||
|
||||
use log::error;
|
||||
use runtime::balances::calls::types::TransferKeepAlive;
|
||||
use subxt::{
|
||||
OnlineClient,
|
||||
backend::{Backend, BackendExt},
|
||||
ext::sp_core::{
|
||||
Pair as _,
|
||||
ed25519::{Pair, Public},
|
||||
},
|
||||
tx::{PairSigner, Signer},
|
||||
};
|
||||
use tokio::sync::mpsc::Receiver;
|
||||
use typed_sled::Tree;
|
||||
|
||||
#[subxt::subxt(
|
||||
runtime_metadata_path = "res/metadata.scale",
|
||||
derive_for_all_types = "Debug"
|
||||
)]
|
||||
pub mod runtime {}
|
||||
|
||||
pub type Client = subxt::OnlineClient<Runtime>;
|
||||
pub type AccountId = subxt::utils::AccountId32;
|
||||
pub type IdtyId = u32;
|
||||
pub type BlockNumber = u32;
|
||||
pub type TxProgress = subxt::tx::TxProgress<Runtime, Client>;
|
||||
pub type Balance = u64;
|
||||
pub type AccountData =
|
||||
runtime::runtime_types::pallet_duniter_account::types::AccountData<Balance, IdtyId>;
|
||||
pub type AccountInfo = runtime::runtime_types::frame_system::AccountInfo<u32, AccountData>;
|
||||
pub type Hash = sp_core::H256;
|
||||
|
||||
// declare runtime types
|
||||
pub enum Runtime {}
|
||||
impl subxt::config::Config for Runtime {
|
||||
type AssetId = ();
|
||||
type Hash = Hash;
|
||||
type AccountId = AccountId;
|
||||
type Address = sp_runtime::MultiAddress<Self::AccountId, u32>;
|
||||
type Signature = sp_runtime::MultiSignature;
|
||||
type Hasher = subxt::config::substrate::BlakeTwo256;
|
||||
type Header = subxt::config::substrate::SubstrateHeader<BlockNumber, Self::Hasher>;
|
||||
type ExtrinsicParams = subxt::config::DefaultExtrinsicParams<Self>;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, codec::Encode)]
|
||||
pub struct Tip {
|
||||
#[codec(compact)]
|
||||
tip: u64,
|
||||
}
|
||||
impl Tip {
|
||||
pub fn new(amount: u64) -> Self {
|
||||
Tip { tip: amount }
|
||||
}
|
||||
}
|
||||
impl From<u64> for Tip {
|
||||
fn from(n: u64) -> Self {
|
||||
Self::new(n)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Msg {
|
||||
NewDebt,
|
||||
Timer,
|
||||
}
|
||||
|
||||
pub async fn run(
|
||||
url: String,
|
||||
pair: Pair,
|
||||
mut recv: Receiver<DebtG2B>,
|
||||
tree_debt_g2b: Tree<DebtG2B, ()>,
|
||||
) {
|
||||
let mut client = OnlineClient::<Runtime>::from_url(&url).await.ok();
|
||||
while let Some(msg) = recv.recv().await {
|
||||
if client.is_none() {
|
||||
client = OnlineClient::<Runtime>::from_url(&url).await.ok();
|
||||
}
|
||||
if let Some(client) = &client {
|
||||
match client
|
||||
.tx()
|
||||
.sign_and_submit_then_watch_default(
|
||||
&runtime::tx().balances().transfer_keep_alive(
|
||||
subxt::utils::MultiAddress::Id(msg.address.clone()),
|
||||
msg.amount,
|
||||
),
|
||||
&subxt::tx::PairSigner::new(pair),
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(_) => {
|
||||
tree_debt_g2b.remove(&msg).ok();
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Submitting transaction: {e:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
147
g1bridge/src/main.rs
Normal file
147
g1bridge/src/main.rs
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
#![feature(try_blocks)]
|
||||
|
||||
mod blockchain;
|
||||
|
||||
use argp::FromArgs;
|
||||
use serde::{Deserialize, Serialize, de};
|
||||
use sp_core::Pair as _;
|
||||
use std::{
|
||||
io::{BufRead, Read},
|
||||
str::FromStr,
|
||||
sync::Arc,
|
||||
};
|
||||
use subxt::{
|
||||
ext::sp_core::ed25519::{Pair, Public},
|
||||
utils::{AccountId32, MultiAddress},
|
||||
};
|
||||
use tiny_http::{Response, ResponseBox, Server, ServerConfig};
|
||||
use tokio::sync::mpsc::{Sender, channel};
|
||||
use typed_sled::Tree;
|
||||
|
||||
/// Game to Blockchain
|
||||
const TREE_DEBT_G2B: &'static str = "debt_g2b";
|
||||
|
||||
/// Blob
|
||||
#[derive(FromArgs)]
|
||||
struct Opt {
|
||||
/// path to the database
|
||||
#[argp(option, short = 'd')]
|
||||
db: String,
|
||||
|
||||
/// secret key is legacy (two passwords on the two first lines)
|
||||
#[argp(switch, short = 'l')]
|
||||
legacy: bool,
|
||||
|
||||
/// path to the file containing the secret key in Substrate format
|
||||
#[argp(option, short = 's')]
|
||||
secret_key: String,
|
||||
|
||||
/// duniter node URL (default: ws://127.0.0.1:9944)
|
||||
#[argp(option, short = 'u', default = "String::from(\"ws://127.0.0.1:9944\")")]
|
||||
url: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
struct DebtG2B {
|
||||
address: AccountId32,
|
||||
amount: u64,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let opt: Opt = argp::parse_args_or_exit(argp::DEFAULT);
|
||||
|
||||
let mut sk_file = std::fs::File::open(opt.secret_key).expect("Cannot open secret key file");
|
||||
let pair: Pair = if opt.legacy {
|
||||
let sk_reader = std::io::BufReader::new(sk_file);
|
||||
let mut sk_lines = sk_reader.lines();
|
||||
let psw1 = sk_lines
|
||||
.next()
|
||||
.expect("Secret key file should contain at least 2 lines for the 2 passwords")
|
||||
.unwrap();
|
||||
let psw2 = sk_lines
|
||||
.next()
|
||||
.expect("Secret key file should contain at least 2 lines for the 2 passwords")
|
||||
.unwrap();
|
||||
let params = scrypt::Params::new(12, 16, 1, 32).unwrap();
|
||||
let mut seed = [0u8; 32];
|
||||
scrypt::scrypt(
|
||||
psw2.trim().as_bytes(),
|
||||
psw1.trim().as_bytes(),
|
||||
¶ms,
|
||||
&mut seed,
|
||||
)
|
||||
.unwrap();
|
||||
Pair::from_seed(&seed)
|
||||
} else {
|
||||
let mut sk_content = String::new();
|
||||
sk_file
|
||||
.read_to_string(&mut sk_content)
|
||||
.expect("Cannot read secret key file");
|
||||
Pair::from_string(sk_content.trim(), None).expect("Cannot decode secret key")
|
||||
};
|
||||
|
||||
simplelog::SimpleLogger::init(log::LevelFilter::Debug, simplelog::Config::default()).unwrap();
|
||||
|
||||
let db = typed_sled::open(opt.db).expect("Cannot open database");
|
||||
let tree_debt_g2b = Tree::<DebtG2B, ()>::open(&db, TREE_DEBT_G2B);
|
||||
|
||||
let (bc_send, bc_recv) = channel(128);
|
||||
|
||||
tokio::spawn(blockchain::run(
|
||||
opt.url,
|
||||
pair,
|
||||
bc_recv,
|
||||
tree_debt_g2b.clone(),
|
||||
));
|
||||
|
||||
let server = Server::http("127.0.0.1:30061").expect("Cannot start server");
|
||||
|
||||
struct Locals {
|
||||
tree_debt_g2b: Tree<DebtG2B, ()>,
|
||||
bc_send: Sender<DebtG2B>,
|
||||
}
|
||||
|
||||
tokio::task_local! {
|
||||
static LOCALS: Arc<Locals>;
|
||||
};
|
||||
|
||||
LOCALS.scope(
|
||||
Arc::new(Locals {
|
||||
tree_debt_g2b,
|
||||
bc_send,
|
||||
}),
|
||||
async move {
|
||||
for request in server.incoming_requests() {
|
||||
let locals = LOCALS.get();
|
||||
tokio::spawn(async move {
|
||||
let url = request.url();
|
||||
|
||||
let mut url_items = url.split('/').filter(|item| !item.is_empty());
|
||||
|
||||
let resp: Option<ResponseBox> = try {
|
||||
match url_items.next() {
|
||||
Some("send") => {
|
||||
let address = AccountId32::from_str(url_items.next()?).ok()?;
|
||||
let amount = url_items.next()?.parse::<u64>().ok()?;
|
||||
println!("{address} {amount}");
|
||||
|
||||
let debt = DebtG2B { address, amount };
|
||||
locals.tree_debt_g2b.insert(&debt, &()).ok()?;
|
||||
locals.bc_send.send(debt).await.ok()?;
|
||||
|
||||
Response::empty(200).boxed()
|
||||
}
|
||||
_ => None?,
|
||||
}
|
||||
};
|
||||
if let Some(resp) = resp {
|
||||
request.respond(resp).ok();
|
||||
} else {
|
||||
request.respond(Response::empty(400)).ok();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
).await;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue