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

Feature/azure docker #7

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 55 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ bdk-reserves = "0.28"
#env_logger = "0.10"
log = "0.4"
base64 = "0.13"
prometheus = "0.13"
lazy_static = "1.4"

[dev-dependencies]
#actix-rt = "2"
Expand Down
28 changes: 25 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,30 @@
FROM rust:1.72-alpine3.18 as builder

ARG ALPINE_REPO
ARG MITM_CA
ARG http_proxy
ENV http_proxy=$http_proxy
ENV https_proxy=$http_proxy
ENV HTTP_PROXY=$http_proxy
ENV HTTPS_PROXY=$http_proxy

# allowing custom package repositories
RUN printf "${ALPINE_REPO}/main\n${ALPINE_REPO}/community\n" > /etc/apk/repositories
RUN cat /etc/apk/repositories

# allowing MITM attacks (requirement for some build systems)
RUN echo "$MITM_CA" > /root/mitm-ca.crt
RUN cat /root/mitm-ca.crt >> /etc/ssl/certs/ca-certificates.crt
RUN apk --no-cache add ca-certificates \
&& rm -rf /var/cache/apk/*
RUN echo "$MITM_CA" > /usr/local/share/ca-certificates/mitm-ca.crt
RUN update-ca-certificates

RUN apk add --no-cache build-base
USER bin
WORKDIR /app
COPY . .
RUN mkdir target && chown bin target && mkdir dist && chown bin dist
USER bin
RUN cargo test
RUN cargo build --release
RUN install -D target/release/bdk-reserves-web dist/bin/bdk-reserves-web
Expand All @@ -16,7 +38,7 @@ RUN cargo fmt -- --check
RUN cargo clippy
RUN cargo audit

FROM scratch
FROM alpine
COPY --from=builder /app/dist /
USER 65534
ENTRYPOINT ["/bin/bdk-reserves-web"]
ENTRYPOINT ["/bin/bdk-reserves-web"]
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
TAG := bdk-reserves-web
ALPINE_REPO := http://dl-cdn.alpinelinux.org/alpine/v3.18
MITM_CA := ""

run: builder
docker run --rm --tty --env PORT=8888 --publish 8888:8888 ${TAG}

builder:
docker build --tag ${TAG} .
docker build --tag ${TAG} --build-arg "ALPINE_REPO=${ALPINE_REPO}" --build-arg "MITM_CA=${MITM_CA}" .
50 changes: 46 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use bdk::bitcoin::util::psbt::PartiallySignedTransaction;
use bdk::bitcoin::{Address, Network, OutPoint, TxOut};
use bdk::electrum_client::{Client, ElectrumApi};
use bdk_reserves::reserves::verify_proof;
use lazy_static::lazy_static;
use prometheus::{self, register_int_counter, Encoder, IntCounter, TextEncoder};
use serde::{Deserialize, Serialize};
use serde_json::json;
use std::{env, io, str::FromStr};
Expand All @@ -15,6 +17,16 @@ struct ProofOfReserves {
proof_psbt: String,
}

lazy_static! {
static ref POR_SUCCESS_COUNTER: IntCounter =
register_int_counter!("POR_success", "Successfully validated proof of reserves").unwrap();
}

lazy_static! {
static ref POR_INVALID_COUNTER: IntCounter =
register_int_counter!("POR_invalid", "Invalid proof of reserves").unwrap();
}

#[actix_web::main]
async fn main() -> io::Result<()> {
let address = env::var("BIND_ADDRESS").unwrap_or_else(|_err| match env::var("PORT") {
Expand All @@ -25,12 +37,15 @@ async fn main() -> io::Result<()> {
println!("Starting HTTP server at http://{}.", address);
println!("You can choose a different address through the BIND_ADDRESS env var.");
println!("You can choose a different port through the PORT env var.");
POR_INVALID_COUNTER.reset();
POR_SUCCESS_COUNTER.reset();

HttpServer::new(|| {
App::new()
.wrap(middleware::Logger::default()) // <- enable logger
.app_data(web::JsonConfig::default().limit(40960)) // <- limit size of the payload (global configuration)
.service(web::resource("/proof").route(web::post().to(check_proof)))
.service(web::resource("/prometheus").route(web::get().to(prometheus)))
.service(index)
})
.bind(address)?
Expand All @@ -44,6 +59,17 @@ async fn index() -> impl Responder {
HttpResponse::Ok().content_type("text/html").body(html)
}

async fn prometheus() -> HttpResponse {
let metric_families = prometheus::gather();
let mut buffer = Vec::new();
let encoder = TextEncoder::new();
encoder.encode(&metric_families, &mut buffer).unwrap();

let output = String::from_utf8(buffer.clone()).unwrap();
//println!("************************\nprometheus stats:\n{}", output);
HttpResponse::Ok().content_type("text/plain").body(output)
}

async fn check_proof(item: web::Json<ProofOfReserves>, req: HttpRequest) -> HttpResponse {
println!("request: {:?}", req);
println!("model: {:?}", item);
Expand All @@ -52,8 +78,14 @@ async fn check_proof(item: web::Json<ProofOfReserves>, req: HttpRequest) -> Http
handle_ext_reserves(&item.message, &item.proof_psbt, 3, item.addresses.clone());

let answer = match proof_result {
Err(e) => json!({ "error": e }),
Ok(res) => res,
Err(e) => {
POR_INVALID_COUNTER.inc();
json!({ "error": e })
}
Ok(res) => {
POR_SUCCESS_COUNTER.inc();
res
}
}
.to_string();
HttpResponse::Ok().content_type("text/json").body(answer)
Expand Down Expand Up @@ -147,7 +179,9 @@ mod tests {

#[actix_web::test]
async fn test_index() -> Result<(), Error> {
let app = App::new().route("/proof", web::post().to(check_proof));
let app = App::new()
.route("/proof", web::post().to(check_proof))
.route("/prometheus", web::get().to(prometheus));
let app = test::init_service(app).await;

let req = test::TestRequest::post().uri("/proof")
Expand All @@ -164,7 +198,15 @@ mod tests {
let response_body = resp.into_body();
let resp = r#"{"error":"NonSpendableInput(1)"}"#;
assert_eq!(to_bytes(response_body).await?, resp);
//assert_eq!(to_bytes(response_body).await?, r##"Hello world!"##);

let req = test::TestRequest::get().uri("/prometheus").to_request();
let resp = app.call(req).await?;

assert_eq!(resp.status(), http::StatusCode::OK);

let response_body = resp.into_body();
let resp = "# HELP POR_invalid Invalid proof of reserves\n# TYPE POR_invalid counter\nPOR_invalid 1\n";
assert_eq!(to_bytes(response_body).await?, resp);

Ok(())
}
Expand Down
Loading