-
Notifications
You must be signed in to change notification settings - Fork 122
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
Difference testing for 'core' protocol using model generated (heuristic) traces #315
Conversation
@@ -0,0 +1,12 @@ | |||
import { gen } from '../src/main.js'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the stuff in this folder necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The easiest way I know of to check the statement coverage of the trace generation on the model is to use yarn jest --collect-coverage
which requires a jest test.
I don't think we should give this up.
diff-models/core/src/common.ts
Outdated
invariantSnapshot: InvariantSnapshot; | ||
} | ||
|
||
interface Consequence { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to know more about what a Consequence is. Is it just the complete model state at any given time? Is it the parts of the model state that you care about checking, minus some "hidden" state?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, this is poorly documented. A consequence is a slice of model state relevant to the action that was last done. It's used for state comparison with the SUT and is helpful for understanding traces when reading through the actions.
Previously I had much more state here, but it's too much and make the jsons huge and any problems really hard to debug.
diff-models/core/jest.config.js
Outdated
@@ -0,0 +1,24 @@ | |||
export default { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost 100% certain this isn't needed. Can you remove all boilerplate files that you don't have a specific purpose for from this folder?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point to remove unnecessary files, but this one is very much needed. Jest will not run without this.
diff-tests/core/core_test.go
Outdated
s.Run(fmt.Sprintf("Trace num: %d", i), func() { | ||
// Setup a new pair of chains for each trace | ||
s.SetupTest() | ||
s.traces.CurrentTraceIx = i |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels really awkward. Can't you just iterate the list and pass the current trace to executeTrace?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be possible and I was just lazy. I'll check again. The thing is I want to keep the trace in 'global' state for diagnostics
diff-tests/core/core_test.go
Outdated
}() | ||
// Record information about the trace, for debugging | ||
// diagnostics. | ||
s.executeTrace() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where does the state after the action get checked (the "Consequence")? I see matchState
being called in the endAndBeginBlock
. Is that it? If it is, it seems odd to have your state being checked by one of your actions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We only compare committed block state because that's the only thing that matters at the end of the day. Anything that happens inside the block is implementation detail. I.e. as long as the same transactions result in the same committed block state we don't care what the go implementation actually does with those transactions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could check after every action but IMO that would bring unnecessary restrictions and make it harder to make the model abstract and to make the implementation efficient
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Second part of the review (still need to look over properties.ts). In general, the code should be commented better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Final part of the review for model.ts
and properties.ts
. See my comments below.
In general, amazing work @danwt 🚀
diff-tests/core/model/src/common.ts
Outdated
h: Record<Chain, number>; | ||
t: Record<Chain, number>; | ||
tokens: number[]; | ||
undelegationQ: Undelegation[]; | ||
delegatorTokens: number; | ||
power: (number | undefined)[]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add comments describing the field. Ditto throughout the model.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, latest model.ts has all fields commented, did you see?
I'm not sure about also commenting these parts. Tbh there probably a much better way to write the typescript than I have done, I need to study the language a bit more.
function powerProvider(block: CommittedBlock) { | ||
return _.range(NUM_VALIDATORS).map( | ||
(i) => | ||
block.invariantSnapshot.tokens[i] + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are all the tokens of validator i
regardless of whether it is bonded, unbonding, or unbonded. For the property, only bonded
and unbonding
validators are relevant (plus the unbonding undelegations that are captured in the next lines).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Useful catch!
interchain-security/diff-tests/core/model/src/properties.ts
Lines 189 to 208 in 07fa9a8
/** | |
* @param block to compute validator voting powers for | |
* @param hp is the earliest height for unbondings to account for | |
* @returns burnable voting power for each validator on the Provider chain | |
*/ | |
function powerProvider(block: CommittedBlock, hp: number): number[] { | |
return _.range(NUM_VALIDATORS).map((i) => { | |
let x = 0; | |
if (block.invariantSnapshot.status[i] !== Status.UNBONDED) { | |
x += block.invariantSnapshot.tokens[i]; | |
} | |
x += sum( | |
block.invariantSnapshot.undelegationQ | |
.filter((e) => e.val === i) | |
.filter((e) => hp <= e.creationHeight) | |
.map((e) => e.initialBalance), | |
); | |
return x; | |
}); | |
} |
Could we also add the new files to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work @danwt.
commit 7e639da Author: Daniel T <[email protected]> Date: Tue Sep 6 11:46:08 2022 +0100 Difference testing for 'core' protocol using model generated (heuristic) traces (#315) * blanket add difftest * (assum + trace pass) upstream sync setup * (full pass) shuffle directories * (all pass) minor tidyup simibc interface * (all pass) removes extraneous updateClients, deliverAcks * (pass) del extra UpdateClient in framework deliverAcks * (pass) tweak docstrings * (pass) remove chains map from framework * (pass) rename, doc simibc * (regression) tweaks * (pass) tweaks * (all pass) bump max gass * Track traces * Bumps ci configs * Try fix gosec * Try fix sonar * Try fix docker go build for 1.18 * README * Move diff artifacts to one dir * Update README * Update git LFS * Update sonar properties * Update README * Rename NetworkLink -> OrderedLink * Better docs main.ts * Docstring matchState * Removes some hardcoded nums in core_test.go * Adds couple of comments to core_test.go * Docstring for Consequence (.ts) * Update core package.json * Ensure typechecks enabled * Prettier on model.ts * DEL .editorconfig for ts model * del eslint * Bump sonar * Minor tidyup Traces struct go * Del unused field in properties.ts * new semantics: model.ts::expired -> willBeProcessedByStakingModule * Better comment DeliverPackets * Better comments for model class fields * Improve model staking class docstrings * Improve model staking class docstrings * Fix more_one_third_val_power_change event * Update testutil/simibc/ordered_link.go comment Co-authored-by: Shawn Marshall-Spitzbart <[email protected]> * Adds event.receive_slash_request_unbonded * Adds event.receive_slash_request_unbonded * Better docstring BlockHistory * Adds 4 new events to constants * Model endblock method split * Couple more comments model.ts * Comment model.ts * New traces * DEL traces * CP (debug) * (debug) offset adjustment * tentative, fix regression (debug) * kill prints * (tentative) property fix * Fixes BBCVP power provider * New traces * Del 2x prints * Comment property perf * rn power -> consumerPower in model * rn power -> consumerPower in driver * Removes outdated comment Co-authored-by: Daniel <[email protected]> Co-authored-by: Jehan <[email protected]> Co-authored-by: Shawn Marshall-Spitzbart <[email protected]>
* move to dir * other stuff * revert one change * Update Dockerfile * Squashed commit , with resolutions, of the following: commit 7e639da Author: Daniel T <[email protected]> Date: Tue Sep 6 11:46:08 2022 +0100 Difference testing for 'core' protocol using model generated (heuristic) traces (#315) * blanket add difftest * (assum + trace pass) upstream sync setup * (full pass) shuffle directories * (all pass) minor tidyup simibc interface * (all pass) removes extraneous updateClients, deliverAcks * (pass) del extra UpdateClient in framework deliverAcks * (pass) tweak docstrings * (pass) remove chains map from framework * (pass) rename, doc simibc * (regression) tweaks * (pass) tweaks * (all pass) bump max gass * Track traces * Bumps ci configs * Try fix gosec * Try fix sonar * Try fix docker go build for 1.18 * README * Move diff artifacts to one dir * Update README * Update git LFS * Update sonar properties * Update README * Rename NetworkLink -> OrderedLink * Better docs main.ts * Docstring matchState * Removes some hardcoded nums in core_test.go * Adds couple of comments to core_test.go * Docstring for Consequence (.ts) * Update core package.json * Ensure typechecks enabled * Prettier on model.ts * DEL .editorconfig for ts model * del eslint * Bump sonar * Minor tidyup Traces struct go * Del unused field in properties.ts * new semantics: model.ts::expired -> willBeProcessedByStakingModule * Better comment DeliverPackets * Better comments for model class fields * Improve model staking class docstrings * Improve model staking class docstrings * Fix more_one_third_val_power_change event * Update testutil/simibc/ordered_link.go comment Co-authored-by: Shawn Marshall-Spitzbart <[email protected]> * Adds event.receive_slash_request_unbonded * Adds event.receive_slash_request_unbonded * Better docstring BlockHistory * Adds 4 new events to constants * Model endblock method split * Couple more comments model.ts * Comment model.ts * New traces * DEL traces * CP (debug) * (debug) offset adjustment * tentative, fix regression (debug) * kill prints * (tentative) property fix * Fixes BBCVP power provider * New traces * Del 2x prints * Comment property perf * rn power -> consumerPower in model * rn power -> consumerPower in driver * Removes outdated comment Co-authored-by: Daniel <[email protected]> Co-authored-by: Jehan <[email protected]> Co-authored-by: Shawn Marshall-Spitzbart <[email protected]> * DEL extra files Co-authored-by: Daniel <[email protected]> Co-authored-by: Daniel T <[email protected]>
Overview
Version 3 of a differential testing approach to testing the 'core' aspects of the Interchain Security system.
This PR contains three major components
All of the included files are necessary for a full understanding, however, some files contain the most information.
Please find a README file which is contained within the Typescript project. This readme file explains the intentions of the work, and gives usage instructions for adapting the model, and generating traces using it.
model.ts
contains the majority of the semantic logic used for modelling the system.main.ts
contains the entry point for interacting with the model and generating traces.properties.ts
contains the code used to check some properties of the protocol, most importantly thebond based consumer voting power
property.core_test.go
contains the core driver code used to read json traces and execute them against real instances of the system, simulated using ibc-go/testing. The pivotal unit test is here. There is a second unit test here which serves only to check that the driver is written correctly.I suggest to read the README first, and then decide which to read next based on your interest.
Gathering feedback
All feedback and especially criticism is welcome!
I'm aware of some major issues already but I think now is a sensible time to merge and to leave improvements to future work.
Future work and issue
Code quality
Test capabilities