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

Make sign tx testable #3022

Merged
merged 9 commits into from
Dec 24, 2021
Merged

Conversation

sevanspowell
Copy link
Contributor

@sevanspowell sevanspowell commented Nov 16, 2021

This PR is primarily about improving the testability of signTransaction, and providing a number of property tests.

  • In the signTransaction code path, pushed IO further to the edge of the program, enabling us to unit test more of the logic of signTransaction.
  • Provided a number of property tests to prove key points of signTransaction (it's witness adding behaviour)
    • Also, specifically added a test to assert that signTransaction maintains the script integrity hash of a transaction, for ADP-1047.
  • Expanded the transaction generator slightly to possibly generate ScriptWitnesses for TxIns.

Comments

Issue Number

ADP-1047 / ADP-1139

@sevanspowell sevanspowell force-pushed the feature/adp-1139/make-signTx-testable branch 2 times, most recently from 685aa39 to f284cf8 Compare November 19, 2021 07:46
@rvl
Copy link
Contributor

rvl commented Nov 24, 2021

@sevanspowell Could we please have a title and description for this PR?

@sevanspowell sevanspowell changed the title Feature/adp 1139/make sign tx testable Make sign tx testable Dec 14, 2021
@sevanspowell sevanspowell force-pushed the feature/adp-1139/make-signTx-testable branch 3 times, most recently from 2c557b0 to d4b02ee Compare December 20, 2021 04:59
@sevanspowell sevanspowell self-assigned this Dec 20, 2021
@sevanspowell sevanspowell marked this pull request as ready for review December 20, 2021 05:04
@sevanspowell sevanspowell force-pushed the feature/adp-1139/make-signTx-testable branch from d4b02ee to 5870069 Compare December 20, 2021 05:04
liftHandler $ W.signTransaction wrk wid pwd sealedTx
sealedTx' <- withWorkerCtx ctx wid liftE liftE $ \wrk -> liftHandler $ do
let
db = wrk ^. W.dbLayer @IO @s @k
Copy link
Contributor

Choose a reason for hiding this comment

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

We have those parts in almost all places in where. Shouldn't we have here also (just for consistency)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It won't work in this case, because wrk is not an argument to the outer function, wrk won't be in scope in the where block.

import qualified Cardano.Api.Shelley as Cardano
import qualified Cardano.Crypto.Hash.Blake2b as Blake2b
Copy link
Contributor

Choose a reason for hiding this comment

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

what about using here as Crypto ?

Copy link
Contributor

Choose a reason for hiding this comment

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

or just import without qualification like in other places in codebase?

-- necessary
signTransaction tl era keyLookup (rootKey, rootPwd) utxo =
let
rewardAcnt :: (XPrv, Passphrase "encryption")
Copy link
Contributor

Choose a reason for hiding this comment

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

what about exposing this function? It is used also in tests. Maybe it would be good to have code reuse

Copy link
Contributor

@paweljakubas paweljakubas left a comment

Choose a reason for hiding this comment

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

very nice properties added. It would be great to continue this path of testing when adding test coverage of decodeTx (in some forthcoming PRs).

  1. We see that signing can add some bits and this is tested.What about properties showing that signing will not change inps, outs, validity, ...., some things' ordering already present in the body?
  2. I see common patterns in properties. For example, we have the same structure:
case Cardano.THINGSupportedInEra era of
    Nothing -> 
    Just _ -> 

I wonder if there is a way to extract that common structure and reuse it in all property tests?

@sevanspowell
Copy link
Contributor Author

very nice properties added. It would be great to continue this path of testing when adding test coverage of decodeTx (in some forthcoming PRs).

1. We see that signing can add some bits and this is tested.What about properties showing that signing will not change inps, outs, validity, ...., some things' ordering already present in the body?

2. I see common patterns in properties. For example,  we have the same structure:
case Cardano.THINGSupportedInEra era of
    Nothing -> 
    Just _ -> 

I wonder if there is a way to extract that common structure and reuse it in all property tests?

Thanks for the feedback @paweljakubas! I've addressed a number of your points in subsequent commits.

Copy link
Contributor

@rvl rvl left a comment

Choose a reason for hiding this comment

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

Excellent work - these are really good tests to have! ⭐

Comment on lines +761 to +760
forAll (genTxInEra era) $ \tx -> do
let
Copy link
Contributor

Choose a reason for hiding this comment

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

May as well combine the let and where bindings at the deeper level...

Suggested change
forAll (genTxInEra era) $ \tx -> do
let
forAll (genTxInEra era) $ \tx -> bodyContentBefore == bodyContentAfter
where
tl = testTxLayer

(same goes for the other prop_ functions)

Comment on lines 629 to 633
conjoin $ (flip foldMap) elems $ \x ->
[ x `elem` xs
& counterexample ("actual set: " <> show xs)
& counterexample ("expected elem: " <> show x)
]
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think the foldMap is needed?

Suggested change
conjoin $ (flip foldMap) elems $ \x ->
[ x `elem` xs
& counterexample ("actual set: " <> show xs)
& counterexample ("expected elem: " <> show x)
]
counterexample ("actual set: " <> show xs) $ conjoin
[ x `elem` xs & counterexample ("expected elem: " <> show x)
| x <- elems ]

Comment on lines +380 to +381
forAllEras (\era -> it ("signTransaction adds reward account witness when necessary (" <> show era <> ")") $
property (prop_signTransaction_addsRewardAccountKey era))
Copy link
Contributor

Choose a reason for hiding this comment

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

I was thinking that it would be nice to have the property description/right beside the property definition, but still exposing the Property as a standalone function. Something like this...

Suggested change
forAllEras (\era -> it ("signTransaction adds reward account witness when necessary (" <> show era <> ")") $
property (prop_signTransaction_addsRewardAccountKey era))
describe desc_signTransaction_addsRewardAccountKey $
forAllEras $ \era -> it (show era) $
property (prop_signTransaction_addsRewardAccountKey era))
-- ... --
desc_signTransaction_addsRewardAccountKey = "signTransaction adds reward account witness when necessary" :: String

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agree, could be cool. But I wouldn't want these to be the only tests that do it.

