program lock_multisig

// Neptune 2-of-3 Multisig Lock Script
//
// Requires any 2 of 3 keyholders to authorize spending.
// Each keyholder has a secret whose hash is committed in the
// program. The prover supplies 2 secrets and a bitmask indicating
// which 2 of the 3 keys are used.
//
// Public input:  kernel MAST hash (5 fields)
// Secret input:  3 auth hashes (divine5 ร— 3), bitmask (1 field),
//                2 secrets (divine ร— 2)
fn verify_key(secret: Field, expected_hash: Field) {
    let d: Digest = hash(secret, 0, 0, 0, 0, 0, 0, 0, 0, 0)
    let (h0, _, _, _, _) = d
    assert_eq(h0, expected_hash)
}

fn main() {
    // Three keyholder auth hashes โ€” committed via program hash.
    let key0_hash: Digest = divine5()
    let key1_hash: Digest = divine5()
    let key2_hash: Digest = divine5()
    let (k0, _, _, _, _) = key0_hash
    let (k1, _, _, _, _) = key1_hash
    let (k2, _, _, _, _) = key2_hash
    // Bitmask: which keys sign (exactly 2 bits set).
    // 3 = keys 0+1, 5 = keys 0+2, 6 = keys 1+2
    let mask: Field = divine()
    if mask == 3 {
        let s0: Field = divine()
        let s1: Field = divine()
        verify_key(s0, k0)
        verify_key(s1, k1)
    } else if mask == 5 {
        let s0: Field = divine()
        let s2: Field = divine()
        verify_key(s0, k0)
        verify_key(s2, k2)
    } else if mask == 6 {
        let s1: Field = divine()
        let s2: Field = divine()
        verify_key(s1, k1)
        verify_key(s2, k2)
    } else {
        assert(false)
    }
    // Bind proof to this transaction.
    let _kernel: Digest = pub_read5()
}

Local Graph