-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
docs: add ADR 063: core API ADR + update app wiring ADR #12972
Conversation
* the core API doesn't implement *any* functionality, it just defines types | ||
* go stable API management principles are followed (TODO: link) | ||
|
||
Runtime modules which implement the core API are *intentionally* separate from the core API in order to enable 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.
will this work if a user does not want to use runtime/DI?
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 will work without DI. If someone wants to do manual wiring, codegen requires exported providers so manual app.go is totally possible.
Runtime basically encapsulates what is now BaseApp + module manager, and will extend these and eventually replace the current implementations (what we've called BaseApp 2.0 with ABCI++, etc). I'll add a bit more text to the ADR defining this.
So runtime will be necessary, but it will be possible to wire it manually, or use DI, or DI codegen which is like manual wiring that the framework does for you.
|
||
Historically modules have exposed their functionality to the state machine via the `AppModule` and `AppModuleBasic` | ||
interfaces which have the following shortcomings: | ||
* both `AppModule` and `AppModuleBasic` need to be defined which is counter-intuitive |
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.
WDYM?
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 distinction between features on AppModule
and AppModuleBasic
seems arbitrary. So does the use of the word "basic".
Historically modules have exposed their functionality to the state machine via the `AppModule` and `AppModuleBasic` | ||
interfaces which have the following shortcomings: | ||
* both `AppModule` and `AppModuleBasic` need to be defined which is counter-intuitive | ||
* apps need to implement the full interfaces, even parts they don't need |
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.
Not technically, as they can define no-ops for many of them, which they do.
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.
Perhaps then the con is: "Modules are required to supply unnecessary boilerplate to implement no-op"
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.
Although, I think some of this could be addressed with breaking refactors to AppModule
, AppModuleBasic
. That is, if AppModuleBasic was decomposed into domain-specific extension interfaces.
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.
Yes, extension interfaces are a solution
interfaces which have the following shortcomings: | ||
* both `AppModule` and `AppModuleBasic` need to be defined which is counter-intuitive | ||
* apps need to implement the full interfaces, even parts they don't need | ||
* interface methods depend heavily on unstable third party dependencies, in particular Tendermint |
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 isn't a con IMO
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.
Depending on particular versions of Tendermint means you can't have a module which simultaneously supports multiple SDK versions in a hypothetical world where ABCI++ exists but maybe some users are more conservative about adopting it. More generally, it means the ecosystem needs to move in fits and starts - all modules must advance together, rather than allowing a "matrix" of compatible versions. I consider this a big con. Will try to explain this a bit more in the ADR
This is going to take me a while to review. I would love as much review as possible from those that this actually impacts the most -- app devs, client and tooling devs, etc... |
|
||
### Backwards Compatibility | ||
|
||
Early versions of runtime modules should aim to support as much as possible modules built with the existing |
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 wording here is runtime modules but in practice the SDK team will implement just one, at least initially, is that right?
I'm having a hard time visualizing how runtime would straddle the current AppModule / sdk.Context
paradigm and the proposed composition through Handler
.
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, I think we would implement one for the existing tendermint version, and another one once ABCI++ comes around possibly deprecating AppModule
altogether. The legacy version might have a fairly long life span of patch updates.
As for the second part, you would just have some sort of module manager which can deal with both AppModule
and Handler
appropriately.
* go stable API management principles are followed (TODO: link) | ||
|
||
Runtime modules which implement the core API are *intentionally* separate from the core API in order to enable more | ||
forks of the runtime module than is possible with the SDK's current tightly coupled `BaseApp` design while still |
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 could a fork of SDK's default runtime look like in practice? Is this a code fork or is runtime to be composable so that users of the sdk can add/adjust functionality? Is there a need for that currently (is this why osmosis forked)?
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.
For example, some state listening functionality like ADR 038 plugins could be implemented by forking (hopefully temporarily) the runtime without needing to wait for a full SDK release with all the other modules
Is this more or less right? Presently
Module behavior is defined at compile time by implementing ProposedModule functions do not receive an Module behavior is defined at runtime (app startup) by interacting with Alternative ProposalGiven that we want a stable Core API, here is a perhaps less invasive alternative: aaronc/core-api...kocubinski/core-api Instead of This allows for a smaller refactor for smoother Core API adoption by maintaining more or less the current usage pattern. We can deprecate Update: aaronc/core-api...kocubinski/core-api-v2 shows a rough draft with module capabilities fleshed out a bit more. |
Sounds pretty accurate @kocubinski .
This is an interesting alternative approach @kocubinski. I'll need to reflect on it a bit. Seems similar to expected keepers. The big downside to this alternate approach that I see is that it doesn't seem possible to know whether a service is available until block processing actually starts whereas with the depinject approach you know at initialization or compile time (with codegen). Does that sound accurate? |
Agreed, I'm mainly wanting core devs to have some shared context first to address any obvious concerns. |
type Manager interface { | ||
// Emit emits events to both clients and state machine listeners. These events MUST be emitted deterministically | ||
// and should be assumed to be part of blockchain consensus. | ||
Emit(proto.Message) error |
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.
why does this have to be a proto.message instead of a golang type?
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.
Because this supports typed events as the first class type of events. We can't just use a regular golang type as a typed event.
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.
rereading the typed events adr I'm not convinced this should be protobuf. is there reasoning proto was decided on here?
``` | ||
|
||
Typed events emitted with `Emit` can be observed by other modules and thus must be deterministic and should be assumed | ||
to be part of blockchain consensus (whether they are part of the block or app hash is left to the runtime to specify). |
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.
how would runtime do this? would it be up to the application developer?
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.
There is a way for registering event listeners described later.
Design questions: | ||
* should we allow overriding event managers (like `sdk.Context.WithEventManager`)? | ||
|
||
#### Block Info Service |
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 think this service may be better named consensus as it has to do with consensus related things.
Secondly, can you briefly comment on how this interface was chosen? what stake holders were consulted for the design, what use cases were considered? to me it seems we are missing stuff here in order to support different use cases. The sdk itself is not a good tell on what is used vs not
} | ||
``` | ||
|
||
Only a limited set of modules need any other information from the Tendermint block header and specific versions |
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.
if we are thinking of abstracting this, I would propose we spend some more time thinking through this in order to see if we could abstract tendermint away from the Cosmos SDK in order to make it agnostic to consensus. I have some ideas on what could be done here.
ChainID string | ||
Height int64 | ||
Time time.Time | ||
Hash []byte |
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.
still don't know what hash this is?
lastresulthash, app hash, last validator hash?
#### Event Listeners | ||
|
||
Handlers allow event listeners for typed events to be registered that will be called deterministically whenever those | ||
events are called in the state machine. Event listeners are functions that take a context, the protobuf message type of |
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.
why does this need to be a proto message?
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.
Again because of ADR 032 typed events
Event listeners provide a standardized alternative to module hooks, such as `StakingHooks`, even though these hooks | ||
are still supported and described in [ADR 057: App Wiring](./adr-057-app-wiring-1.md) | ||
|
||
Only one event listener per event type can be defined per module. Event listeners will be called in a deterministic |
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 believe these events are different than client events, if so we should make sure to identify that. This could get confusing
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 events are both client and internal events. The legacy "untyped" events are client only.
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.
oh didnt know this. Is this mentioned in another ADR?do these events get added to consensus if they are used internally?
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.
Yes. This is mentioned first in this ADR I think. Maybe it's too big of a scope and we should save it for a separate ADR
I've updated this ADR to only include stuff that has already been merged into core. I have removed gas, block info, and upgrades which should probably be part of this ADR but in an update; event listeners which should probably be a separate ADR; and ADR 033 stuff which should probably just go in an update of that ADR. Is this good to merge now? |
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.
thank you for making the changes. Super excited to see this come together
Marking this to be merged since its already mostly implemented, which means we have had consensus. No need to block the pr |
Description
Closes #12923
This PR adds ADR 063 which describes the core module API in #12239.
It also updates ADR 057: App Wiring to reflect integration with this ADR. ADR 063 is effectively the part 2 of app wiring mentioned in ADR 057.
Author Checklist
All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.
I have...
!
to the type prefix if API or client breaking changeCHANGELOG.md
Reviewers Checklist
All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.
I have...
!
in the type prefix if API or client breaking change