Merge branch 'status' into msl/parse-jets

This commit is contained in:
Matthew LeVan 2023-12-06 16:45:22 -05:00
commit b7cb624b85
10 changed files with 199 additions and 220 deletions

View File

@ -254,20 +254,36 @@ enum NockWork {
Work12(Nock12),
}
pub struct ContextSnapshot {
cold: Cold,
warm: Warm,
}
pub struct Context {
pub stack: NockStack,
// For printing slogs; if None, print to stdout; Option slated to be removed
pub newt: Newt,
pub cold: Cold,
pub warm: Warm,
pub hot: Hot,
// XX: persistent memo cache
// Per-event cache; option to share cache with virtualized events
pub cache: Hamt<Noun>,
pub scry_stack: Noun,
pub trace_info: Option<TraceInfo>,
}
impl Context {
pub fn save(&self) -> ContextSnapshot {
ContextSnapshot {
cold: self.cold,
warm: self.warm,
}
}
pub fn restore(&mut self, saved: &ContextSnapshot) {
self.cold = saved.cold;
self.warm = saved.warm;
}
}
#[derive(Clone, Copy, Debug)]
pub enum Error {
ScryBlocked(Noun), // path
@ -301,6 +317,7 @@ fn debug_assertions(stack: &mut NockStack, noun: Noun) {
pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Result {
let terminator = Arc::clone(&TERMINATOR);
let orig_subject = subject; // for debugging
let snapshot = context.save();
let virtual_frame: *const u64 = context.stack.get_frame_pointer();
let mut res: Noun = D(0);
@ -858,7 +875,7 @@ pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Res
match nock {
Ok(res) => Ok(res),
Err(err) => Err(exit(context, virtual_frame, err)),
Err(err) => Err(exit(context, &snapshot, virtual_frame, err)),
}
}
@ -1075,10 +1092,16 @@ fn push_formula(stack: &mut NockStack, formula: Noun, tail: bool) -> result::Res
Ok(())
}
fn exit(context: &mut Context, virtual_frame: *const u64, error: Error) -> Error {
fn exit(
context: &mut Context,
snapshot: &ContextSnapshot,
virtual_frame: *const u64,
error: Error,
) -> Error {
unsafe {
let stack = &mut context.stack;
context.restore(snapshot);
let stack = &mut context.stack;
let mut preserve = match error {
Error::ScryBlocked(path) => path,
Error::Deterministic(t) | Error::NonDeterministic(t) | Error::ScryCrashed(t) => {
@ -1088,10 +1111,9 @@ fn exit(context: &mut Context, virtual_frame: *const u64, error: Error) -> Error
}
};
while (stack).get_frame_pointer() != virtual_frame {
(stack).preserve(&mut preserve);
// (stack).preserve(&mut context.cold);
(stack).frame_pop();
while stack.get_frame_pointer() != virtual_frame {
stack.preserve(&mut preserve);
stack.frame_pop();
}
match error {

View File

@ -20,7 +20,7 @@ use crate::jets::bits::*;
use crate::jets::cold::Cold;
use crate::jets::form::*;
use crate::jets::hash::*;
use crate::jets::hot::Hot;
use crate::jets::hot::{Hot, URBIT_HOT_STATE};
use crate::jets::list::*;
use crate::jets::lock::aes::*;
use crate::jets::lock::ed::*;
@ -301,7 +301,7 @@ pub mod util {
let newt = Newt::new_mock();
let cold = Cold::new(&mut stack);
let warm = Warm::new();
let hot = Hot::init(&mut stack);
let hot = Hot::init(&mut stack, URBIT_HOT_STATE);
let cache = Hamt::<Noun>::new();
Context {

View File

@ -267,6 +267,7 @@ impl Iterator for NounList {
}
}
#[derive(Copy, Clone)]
pub struct Cold(*mut ColdMem);
struct ColdMem {

View File

@ -4,8 +4,9 @@ use ares_macros::tas;
use either::Either::{self, Left, Right};
use std::ptr::null_mut;
// const A_50: Either<u64, (u64, u64)> = Right((b"a", 50));
const K_139: Either<&[u8], (u64, u64)> = Right((tas!(b"k"), 139));
/** Root for Hoon %k.139
*/
pub const K_139: Either<&[u8], (u64, u64)> = Right((tas!(b"k"), 139));
// // This is the const state all in one spot as literals
// #[allow(clippy::complexity)]
@ -57,8 +58,14 @@ const K_139: Either<&[u8], (u64, u64)> = Right((tas!(b"k"), 139));
// (&[A_50, Left(b"mink")], 1, jet_mink),
// ];
/**
* (path, axis in battery, jet function pointer)
* see the [Jet] typedef in ares::jets for the proper prototype
*/
pub type HotEntry = (&'static [Either<&'static [u8], (u64, u64)>], u64, Jet);
#[allow(clippy::complexity)]
const TRUE_HOT_STATE: &[(&[Either<&[u8], (u64, u64)>], u64, Jet)] = &[
pub const URBIT_HOT_STATE: &[HotEntry] = &[
(&[K_139, Left(b"one"), Left(b"add")], 1, jet_add),
(&[K_139, Left(b"one"), Left(b"dec")], 1, jet_dec),
(&[K_139, Left(b"one"), Left(b"div")], 1, jet_div),
@ -759,10 +766,10 @@ const TRUE_HOT_STATE: &[(&[Either<&[u8], (u64, u64)>], u64, Jet)] = &[
pub struct Hot(*mut HotMem);
impl Hot {
pub fn init(stack: &mut NockStack) -> Self {
pub fn init(stack: &mut NockStack, constant_hot_state: &[HotEntry]) -> Self {
unsafe {
let mut next = Hot(null_mut());
for (htap, axe, jet) in TRUE_HOT_STATE {
for (htap, axe, jet) in constant_hot_state {
let mut a_path = D(0);
for i in *htap {
match i {

View File

@ -1,33 +1,12 @@
/** Virtualization jets
*/
use crate::hamt::Hamt;
use crate::interpreter::{interpret, Context, Error};
use crate::interpreter::Context;
use crate::jets::util::slot;
use crate::jets::{JetErr, Result};
use crate::noun::{Cell, Noun, D, NO, T, YES};
use crate::noun::{Noun, D, NO, T};
crate::gdb!();
// Deterministic scry crashes should have the following behaviour:
//
// root <-- bail, %crud
// mink <-- return Deterministic
// scry <-- return ScryCrashed
//
// root <-- bail, %crud
// mink <-- return Deterministic
// mink <-- return ScryCrashed
// scry <-- return ScryCrashed
// scry <-- return ScryCrashed
//
// root
// mink <-- return Tone
// mink <-- return Deterministic
// mink <-- return ScryCrashed
// scry <-- return ScryCrashed
// scry <-- return ScryCrashed
// scry
//
pub fn jet_mink(context: &mut Context, subject: Noun) -> Result {
let arg = slot(subject, 6)?;
// mink sample = [nock scry_namespace]
@ -36,45 +15,8 @@ pub fn jet_mink(context: &mut Context, subject: Noun) -> Result {
let v_formula = slot(arg, 5)?;
let scry_handler = slot(arg, 3)?;
let old_cache = context.cache;
let old_scry_stack = context.scry_stack;
context.cache = Hamt::<Noun>::new();
context.scry_stack = T(&mut context.stack, &[scry_handler, old_scry_stack]);
match util::mink(context, v_subject, v_formula) {
Ok(noun) => {
context.cache = old_cache;
context.scry_stack = old_scry_stack;
Ok(noun)
}
Err(error) => match error {
Error::NonDeterministic(_) => Err(JetErr::Fail(error)),
Error::ScryCrashed(trace) => {
// When we enter a +mink call, we record the state of the scry handler stack at the
// time (i.e. the Noun representing (list scry)). Each scry will pop the head off of
// this scry handler stack and calls interpret(), using the rest of the scry handler
// stack in the event that it scries again recursively. When a scry succeeds, it
// replaces the scry handler that it used by pushing it back onto the top of the
// scry handler stack. However, it never does so when it fails. Therefore, we can
// tell which particular virtualization instance failed by comparing the scry
// handler stack at the time of failure (i.e. the scry handler stack in the context
// after a failed scry) with the scry handler stack at the time of the virtualization
// call. Thus, whenever a virtualized interpret() call fails with a
// Error::ScryCrashed, jet_mink() compares the two scry handler stack Nouns> If they
// are identical, jet_mink() bails with Error::Deterministic. Otherwise, it forwards
// the Error::ScryCrashed to the senior virtualization call.
if unsafe { context.scry_stack.raw_equals(old_scry_stack) } {
Err(JetErr::Fail(Error::Deterministic(trace)))
} else {
Err(JetErr::Fail(error))
}
}
Error::Deterministic(_) | Error::ScryBlocked(_) => {
panic!("scry: mink: unhandled errors in helper")
}
},
}
// Implicit error conversion
Ok(util::mink(context, v_subject, v_formula, scry_handler)?)
}
pub fn jet_mole(context: &mut Context, subject: Noun) -> Result {
@ -90,18 +32,15 @@ pub fn jet_mure(context: &mut Context, subject: Noun) -> Result {
let fol = util::slam_gate_fol(&mut context.stack);
let scry = util::pass_thru_scry(&mut context.stack);
context.scry_stack = T(&mut context.stack, &[scry, context.scry_stack]);
match interpret(context, tap, fol) {
Ok(res) => {
context.scry_stack = context.scry_stack.as_cell()?.tail();
Ok(T(&mut context.stack, &[D(0), res]))
match util::mink(context, tap, fol, scry) {
Ok(tone) => {
if unsafe { tone.as_cell()?.head().raw_equals(D(0)) } {
Ok(tone)
} else {
Ok(D(0))
}
}
Err(error) => match error {
// Since we are using the pass-through scry handler, we know for a fact that a scry
// crash must have come from a senior virtualization context.
Error::NonDeterministic(_) | Error::ScryCrashed(_) => Err(JetErr::Fail(error)),
Error::Deterministic(_) | Error::ScryBlocked(_) => Ok(D(0)),
},
Err(err) => Err(JetErr::Fail(err)),
}
}
@ -110,37 +49,32 @@ pub fn jet_mute(context: &mut Context, subject: Noun) -> Result {
let fol = util::slam_gate_fol(&mut context.stack);
let scry = util::pass_thru_scry(&mut context.stack);
context.scry_stack = T(&mut context.stack, &[scry, context.scry_stack]);
match interpret(context, tap, fol) {
Ok(res) => {
context.scry_stack = context.scry_stack.as_cell()?.tail();
Ok(T(&mut context.stack, &[YES, res]))
let tone = util::mink(context, tap, fol, scry);
match util::mook(context, tone?.as_cell()?, false) {
Ok(toon) => {
match toon.head() {
x if unsafe { x.raw_equals(D(0)) } => Ok(toon.as_noun()),
x if unsafe { x.raw_equals(D(1)) } => {
// XX: Need to check that result is actually of type path
// return [[%leaf "mute.hunk"] ~] if not
let bon = util::smyt(&mut context.stack, toon.tail())?;
Ok(T(&mut context.stack, &[NO, bon, D(0)]))
}
x if unsafe { x.raw_equals(D(2)) } => Ok(T(&mut context.stack, &[NO, toon.tail()])),
_ => panic!("serf: mook: invalid toon"),
}
}
Err(error) => match error {
// Since we are using the pass-through scry handler, we know for a fact that a scry
// crash must have come from a senior virtualization context.
Error::NonDeterministic(_) | Error::ScryCrashed(_) => Err(JetErr::Fail(error)),
Error::ScryBlocked(path) => {
// XX: Need to check that result is actually of type path
// return [[%leaf "mute.hunk"] ~] if not
let bon = util::smyt(&mut context.stack, path)?;
Ok(T(&mut context.stack, &[NO, bon, D(0)]))
}
Error::Deterministic(trace) => {
let ton = Cell::new(&mut context.stack, D(2), trace);
let tun = util::mook(context, ton, false)?;
Ok(T(&mut context.stack, &[NO, tun.tail()]))
}
},
Err(err) => Err(JetErr::Fail(err)),
}
}
pub mod util {
use crate::hamt::Hamt;
use crate::interpreter::{interpret, Context, Error};
use crate::jets;
use crate::jets::bits::util::rip;
use crate::jets::form::util::scow;
use crate::jets::JetErr;
use crate::mem::NockStack;
use crate::noun::{tape, Cell, Noun, D, T};
use ares_macros::tas;
@ -157,7 +91,7 @@ pub mod util {
/// The classic "pass-through" scry handler.
pub fn pass_thru_scry(stack: &mut NockStack) -> Noun {
// > .* 0 != => ~ |=(a=^ ``.*(a [%12 [%0 2] %0 3]))
// .* 0 != => ~ |=(a=^ ``.*(a [%12 [%0 2] %0 3]))
// [[[1 0] [1 0] 2 [0 6] 1 12 [0 2] 0 3] [0 0] 0]
let sig = T(stack, &[D(1), D(0)]);
let sam = T(stack, &[D(0), D(6)]);
@ -176,13 +110,94 @@ pub mod util {
T(stack, &[dos, gat])
}
pub fn mink(context: &mut Context, subject: Noun, formula: Noun) -> Result<Noun, Error> {
/// The "always-fail" scry
pub fn null_scry(stack: &mut NockStack) -> Noun {
// .* 0 != => ~ |=(^ ~)
// [[1 0] [0 0] 0]
let sig = T(stack, &[D(1), D(0)]);
let zap = T(stack, &[D(0), D(0)]);
T(stack, &[sig, zap, D(0)])
}
// Deterministic scry crashes should have the following behaviour:
//
// root <-- bail, %crud
// mink <-- return Deterministic
// scry <-- return ScryCrashed
//
// root <-- bail, %crud
// mink <-- return Deterministic
// mink <-- return ScryCrashed
// scry <-- return ScryCrashed
// scry <-- return ScryCrashed
//
// root
// mink <-- return Tone
// mink <-- return Deterministic
// mink <-- return ScryCrashed
// scry <-- return ScryCrashed
// scry <-- return ScryCrashed
// scry
//
pub fn mink(
context: &mut Context,
subject: Noun,
formula: Noun,
scry: Noun,
) -> Result<Noun, Error> {
let cache_snapshot = context.cache;
let scry_snapshot = context.scry_stack;
context.cache = Hamt::<Noun>::new();
context.scry_stack = T(&mut context.stack, &[scry, context.scry_stack]);
match interpret(context, subject, formula) {
Ok(res) => Ok(T(&mut context.stack, &[D(0), res])),
Ok(res) => {
context.cache = cache_snapshot;
context.scry_stack = scry_snapshot;
Ok(T(&mut context.stack, &[D(0), res]))
}
Err(err) => match err {
Error::ScryBlocked(path) => Ok(T(&mut context.stack, &[D(1), path])),
Error::Deterministic(trace) => Ok(T(&mut context.stack, &[D(2), trace])),
Error::NonDeterministic(_) | Error::ScryCrashed(_) => Err(err),
Error::ScryBlocked(path) => {
context.cache = cache_snapshot;
context.scry_stack = scry_snapshot;
Ok(T(&mut context.stack, &[D(1), path]))
}
Error::Deterministic(trace) => {
context.cache = cache_snapshot;
context.scry_stack = scry_snapshot;
Ok(T(&mut context.stack, &[D(2), trace]))
}
Error::ScryCrashed(trace) => {
context.cache = cache_snapshot;
// When we enter a +mink call, we record the state of the scry handler stack at the
// time (i.e. the Noun representing (list scry)). Each scry will pop the head off of
// this scry handler stack and calls interpret(), using the rest of the scry handler
// stack in the event that it scries again recursively. When a scry succeeds, it
// replaces the scry handler that it used by pushing it back onto the top of the
// scry handler stack. However, it never does so when it fails. Therefore, we can
// tell which particular virtualization instance failed by comparing the scry
// handler stack at the time of failure (i.e. the scry handler stack in the context
// after a failed scry) with the scry handler stack at the time of the virtualization
// call. Thus, whenever a virtualized interpret() call fails with a
// Error::ScryCrashed, jet_mink() compares the two scry handler stack Nouns> If they
// are identical, jet_mink() bails with Error::Deterministic. Otherwise, it forwards
// the Error::ScryCrashed to the senior virtualization call.
if unsafe { context.scry_stack.raw_equals(scry_snapshot) } {
Err(Error::Deterministic(trace))
} else {
Err(err)
}
}
Error::NonDeterministic(_) => {
// We choose to restore the cache and scry stack even on NonDeterministic errors
// to keep the logic all in one place (as opposed to having the serf reset them
// manually ONLY for NonDeterministic errors).
context.cache = cache_snapshot;
context.scry_stack = scry_snapshot;
Err(err)
}
},
}
}
@ -190,14 +205,14 @@ pub mod util {
/** Consume $tone, produce $toon
*/
// XX: should write a jet_mook wrapper for this function
pub fn mook(context: &mut Context, tone: Cell, flop: bool) -> result::Result<Cell, JetErr> {
pub fn mook(context: &mut Context, tone: Cell, flop: bool) -> result::Result<Cell, Error> {
let tag = tone.head().as_direct()?;
let original_list = tone.tail();
if (tag.data() != 2) | unsafe { original_list.raw_equals(D(0)) } {
return Ok(tone);
} else if original_list.atom().is_some() {
return Err(JetErr::Fail(Error::Deterministic(D(0))));
return Err(Error::Deterministic(D(0)));
}
// XX: trim traces longer than 1024 frames
@ -235,17 +250,17 @@ pub mod util {
}
Right(_cell) => {
// 'tank: {
// if let Ok(tone) = mink(context, dat, cell.head()) {
// if let Some(cell) = tone.cell() {
// if cell.head().raw_equals(D(0)) {
// // XX: need to check that this is
// // actually a path;
// // return leaf+"mook.mean" if not
// break 'tank cell.tail();
// let scry = null_scry(context);
// if let Ok(tone) = mink(context, dat, cell.head(), scry) {
// if let Some(cell) = tone.cell() {
// if cell.head().raw_equals(D(0)) {
// // XX: need to check that this is
// // actually a path;
// // return leaf+"mook.mean" if not
// break 'tank cell.tail();
// }
// }
// }
// }
{
let stack = &mut context.stack;
let tape = tape(stack, "####");

View File

@ -7,6 +7,7 @@ use crate::noun::{Noun, Slots};
use std::ptr::{copy_nonoverlapping, null_mut};
/// key = formula
#[derive(Copy, Clone)]
pub struct Warm(Hamt<WarmEntry>);
impl Preserve for Warm {

View File

@ -1,22 +1,7 @@
use ares::hamt::Hamt;
use ares::interpreter::{interpret, Context};
use ares::jets::cold::Cold;
use ares::jets::hot::Hot;
use ares::jets::warm::Warm;
use ares::mem::NockStack;
use ares::newt::Newt;
use ares::noun::{IndirectAtom, Noun, D};
use ares::jets::hot::URBIT_HOT_STATE;
use ares::serf::serf;
use ares::serialization::{cue, jam};
use memmap::Mmap;
use memmap::MmapMut;
use std::env;
use std::fs::File;
use std::fs::OpenOptions;
use std::io;
use std::mem;
use std::ptr::copy_nonoverlapping;
use std::ptr::write_bytes;
fn main() -> io::Result<()> {
// debug
@ -47,61 +32,8 @@ fn main() -> io::Result<()> {
}
if filename == "serf" {
return serf();
return serf(URBIT_HOT_STATE);
}
let output_filename = format!("{}.out", filename);
let f = File::open(filename)?;
let in_len = f.metadata()?.len();
let mut stack = NockStack::new(8 << 10 << 10, 0);
let jammed_input = unsafe {
let in_map = Mmap::map(&f)?;
let word_len = (in_len + 7) >> 3;
let (mut atom, dest) = IndirectAtom::new_raw_mut(&mut stack, word_len as usize);
write_bytes(dest.add(word_len as usize - 1), 0, 1);
copy_nonoverlapping(in_map.as_ptr(), dest as *mut u8, in_len as usize);
mem::drop(in_map);
atom.normalize_as_atom()
};
let input = cue(&mut stack, jammed_input);
let input_cell = input
.as_cell()
.expect("Input must be jam of subject/formula pair");
let newt = Newt::new_mock();
let cache = Hamt::<Noun>::new();
let cold = Cold::new(&mut stack);
let warm = Warm::new();
let hot = Hot::init(&mut stack);
let mut context = Context {
stack,
newt,
cache,
cold,
warm,
hot,
scry_stack: D(0),
trace_info: None,
};
let result =
interpret(&mut context, input_cell.head(), input_cell.tail()).expect("nock failed");
if let Ok(atom) = result.as_atom() {
println!("Result: {}", atom);
}
let jammed_result = jam(&mut context.stack, result);
let f_out = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(output_filename)?;
f_out.set_len((jammed_result.size() << 3) as u64)?;
unsafe {
let mut out_map = MmapMut::map_mut(&f_out)?;
copy_nonoverlapping(
jammed_result.data_pointer() as *mut u8,
out_map.as_mut_ptr(),
jammed_result.size() << 3,
);
out_map.flush()?;
};
Ok(())
panic!("Ares can only run as a serf!");
}

View File

@ -2,7 +2,7 @@ use crate::hamt::Hamt;
use crate::interpreter;
use crate::interpreter::{inc, interpret, Error};
use crate::jets::cold::Cold;
use crate::jets::hot::Hot;
use crate::jets::hot::{Hot, HotEntry};
use crate::jets::list::util::{lent, zing};
use crate::jets::nock::util::mook;
use crate::jets::warm::Warm;
@ -38,28 +38,29 @@ struct Context {
}
impl Context {
pub fn new(snap_path: &PathBuf, trace_info: Option<TraceInfo>) -> Self {
pub fn new(
snap_path: &PathBuf,
trace_info: Option<TraceInfo>,
constant_hot_state: &[HotEntry],
) -> Self {
// TODO: switch to Pma when ready
// let snap = &mut snapshot::pma::Pma::new(snap_path);
let mut snapshot = DoubleJam::new(snap_path);
let mut stack = NockStack::new(1024 << 10 << 10, 0);
let newt = Newt::new();
let cache = Hamt::<Noun>::new();
let mut stack = NockStack::new(512 << 10 << 10, 0);
let cold = Cold::new(&mut stack);
let warm = Warm::new();
let hot = Hot::init(&mut stack);
let hot = Hot::init(&mut stack, constant_hot_state);
let (epoch, event_num, arvo) = snapshot.load(&mut stack).unwrap_or((0, 0, D(0)));
let mug = mug_u32(&mut stack, arvo);
let nock_context = interpreter::Context {
stack,
newt,
newt: Newt::new(),
cold,
warm,
warm: Warm::new(),
hot,
cache,
cache: Hamt::<Noun>::new(),
scry_stack: D(0),
trace_info,
};
@ -179,7 +180,7 @@ lazy_static! {
* This is suitable for talking to the king process. To test, change the arg_c[0] line in
* u3_lord_init in vere to point at this binary and start vere like normal.
*/
pub fn serf() -> io::Result<()> {
pub fn serf(constant_hot_state: &[HotEntry]) -> io::Result<()> {
// Register SIGINT signal hook to set flag first time, shutdown second time
signal_hook::flag::register_conditional_shutdown(SIGINT, 1, Arc::clone(&TERMINATOR))?;
signal_hook::flag::register(SIGINT, Arc::clone(&TERMINATOR))?;
@ -215,7 +216,7 @@ pub fn serf() -> io::Result<()> {
}
}
let mut context = Context::new(&snap_path, trace_info);
let mut context = Context::new(&snap_path, trace_info, constant_hot_state);
context.ripe();
// Can't use for loop because it borrows newt
@ -450,6 +451,7 @@ fn work_swap(context: &mut Context, job: Noun, goof: Noun) {
clear_interrupt();
let stack = &mut context.nock_context.stack;
context.nock_context.cache = Hamt::<Noun>::new();
// crud ovo = [+(now) [%$ %arvo ~] [%crud goof ovo]]
let job_cell = job.as_cell().expect("serf: work: job not a cell");
let job_now = job_cell.head().as_atom().expect("serf: work: now not atom");

View File

@ -29,7 +29,6 @@
"rustfmt"
"rust-src"
])
pkgs.autoconf-archive
pkgs.cargo-watch
pkgs.iconv
pkgs.llvmPackages.clang

View File

@ -1,5 +1,5 @@
{ stdenv, fetchFromGitHub, autoreconfHook, pkg-config, openssl, cryptopp, secp256k1, libaes_siv }:
let rev = "375fa7e6a730d8aa517ca981b2b7b505bf4e1103";
{ stdenv, fetchFromGitHub, autoreconfHook, autoconf-archive, pkg-config, openssl, cryptopp, secp256k1, libaes_siv }:
let rev = "43479c3262a11e20da5f6218f3b0b3d63931ceea";
in stdenv.mkDerivation {
pname = "urcrypt";
version = "git-${rev}";
@ -7,14 +7,14 @@ in stdenv.mkDerivation {
inherit rev;
owner = "urbit";
repo = "urcrypt";
hash = "sha256:1c3cqmwr5mys4v9y0834hxqfr6aynm2gav7730bjzfvrdc21ijqa";
hash = "sha256-GkhqvhDyhsdzjWpR8uqmhdRdhxdpmLGWXtIUZPAbWZs=";
};
preConfigure = ''
./autogen.sh
'';
# preConfigure = ''
# ./autogen.sh
# '';
nativeBuildInputs = [autoreconfHook pkg-config];
nativeBuildInputs = [autoreconfHook autoconf-archive pkg-config];
buildInputs = [openssl cryptopp secp256k1 libaes_siv];
}