libdpf/examples/applications/ledger23.cpp

86 lines
2.7 KiB
C++
Raw Normal View History

#include <array>
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <vector>
#include "dpf.hpp"
#include "dpf/app_flow.hpp"
#include "dpf/app_plans.hpp"
// A (2,3) ledger, the DPF step. Three servers replicate a ledger as
// Shamir-style (2-of-3) shares (this group's dpf3 / VDPF+ construction). Each
// append writes one point (slot -> amount) into all three shares; any two
// servers reconstruct a slot. A verifiable proof (verify_dpf3) rejects an
// append that is not a single well-formed point before it is applied.
//
// c++ -std=c++17 -march=native -I include -I thirdparty \
// examples/applications/ledger23.cpp
namespace
{
using dpf::fp61;
constexpr std::size_t nslots = 256; // uint8 slot domain
fp61 open2(fp61 a, fp61 b) // any two of three shares reconstruct
{
return dpf::shamir3::reconstruct(dpf::shamir3::share{1, a},
dpf::shamir3::share{2, b});
}
} // namespace
int main()
{
std::vector<fp61> l1(nslots), l2(nslots), l3(nslots);
// Each append is a verified (2,3) point key.
const std::pair<std::uint8_t, std::uint64_t> entries[] = {
{5, 100}, {40, 25}, {5, 7}};
for (auto [slot, amount] : entries)
{
auto [k1, k2, k3] = dpf::make_dpf3(slot, fp61{amount}, dpf::verifiable{});
if (!dpf::verify_dpf3(dpf::prove_dpf3(k1, slot),
dpf::prove_dpf3(k2, slot), dpf::prove_dpf3(k3, slot)))
{
std::cerr << "ledger append audit\n";
return 1;
}
// Fold the (2,3) expansion into each party's ledger shares.
dpf::eval_full_add_into(l1, k1);
dpf::eval_full_add_into(l2, k2);
dpf::eval_full_add_into(l3, k3);
}
// Slot 5 got two credits (100 + 7); slot 40 got 25; the rest are 0.
if (open2(l1[5], l2[5]) != fp61{107}
|| open2(l1[40], l2[40]) != fp61{25}
|| open2(l1[0], l2[0]).raw() != 0)
{
std::cerr << "ledger balance\n";
return 1;
}
// A proof that does not come from the same append is rejected: mixing one
// party's token from an independent key triple fails verification.
auto [b1, b2, b3] = dpf::make_dpf3(std::uint8_t{9}, fp61{1}, dpf::verifiable{});
auto [c1, c2, c3] = dpf::make_dpf3(std::uint8_t{9}, fp61{1}, dpf::verifiable{});
if (dpf::verify_dpf3(dpf::prove_dpf3(b1, std::uint8_t{9}),
dpf::prove_dpf3(b2, std::uint8_t{9}),
dpf::prove_dpf3(c3, std::uint8_t{9})))
{
std::cerr << "ledger accepted a bad append\n";
return 1;
}
{
if (int rc = dpf::app::run_measured("ledger23",
dpf::protocol::ledger23_append_plan(0), 2))
return rc;
}
std::cout << open2(l1[5], l2[5]).raw() << "\n";
return 0;
}