Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix ife input spend challenge using wrong index #593

Merged
merged 8 commits into from
Mar 6, 2020
Merged

Conversation

boolafish
Copy link
Contributor

@boolafish boolafish commented Mar 4, 2020

Note

This is the fix for issue: omisego/security-issues#15

  1. Add py tests to cover the scenerio
  2. fix the contract using the right index

Test

The test in this commit would fail before making the contract change. VM Exception while processing transaction: revert Output index out of bounds

This is an effort to add tests to cover challenge IFE input spent on all output indexes.
We found a bug that we are using wrong indexes in contract code.

But, this test end up does not break the existing contract as although it is attracting wrong output, we are only
using the output type with that output. With current system, we only have 1 output type for payment tx. As a result
it failed to break with this test..

https://github.com/omisego/security-issues/issues/15
Test in previous commit failed to cover the situation that would fail the contract with wrong index. This one
test the index from another side (challenge input index) and it works to break the contract.

Without the fix, it would result in "VM Exception while processing transaction: revert Output index out of bounds" error
from the EVM.
This commit is the fix on the contract for input spend challenge
@@ -20,6 +21,97 @@ def test_challenge_in_flight_exit_input_spent_should_succeed(testlang, period):
assert not in_flight_exit.input_piggybacked(0)



@pytest.mark.parametrize("num_outputs", [1, 2, 3, 4])
def test_challenge_in_flight_exit_should_succeed_for_all_output_indexes(testlang, num_outputs):
Copy link
Contributor Author

@boolafish boolafish Mar 4, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this test (surprisingly) actually would not fail even without the fix

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think not that surprisingly:

  • the problem was with checking just the spending condition
  • the index of the double spend in the challenge tx is always 0, where owner[0] signs
  • this coincides with the input transaction having owner[0]'s output on position 0.

So even though the double spend would not necessarily be of owner[0] and at position 0, the spending condition would always pass.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this coincides with the input transaction having owner[0]'s output on position 0.

Yes, but other than 0, the index would mismatch. I was expecting this to break.

However because we are only using outputType from the output we retrieve, even the index mismatches, it would end up being same output type since we have only one type atm.



@pytest.mark.parametrize("challenge_index", [0, 1, 2, 3])
def test_challenge_in_flight_exit_should_succeed_for_all_challenge_indexes(testlang, challenge_index):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the test that would actually fail

Copy link
Contributor

@pik694 pik694 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdobacz has also suggested to prepare a parametrizable test that would check all the possibilities - check each input, output index etc.

@pytest.mark.parametrize("period", [1, 2, 4])
def test_challenge_in_flight_exit_input_spent_should_succeed(testlang, period):
@pytest.mark.parametrize("period", [1, 2, 3, 4])
def test_challenge_in_flight_exit_input_spent_should_succeed_in_all_periods(testlang, period):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this test does not check whether we really can challenge in each period - it forwards just to the second and then challenges. Additionally, the comment above the test does not match now.

Copy link
Contributor Author

@boolafish boolafish Mar 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated the test name a bit, can you check again?

Actually, the name seems correct to me.

it forwards just to the second and then challenges

No, it actually forward to the period. Or at least, it forward to period * 1/2 MIN_EXIT_PERIOD

Comment on lines 32 to 34
for i in range(0, num_outputs):
owners.append(testlang.accounts[i])
outputs.append((testlang.accounts[i].address, NULL_ADDRESS, tx_output_amount))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we extract it into a separate function? I know that such code is commonly used (which is bad), but this test is quite long and needs simplification so that it is easier to read.

Copy link
Contributor Author

@boolafish boolafish Mar 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the way a bit, and also just realize that owners list is totally useless as the spend_utxo function would be only using the first owner when signing under the hood.

Please re-review whether your comment still hold with my change?

@pdobacz pdobacz mentioned this pull request Mar 4, 2020
1 task
@pdobacz
Copy link
Contributor

pdobacz commented Mar 4, 2020

Suggesting a parametrized test for one of the other cases (ChallengeIFEOutputSpent) here #594, if this is useful

@pdobacz
Copy link
Contributor

pdobacz commented Mar 4, 2020

On the fix itself: it looks on point, I'd however go for the other similar test cases, like the one I suggested (see #594). Such a test would fit for:

1. kudo Piotr's idea to parametize the inputs for indexes at once
1. rename the period test a bit as just realize that it can work with period 0 too

Piotr's PR: #594
Copy link
Contributor

@pdobacz pdobacz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! As agreed, #594 will go separately, straight to master, same as other test expansions suggested!

Copy link
Contributor

@kevsul kevsul left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@boolafish boolafish merged commit 8b408d9 into master Mar 6, 2020
@boolafish boolafish deleted the boolafish/fix_ife branch March 6, 2020 00:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants