module os.neptune.standards.plumb
// PLUMBv2: full-Digest authorities and atomic same-sibling tree transitions.
// Normative contract: Trident reference/plumb-v2.md. Legacyv1 is experimental.
pub fn tree_depth() -> Field { 20 }
pub fn pair(left: Digest, right: Digest) -> Digest {
let (a,b,c,d,e) = left
let (f,g,h,i,j) = right
hash(a,b,c,d,e,f,g,h,i,j)
}
pub fn is_zero(value: Digest) -> Bool {
let (a,b,c,d,e) = value
if a == 0 {
if b == 0 {
if c == 0 {
if d == 0 { e == 0 } else { false }
} else { false }
} else { false }
} else { false }
}
pub fn hash_config(
admin_auth: Digest, pay_auth: Digest, lock_auth: Digest,
mint_auth: Digest, burn_auth: Digest,
pay_hook: Field, lock_hook: Field, update_hook: Field,
mint_hook: Field, burn_hook: Field
) -> Digest {
let a = pair(admin_auth,pay_auth)
let b = pair(lock_auth,mint_auth)
let hooks = hash(pay_hook,lock_hook,update_hook,mint_hook,burn_hook,2,2,0,0,0)
let c = pair(burn_auth,hooks)
pair(pair(a,b),c)
}
pub fn verify_config(
admin_auth: Digest, pay_auth: Digest, lock_auth: Digest,
mint_auth: Digest, burn_auth: Digest,
pay_hook: Field, lock_hook: Field, update_hook: Field,
mint_hook: Field, burn_hook: Field, expected: Digest
) {
assert_digest(hash_config(admin_auth,pay_auth,lock_auth,mint_auth,burn_auth,
pay_hook,lock_hook,update_hook,mint_hook,burn_hook),expected)
}
pub fn verify_auth(authority: Digest) {
assert(is_zero(authority) == false)
let secret: Digest = divine5()
let (a,b,c,d,e) = secret
assert_digest(hash(a,b,c,d,e,2,1,0,0,0),authority)
}
// Hook IDs are requests to the integrating verifier, not verified hook proofs.
pub fn signal_hook(hook: Field) {
if hook == 0 { } else { pub_write(hook) }
}
pub fn assert_non_negative(value: Field) { let _: U32 = as_u32(value) }
pub fn next_nonce(nonce: Field) -> Field {
assert_non_negative(nonce)
let next = nonce + 1
assert_non_negative(next)
next
}
pub fn check_index(id: Field, index: U32) {
assert((id == 0) == false)
assert_eq(id,as_field(index))
assert(index < as_u32(1048576))
}
pub fn empty_leaf() -> Digest { hash(0,0,0,0,0,0,0,0,2,0) }
// Recompute old and new roots from exactly the same20 sibling Digests.
// Return the new root only after authenticating the original leaf and index.
pub fn update_leaf(old_leaf: Digest, new_leaf: Digest, old_root: Digest, index: U32) -> Digest {
assert(index < as_u32(1048576))
let mut old_node: Digest = old_leaf
let mut new_node: Digest = new_leaf
let mut idx: U32 = index
for level in 0..20 bounded 20 {
let sibling: Digest = divine5()
let (parent, side): (U32,U32) = idx /% as_u32(2)
if side == as_u32(0) {
old_node = pair(old_node,sibling)
new_node = pair(new_node,sibling)
} else {
old_node = pair(sibling,old_node)
new_node = pair(sibling,new_node)
}
idx = parent
}
assert(idx == as_u32(0))
assert_digest(old_node,old_root)
new_node
}