1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use std::path::Path;

use zeroize::Zeroizing;

use ciphersuite::{group::ff::PrimeField, Ciphersuite, Ristretto};

use crate::{Network, Os, mimalloc, os, build_serai_service, write_dockerfile};

#[allow(clippy::needless_pass_by_value)]
pub fn processor(
  orchestration_path: &Path,
  network: Network,
  coin: &'static str,
  _coordinator_key: <Ristretto as Ciphersuite>::G,
  coin_key: Zeroizing<<Ristretto as Ciphersuite>::F>,
  entropy: Zeroizing<[u8; 32]>,
) {
  let setup = mimalloc(Os::Debian).to_string() +
    &build_serai_service(
      if coin == "ethereum" {
        r#"
RUN cargo install svm-rs
RUN svm install 0.8.25
RUN svm use 0.8.25
"#
      } else {
        ""
      },
      network.release(),
      &format!("binaries {} {coin}", network.db()),
      "serai-processor",
    );

  const ADDITIONAL_ROOT: &str = r#"
# Install ca-certificates
RUN apt install -y ca-certificates
"#;

  // TODO: Randomly generate these
  const RPC_USER: &str = "serai";
  const RPC_PASS: &str = "seraidex";
  // TODO: Isolate networks
  let hostname = format!("serai-{}-{coin}", network.label());
  let port = format!(
    "{}",
    match coin {
      "bitcoin" => 8332,
      "ethereum" => 8545,
      "monero" => 18081,
      _ => panic!("unrecognized external network"),
    }
  );

  let mut env_vars = vec![
    ("MESSAGE_QUEUE_RPC", format!("serai-{}-message-queue", network.label())),
    ("MESSAGE_QUEUE_KEY", hex::encode(coin_key.to_repr())),
    ("ENTROPY", hex::encode(entropy.as_ref())),
    ("NETWORK", coin.to_string()),
    ("NETWORK_RPC_LOGIN", format!("{RPC_USER}:{RPC_PASS}")),
    ("NETWORK_RPC_HOSTNAME", hostname),
    ("NETWORK_RPC_PORT", port),
    ("DB_PATH", "/volume/processor-db".to_string()),
    ("RUST_LOG", "info,serai_processor=debug".to_string()),
  ];
  if coin == "ethereum" {
    env_vars
      .push(("ETHEREUM_RELAYER_HOSTNAME", format!("serai-{}-ethereum-relayer", network.label())));
    env_vars.push(("ETHEREUM_RELAYER_PORT", "20830".to_string()));
  }
  let mut env_vars_str = String::new();
  for (env_var, value) in env_vars {
    env_vars_str += &format!(r#"{env_var}=${{{env_var}:="{value}"}} "#);
  }

  let run_processor = format!(
    r#"
# Copy the Processor binary and relevant license
COPY --from=builder --chown=processor /serai/bin/serai-processor /bin/
COPY --from=builder --chown=processor /serai/AGPL-3.0 .

# Run processor
CMD {env_vars_str} serai-processor
"#
  );

  let run = os(Os::Debian, ADDITIONAL_ROOT, "processor") + &run_processor;
  let res = setup + &run;

  let mut processor_path = orchestration_path.to_path_buf();
  processor_path.push("processor");
  processor_path.push(coin);
  processor_path.push("Dockerfile");

  write_dockerfile(processor_path, &res);
}