I have problem with Counter-Party Signature on one Entry - Multi Signature Entry

My issue is straightforward. I have one Public entry and 2 parties supposed to sign it and my hApp need to validate if each party signed the entry or not.

Example: Alice create a public entry (so it automatically signed by Alice since he is the creator), then Bob would have the Address of entry and try to sign it as well. at the end I have a function which receive an entry address and validate that if this AGENT_ADDRESS already signed it or not.

I create a simple example in my github and you can see. just pull and read and run the test.

As you can see in test, Alice create a public entry, is_signed_by_me returns true for Alice and Bob which is not correct. Bob hasn’t signed the entry.

Source Code
  pub fn sign_entry(entry_address: Address) -> ZomeApiResult<Address> {
        let entry = hdk::get_entry(&entry_address).unwrap().unwrap();
        let signature = hdk::sign(entry_address.clone())?;
        let my_provenance = Provenance::new(AGENT_ADDRESS.clone(), Signature::from(signature));
        let options = CommitEntryOptions::new(vec![my_provenance]);
        let address = hdk::commit_entry_result(&entry, options)?;
        Ok(address.address())
    }

pub fn is_signed_by_me(entry_address: Address) -> ZomeApiResult<bool> {
    let signature = hdk::sign(entry_address.clone())?;
    let provenance = Provenance::new(AGENT_ADDRESS.clone(), Signature::from(signature));
    let validate_signature = hdk::verify_signature(provenance.clone(), entry_address.clone())?;
    if !validate_signature {
        return Err(ZomeApiError::from(String::from(
            "Error: You did not sign this entry",
        )));
    } else {
        Ok(true)
    }
}

@pauldaoust @freesig @RobLyon

Hi @hedayat — verify_signature checks that a signature is valid, not whether it exists on the entry in the DHT. In order to check whether the entry is signed by you, you’ll need to check the sources on the entry as it appears on the DHT. You can use get_entry_result and specify headers: true in the options struct. Then, in the returned result, you iterate through all the provenances on all the headers, looking for your own AGENT_ADDRESS. Hope that helps; let me know if you get stuck!

1 Like

Thanks @pauldaoust, I got the point and could overcome my obstacle.

I have another question. Alice creates a public entry. is there any way that he can give the permission to Bob to just find that entry by address and Sign the public entry. without any changes in entry?

In general terms, what is the best strategy to implement a multi-signature entry?

I updated my repository again, you can take a look at test scenario.
Alice updating the entry with valid signature of Bob, but finally Bob provenace does not appear in headers.provenances:

    let options = CommitEntryOptions::new(vec![provenance, my_provenance]);
    let entry = hdk::get_entry(&entry_address).unwrap().unwrap();
    let address = hdk::commit_entry_result(&entry, options)?;

@hedayat it definitely depends on the scenario (isn’t that an annoying answer? but it’s true :slight_smile: )

When you’re doing something like contract signing, you might very well need commit-time proof that someone agreed to your contract. That’s when you’d send the entry to the other signer via node-to-node messaging, have them send back the signature, and then commit their signature to your own entry/header pair using the code you posted above.

But there are scenarios where that wouldn’t work. Let’s say Alice wants Bob to sign her contract, but they live on opposite sides of the world and their computers aren’t on at the same time. So they can’t use node-to-node messaging. Here’s where Alice might want Bob to “find that entry by address and sign [it] without any changes in entry”. It happens when Bob commits the exact same entry to his source chain and publishes it.

In both scenarios, it’s one entry on the DHT. But in scenario one:

  • The entry has a single header with two provenances (although it’s probably a good idea to get Bob to also commit the entry to his chain and include Alice’s signature, in which case it’ll have two headers with the same two provenances).
  • It’s more final — everyone who needs to sign it has signed it at commit-time.

Whereas with scenario two:

  • It’s less final, more eventually-consistent (that is, it isn’t guaranteed to come to finality, but in real-life terms it’s got a pretty good chance, and there aren’t any synchronisation conflicts to worry about).
  • The entry has two headers with one provenance each (one for Alice’s commit, one for Bob’s commit).

@pauldaoust thanks for the advice. I implemented and tested both scenarios. But I didn’t receive expected result. always the signature of Entry creator is sitting in the headers.
It seems we need to wait for the next release of hdk core.

Hi @hedayat – when you say the signature of the entry creator is sitting in the headers, do you mean that it’s the only header? It should always be the first signature under Provenances, but if it’s the only one, even after passing other signatures… yeah, that’s a Holochain bug then!