iotaledger / iota.py

PyOTA: The IOTA Python API Library
https://docs.iota.org/
MIT License
345 stars 124 forks source link

Bundle with multisig transaction fails verification with "Transaction 1 has invalid signature (using 6 fragments)" #218

Open rav1112 opened 5 years ago

rav1112 commented 5 years ago

I am using MultiSignature Code. When I am preparing transfer, I am the error --- ValueError: Request failed validation ({'multisigInput': ['wrong_type']}) (exc.context["filter_errors"] contains more information). What can be the issue as I am inserting proper multisignature address

todofixthis commented 5 years ago

Hi @rav1112 the exception has a context attribute attached to it which contains more information:

from pprint import pprint

try:
    ...
except Exception as exc:
    context = getattr(exc, "context", {})
    pprint(context)
    raise
rav1112 commented 5 years ago

I tried with above exception i got ----

 {'filter_errors': {'multisigInput': [{'code': 'wrong_type', 'message': 'Address is not valid (allowed types: MultisigAddress).', 'context': {'value': Address(------XXXXXXXX-------'), 'filter': 'Type(MultisigAddress, allow_subclass=True)', 'key': 'multisigInput', 'replacement': None, 'code': 'wrong_type'}, 'exc_info': None}]}}

I have pass multisignature value in string type so that's why it is coming i think.... May I know how to convert string to MultisigAddress.

todofixthis commented 5 years ago

Gotcha. Hmmmm, I think the only reason why MultisigAddress (or subclass) is required is to protect against attempting to create a multisig transfer from a non-multisig address. This is one of those cases where the behaviour is technically possible, but "probably" wrong (if you have a non-multisig address, then the prepare_transfer() method will get the job done, and it's simpler to use).

The only other reason I can think of why a MultisigAddress might be required is because it keeps track of the digests used to create it, but I can't find anything in the code that would suggest that this is significant.

Try constructing a MultisigAddress manually.

multisig_input = MultisigAddress(
    trytes="ADDY",
    digests=[],  # list of `Digest` objects, if you have them
    balance=42,  # optional
)

# If you set `digests` to an empty list, you will need to
# manually set the security level.  This must be equal to
# the sum of the security levels of each of the digests
# used to build the multisig address.
multisig_input.security_level = 10

api.prepare_multisig_transfer(transfers, multisig_input, change_address)
rav1112 commented 5 years ago

Thanks for your support

rav1112 commented 5 years ago

['Transaction 1 has invalid signature (using 6 fragments).'] I understand that signature are invalid. But I want to understand regarding (using 6 fragments). Can you please explain regarding this? Also what can be the issue?

todofixthis commented 5 years ago

Sure! The "using 6 fragments" part indicates that the signature was split across 6 transactions (fragments) within the bundle (see https://iota.stackexchange.com/a/147/283 for more info).

"invalid signature" is a frustrating error to troubleshoot, because there's really no way to get any forensic data. The validator ran the signature through a kerl sponge, and the end result was different than the expected value. By design, it's mathematically imposible to reverse the computation to find out where things went wrong.

If this is coming from a multisig address, the invalid signature is likely caused by one of the following problems:

rav1112 commented 5 years ago

Ya Error is coming from multisig process. I have double check the conditions but not able to figure out what will be the problem. I am doing N-of-N Signing Process withe private keys. But I am not able to transfer the value. And I am doing this process in my local with same computer. May I know what steps I can take now?

todofixthis commented 5 years ago

Hmm. The next thing I would try is re-creating the MultisigAddress from scratch, following the instructions at https://pyota.readthedocs.io/en/latest/multisig.html#generating-multisignature-address.

Then compare these values to look for discrepancies:

rav1112 commented 5 years ago

I recreated multisignature address from the scratch but then too it is giving same error i.e. Transaction 1 has invalid signature (using 6 fragments). after signing the process. I have follow the same process of https://pyota.readthedocs.io/en/latest/multisig.html#generating-multisignature-address.

todofixthis commented 5 years ago

Oooh... ok that's... concerning. This might be indicative of a bug in PyOTA. Could you try re-creating the multisig address using the JS lib and see if you get a different result?

rav1112 commented 5 years ago

In JS lib, It is giving same result for digests and multisignature address. But after signing and validated it is transfering the value properly ... while in pyota it gives Transaction 1 has invalid signature (using 6 fragments) after signing and validated .

todofixthis commented 5 years ago

Thanks @rav1112 ! This is def a bug in PyOTA then; I'm re-opening this one.

Unit tests should have caught this; now I'm wondering what we missed 🙀 I'll take a quick peek at the tests to see if we have a case that covers this scenario.

todofixthis commented 5 years ago

Just to confirm, do the transactions in the bundle have signatures attached to them (i.e., does the code also invoke the sign_input_transactions() method for each private key)?

rav1112 commented 5 years ago

Yes the bundle have Signature attached to the transactions. Its something while validate_signature_fragments() it returns false which means return actual_public_key == public_key.as_trits() is false basically it is not satisfying the condition.

todofixthis commented 5 years ago

Awesome, thanks! Will look into this!!

rav1112 commented 5 years ago

Ok ! Thanks! Let me know once it is done! Also can you tell me the tentative date that how long it can take as I m stuck in one of the functionality?

lzpap commented 4 years ago

Same issue as #276 , problem is in PyOTA multisig signing process somewhere...