Info

Download ZIP (15.6 KB)

Testing and Issues

You can test this entry and submit issues during the testing period of the Blockchain Contest contest.

Entries with serious issues will not be able to win the contest, but even minor issues might be important for overall results.

Voting

44

Comments

Multi-signature wallet smart-contract

Creates a new multi-signature wallet (at least K of N signatures are required for an order to be processed by the multisig wallet). N can be from 1 to 100. K can be from 1 to 100, but must be lower or equal N.
1
Interface methods:

✓ seqno: return a current seqno value of a smart contract (stored in persistent storage);

✓ orders: return list of ALL pending orders from a persistent storage of a smart contract;

✓ orders_signature_check (arguments: int direction, int key_id):

direction: can be -1 or 0. If -1 user will get all pending orders, that signed by chosen private key. If 0 user will get all pending orders, NOT SIGNED by chosen private key; 

key_id: can be from 1 to 100. It is an ID of a private/public keypair. For example, user has created a smart contract wallet with 5 public/private key pairs, so he has private key files like: 'new-wallet1.pk', 'new-wallet2.pk', ... , 'new-wallet5.pk'. So ID of a first private key is 1, second is 2 and so on, until last value - 5.
1
Interface scripts:

✓ new-wallet.fif - to create of a new wallet smart contract; all N private keys are generating (or loading from files like 'new-wallet<Y>.pk', where Y is ID of a key from 1 to 100) at the moment of a script launch;

✓ send-order.fif - to create (BoC files with serialized) external messages with completely new orders; by the way, using my script you can sign a message with ANY NUMBER OF SIGNATURES by only one startup of a script;

✓ parse-order.fif - to extract and show the internal message (especially its destination address and value) and the list of signatures from a previously serialized external messages (loaded from a file);

✓ add-signatures.fif - to add new signatures to such external messages using a local private key file/files; by the way, using my script you can add ANY NUMBER OF SIGNATURES by only one startup of a script;
1
✓ merge-orders.fif - to merge two external messages with the same body, but with different signature sets, into one external message with the union of these signature sets;

✓ generate-order.fif - to create and sign a "new order" external message corresponding to a partially signed order recovered from the current state of the blockchain using one of the get-methods.
1
You have not added any comments yet...
by rating

Issues

Magic Python Nov 4, 2019 at 09:38
plus:
All required features are implemented.
Good performance (0.06G for a transfer with n=16, k=10).

minus:
Aways checks all pending orders. Could lead to quadratic time complexity.
11
Earnest Gnu Nov 4, 2019 at 20:02
Thank you very much for your review!
I am fully agree with you ;)
Magic Python Oct 16, 2019 at 11:39
accept_message() is called before any signature was checked.
2
Earnest Gnu Oct 17, 2019 at 20:08
Yes, you are right! That's my fault, when checking did not notice this...

As I see right now, the best solve of this issue - to call accept_message() after FIRST SUCCESSFULL SIGNATURE CHECK. And also to make throw_if() when there is 0 successful checked signatures.

These are just a few lines of code... Unfortunately, I didn’t notice this problem when testing a smart contract. 
I focused on checking ALL wallet scenarios described in the task from Telegram - and really fixed all the possible bugs here - but automatically have skipped this error ...
> As I see right now, the best solve of this issue - to call accept_message() after FIRST SUCCESSFULL SIGNATURE CHECK

No, you cannot. Once you accept message no exceptions can be thrown because that would revert storage (including seqno). I can then replay that message many times draining funds.

Here is an example contract that can never get past seqno 1 and will loose funds processing every message https://gist.github.com/rainydio/b59f20c2342c71c8d7df34e5795cf821
1
Earnest Gnu Oct 18, 2019 at 17:43
> No, you cannot. Once you accept message no exceptions can be thrown because that would revert storage (including seqno).

You are right here. But you do not carefully read my opinion above. There: "the best solve of this issue - to call accept_message() after FIRST SUCCESSFULL SIGNATURE CHECK. And also to make throw_if() when there is 0 successful checked signatures."

So, if there is no valid signatures, then accept_message() do not called, in the case if I solved this problem as I described above. So, if there is 0 valid signatures, there is 0 "accept_message()" calls -> we can make "throw_if(35, signatures_count == 0)" - something like that!

P.S.: About "draining funds" - I have understood it before ) I have said, that it is sad, that I have missed so simple issue.

This is really unpleasant, because the solution == a couple of lines of code (~2-4 in average)...
But what if I upon seeing your perfectly valid and signed message. I will send almost a copy of it, attempting to run in front of you. So that my message gets accepted instead of yours. But my message will contain huge dictionary of garbage after first real signature.

Any gas spent checking invalid signature can be used to launch an attack. That actually makes perfect sense, isn't it?
Earnest Gnu Oct 18, 2019 at 19:36
Fuh... i understood! Yes, you are here right, throw_if after signature check is a bad option! I do not thinked about such a scenario, but right now it’s clear for me, thank you!
Nobody added any issues yet...