-
Notifications
You must be signed in to change notification settings - Fork 138
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
feat: implement hss sign schedule function #16789
base: develop
Are you sure you want to change the base?
Conversation
Signed-off-by: Luke Lee <[email protected]>
Coverage summary from CodacySee diff coverage on Codacy
Coverage variation details
Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: Diff coverage details
Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: See your quality gate settings Change summary preferencesCodacy stopped sending the deprecated coverage status on June 5th, 2024. Learn more |
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.
Overall LGTM, ty @lukelee-sl !
Left a few suggestions for improvement but all up to you
...-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/TransactionProcessor.java
Outdated
Show resolved
Hide resolved
hedera-node/hedera-config/src/main/java/com/hedera/node/config/data/ContractsConfig.java
Show resolved
Hide resolved
.../app/service/contract/impl/exec/systemcontracts/hss/signschedule/SignScheduleTranslator.java
Show resolved
Hide resolved
.../app/service/contract/impl/exec/systemcontracts/hss/signschedule/SignScheduleTranslator.java
Outdated
Show resolved
Hide resolved
Signed-off-by: Luke Lee <[email protected]>
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.
LGTM
…into 16700-implement-sign-schedule
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.
Will come back for tests (bdd) later. Some questions for now.
assertThat(derivedVerifier.authorizingSimpleKeys()).containsExactly(A_CONTRACT_ID_KEY); | ||
assertThat(derivedVerifier.authorizingSimpleKeys()).isNotEmpty(); | ||
} | ||
|
||
@Test | ||
void keyVerifierOnlySupportsKeyVerification() { |
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.
Given this test what does this test's name mean? (I know you didn't name it, but you could fix the name anyway, if I'm not just confused.)
...-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/TransactionProcessor.java
Show resolved
Hide resolved
...-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/TransactionProcessor.java
Show resolved
Hide resolved
@@ -258,8 +258,9 @@ private InvolvedParties computeInvolvedParties( | |||
} | |||
|
|||
private boolean contractNotRequired(@Nullable final HederaEvmAccount to, @NonNull final Configuration config) { | |||
final var maybeGrandfatheredNumber = | |||
(to == null) ? null : to.isTokenFacade() ? null : to.hederaId().accountNumOrThrow(); | |||
final var maybeGrandfatheredNumber = (to == null || to.isTokenFacade() || to.isScheduleTxnFacade()) |
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.
Also I was curious why this change didn't have a corresponding test to modify in TransactionProcessorTest
but I see it's basically not unit-testable: It's a private
method nested 3 levels deep in calls from other private
methods. You basically can only test this little method by starting at the top-level method in this class (processTransaction
) and maneuvering to drive private method computeInvolvedParties
to the exact required state and inspecting the resulting HederaEvmTransactionResult
. After mocking all dependencies of actually doing the transaction you're submitting and also for computing gas.
private
methods make classes untestable, most often, in my experience. And it doesn't add much in the way of "safety" in terms of not using things that weren't meant to be public. If the original dev didn't want the stuff to be public he should have isolated it behind an interface for the public methods, leaving the formerly-private
methods available publicly in the ...Impl
so they could be tested.
@@ -63,7 +68,8 @@ public HssCallAttempt( | |||
@NonNull final VerificationStrategies verificationStrategies, | |||
@NonNull final SystemContractGasCalculator gasCalculator, | |||
@NonNull final List<CallTranslator<HssCallAttempt>> callTranslators, | |||
final boolean isStaticCall) { | |||
final boolean isStaticCall, | |||
@NonNull final Address originatorAddress) { |
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.
Should this be moved up, perhaps under senderAddress
?
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.
Michael, convinced me that originatorAddress is not really needed. I will remove it.
return gasOnly( | ||
haltResult( | ||
ERROR_DECODING_PRECOMPILE_INPUT, | ||
contractsConfigOf(frame).precompileHtsDefaultGasCost()), |
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.
Should there be a config for precompileHssDefaultGasGost
? (Hss)
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 don't think it is worth it to have a different gas cost for this for each system contract.
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.
Maybe should be renamed?
* An HSS call that simply dispatches a synthetic transaction body and returns a result that is | ||
* an encoded {@link ResponseCodeEnum}. | ||
*/ | ||
public class DispatchForResponseCodeHssCall extends AbstractCall { |
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.
So close to DispatchForResponseCodeHtsCall
and yet not close enough to derive from same abstract class. (Or is it close enough?)
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 didn't want all of the clutter if possible. Maybe I'll create an abstract class if it turns out the addition updaters are needed here.
.../app/service/contract/impl/exec/systemcontracts/hss/signschedule/SignScheduleTranslator.java
Show resolved
Hide resolved
} | ||
key = attempt.enhancement().nativeOperations().getAccountKey(attempt.originatorAccount()); | ||
if (key != null) { | ||
return Set.of(key); |
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.
What if this account key is not a simple key. Isn't this eventually what is sent to ChildDispatchFactory
where it becomes what's returned by a key verifiers authorizingSimpleKeys
? Wouldn't that mean it needs to be a simple key?
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 image that the key will be passed into the verifier
and as long as the verifier
can handle key lists for verification then it should work? It looks like the DefaultKeyVerifier
which is what I am passing does allow verification of things like key lists but not sure here. @tinker-michaelj ?
@@ -110,7 +110,7 @@ public class DispatchingEvmFrameState implements EvmFrameState { | |||
// The only exception is that the function selector for `redirectForScheduleTxn` (0x5c3889ca) | |||
// has been pre substituted before the ADDRESS_BYTECODE_PATTERN. | |||
private static final String SCHEDULE_CALL_REDIRECT_CONTRACT_BINARY = | |||
"6080604052348015600f57600080fd5b50600061016a9050775c3889cafefefefefefefefefefefefefefefefefefefefe600052366000602037600080366018016008845af43d806000803e8160008114605857816000f35b816000fdfea2646970667358221220d8378feed472ba49a0005514ef7087017f707b45fb9bf56bb81bb93ff19a238b64736f6c634300080b0033"; | |||
"6080604052348015600f57600080fd5b50600061016b9050775c3889cafefefefefefefefefefefefefefefefefefefefe600052366000602037600080366018016008845af43d806000803e8160008114605857816000f35b816000fdfea2646970667358221220d8378feed472ba49a0005514ef7087017f707b45fb9bf56bb81bb93ff19a238b64736f6c634300080b0033"; |
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 detect one letter in that hex string changed. Don't even know if it is the right change. I suggest again: This is the 4 byte hex selector that needs to be substituted into these three otherwise identical 147 byte hex strings. Can't we have code that takes the one true proxy binary and injects that selector into it producing these three static strings?
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.
well there's actually 2 changes. I see what I can do.
Signed-off-by: Luke Lee <[email protected]>
Signed-off-by: Luke Lee <[email protected]>
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.
LGTM (though there's still a question about simple keys remaining for completeness)
assertThat(derivedVerifier.authorizingSimpleKeys()).containsExactly(A_CONTRACT_ID_KEY); | ||
assertThat(derivedVerifier.authorizingSimpleKeys()).isNotEmpty(); |
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.
FYI, assertThat
has a "fluid" API, you can write
assertThat(derivedVerifier.authorizingSimpleKeys()).isNotEmpty().containsExactly(A_CONTRACT_ID_KEY);
(though in fact that's redundant in this particular case, don't need the isNotEmpty()
here)
(in general should be containsOnly
as even if this test had more then one element to be contained the order doesn't matter)
(just spitting out AssertJ stuff for posterity, don't even think about it.)
...-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/TransactionProcessor.java
Show resolved
Hide resolved
@@ -91,26 +91,40 @@ public class DispatchingEvmFrameState implements EvmFrameState { | |||
|
|||
private static final String ADDRESS_BYTECODE_PATTERN = "fefefefefefefefefefefefefefefefefefefefe"; | |||
|
|||
private static final String PROXY_PRE_BYTES = "6080604052348015600f57600080fd5b506000610"; |
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 do like this version better. I was actually thinking of something like this (two alternatives here, 1 and 2):
private static final String PROXY_PRE_BYTES = "6080604052348015600f57600080fd5b506000610";
private static final String PROXY_MID_BYTES = "905077";
private static final String PROXY_POST_BYTES =
"fefefefefefefefefefefefefefefefefefefefe600052366000602037600080366018016008845af43d806000803e8160008114605857816000f35b816000fdfea2646970667358221220d8378feed472ba49a0005514ef7087017f707b45fb9bf56bb81bb93ff19a238b64736f6c634300080b0033";
private static final BiFunction<String, String, String> constructProxy1 =
(@NonNull final String systemContractAddress, @NonNull final String functionSelectorHex) ->
PROXY_PRE_BYTES + systemContractAddress + PROXY_MID_BYTES + functionSelectorHex + PROXY_POST_BYTES;
private static final String PROXY_METHOD_TEMPLATE =
"6080604052348015600f57600080fd5b506000610%1$s905077%2$sfefefefefefefefefefefefefefefefefefefefe600052366000602037600080366018016008845af43d806000803e8160008114605857816000f35b816000fdfea2646970667358221220d8378feed472ba49a0005514ef7087017f707b45fb9bf56bb81bb93ff19a238b64736f6c634300080b0033";
private static final BiFunction<String, String, String> constructProxy2 =
(@NonNull final String systemContractAddress, @NonNull final String functionSelectorHex) ->
PROXY_METHOD_TEMPLATE.formatted(systemContractAddress, functionSelectorHex);
private static final String TOKEN_CALL_REDIRECT_CONTRACT_BINARY = constructProxy1.apply("0167", "618dc65e");
private static final String ACCOUNT_CALL_REDIRECT_CONTRACT_BINARY = constructProxy2.apply("016a", "e4cbd3a7");
Description:
Implements the
signSchedule
proxy contract function and theauthorizeSchedule
function for the Schedule system contract.Related issue(s):
Fixes #16700
Notes for reviewer:
A future pr will add additional BDD and unit test.
Checklist