rootK = first liftRawKey rootXPrv

rawRewardK :: (XPrv, Passphrase "encryption")
rawRewardK = (getRawKey $ deriveRewardAccount (snd rootK) (fst rootK), snd rootK)
Copy link
Contributor

Choose a reason for hiding this comment

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

If we find that tests are taking too long to run due to key generation, we could shift these things up into a precooked record of key inputs.

[mkShelleyWitness txBody rawRewardK]

checkCoverage $
expectedWits `checkSubsetOf` (getSealedTxWitnesses sealedTx')
Copy link
Contributor

Choose a reason for hiding this comment

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

Cool. I was wondering whether the reward account xpub could be used to verify new witnesses, but it seems easier and more effective to just generate the witness directly, as you have done.

- For signTransaction:
  - Move IO operations out of the wallet layer and into the server handler. We
    want to move IO operations to the edge of our program, in this case, the
    "edge" is our server handler. Doing so makes the wallet layer easier to
    test.
- This update allows the spending witness for a TxIn to be a script witness or a
  key witness. Previously only key witnesses were supported.
- Add the following property tests for signTransaction:
  - adds the reward account witness when necessary
  - adds extra key witnesses when necessary
  - adds tx in witnesses when necessary
  - adds collateral witnesses when necessary
  - never removes witnesses
- Add tests to ensure signTransaction doesn't modify TxBody.
- Make "checkSubsetOf" test more concise and reusable.
@sevanspowell sevanspowell force-pushed the feature/adp-1139/make-signTx-testable branch from bc22af0 to 5351ce1 Compare December 23, 2021 09:42
@sevanspowell
Copy link
Contributor Author

bors try

iohk-bors bot added a commit that referenced this pull request Dec 24, 2021
@iohk-bors
Copy link
Contributor

iohk-bors bot commented Dec 24, 2021

try

Build succeeded:

@sevanspowell
Copy link
Contributor Author

bors r+

@sevanspowell
Copy link
Contributor Author

bors cancel

@iohk-bors
Copy link
Contributor

iohk-bors bot commented Dec 24, 2021

Canceled.

@sevanspowell
Copy link
Contributor Author

bors r+

@iohk-bors
Copy link
Contributor

iohk-bors bot commented Dec 24, 2021

Build succeeded:

@iohk-bors iohk-bors bot merged commit 2cb11cc into master Dec 24, 2021
@iohk-bors iohk-bors bot deleted the feature/adp-1139/make-signTx-testable branch December 24, 2021 02:41
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.

3 participants