crypto fix
All checks were successful
Deploy / build-deploy (push) Successful in 2m26s

This commit is contained in:
Jorijn van der Graaf 2026-08-20 00:09:08 +02:00
commit 47d302a9a4
4 changed files with 364 additions and 39 deletions

View file

@ -134,6 +134,77 @@ int main() {
"eurc: a hex block number is still accepted");
}
// ── corroboration: multiple endpoints per chain ──────────────────
{
// The single-"rpc" shorthand still parses, and lands as one endpoint
// with min_confirmations=1 (the pre-corroboration behaviour).
const auto one = Server::ParseEurcChains(R"({"chains":[
{"name":"base","rpc":"https://a.example",
"contract":"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"}]})");
Check(one.has_value() && (*one)[0].rpcUrls.size() == 1
&& (*one)[0].rpcUrls[0] == "https://a.example"
&& (*one)[0].minConfirmations == 1,
"eurc: the single-rpc shorthand still loads, one source, one confirmation");
// Two endpoints default to requiring agreement between both.
const auto two = Server::ParseEurcChains(R"({"chains":[
{"name":"base","rpcs":["https://a.example","https://b.example"],
"contract":"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"}]})");
Check(two.has_value() && (*two)[0].rpcUrls.size() == 2
&& (*two)[0].minConfirmations == 2,
"eurc: two endpoints default to two confirmations");
// Three endpoints still default to two — a quorum, not unanimity, so
// one node being down does not stop the shop settling.
const auto three = Server::ParseEurcChains(R"({"chains":[
{"name":"base","rpcs":["https://a.example","https://b.example",
"https://c.example"],
"contract":"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"}]})");
Check(three.has_value() && (*three)[0].minConfirmations == 2,
"eurc: three endpoints still need two agreeing, not all three");
// An explicit value is honoured.
const auto strict = Server::ParseEurcChains(R"({"chains":[
{"name":"base","rpcs":["https://a.example","https://b.example",
"https://c.example"],"min_confirmations":3,
"contract":"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"}]})");
Check(strict.has_value() && (*strict)[0].minConfirmations == 3,
"eurc: an explicit min_confirmations is honoured");
}
// One endpoint cannot corroborate itself, so a repeated URL is refused
// rather than counted twice toward the quorum.
Check(!Server::ParseEurcChains(R"({"chains":[
{"name":"base","rpcs":["https://a.example","https://a.example"],
"contract":"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"}]})").has_value(),
"eurc: the same endpoint listed twice is refused");
// Asking for more agreement than there are sources would never settle
// anything — a silent never-pays shop, so it is a refusal at load.
Check(!Server::ParseEurcChains(R"({"chains":[
{"name":"base","rpcs":["https://a.example","https://b.example"],
"min_confirmations":3,
"contract":"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"}]})").has_value(),
"eurc: more confirmations than endpoints is refused");
Check(!Server::ParseEurcChains(R"({"chains":[
{"name":"base","rpcs":["https://a.example"],"min_confirmations":0,
"contract":"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"}]})").has_value(),
"eurc: zero confirmations is refused");
// An empty rpcs list is not a chain that can be watched.
Check(!Server::ParseEurcChains(R"({"chains":[
{"name":"base","rpcs":[],
"contract":"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"}]})").has_value(),
"eurc: an empty endpoint list is refused");
Check(!Server::ParseEurcChains(R"({"chains":[
{"name":"base","rpcs":["https://a.example",42],
"contract":"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"}]})").has_value(),
"eurc: a non-string endpoint is refused");
Check(!Server::ParseEurcChains(R"({"chains":[
{"name":"base","rpcs":["https://a.example","ftp://b.example"],
"contract":"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"}]})").has_value(),
"eurc: a non-http endpoint anywhere in the list is refused");
if (failures != 0) {
std::println(std::cerr, "{} check(s) failed", failures);
return 1;