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

feat: rust core API dev branch #22239

Draft
wants to merge 197 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
197 commits
Select commit Hold shift + click to select a range
8712e44
feat: first draft of rust interchain core
aaronc Sep 13, 2024
03c88ff
updates
aaronc Sep 13, 2024
a0767d8
WIP on types
aaronc Sep 13, 2024
be1761b
refactor prelude into root crate
aaronc Sep 13, 2024
24914e8
simple time lib
aaronc Sep 14, 2024
ce1947f
add vesting example
aaronc Sep 14, 2024
cb10d5e
update
aaronc Sep 14, 2024
58e4454
WIP on examples
aaronc Sep 14, 2024
824decf
resource, ref, mixin, etc
aaronc Sep 14, 2024
7e25bec
WIP on testing
aaronc Sep 14, 2024
d344ca6
testing API
aaronc Sep 14, 2024
4910312
testing API
aaronc Sep 14, 2024
9473b86
testing API WIP
aaronc Sep 14, 2024
51de265
WIP on schema types
aaronc Sep 16, 2024
9585706
WIP on schema types
aaronc Sep 16, 2024
8204146
WIP on schema types
aaronc Sep 16, 2024
4484b58
WIP on schema, state objects
aaronc Sep 16, 2024
74fe5de
WIP on organization and docs
aaronc Sep 17, 2024
b5a5d3f
docs
aaronc Sep 17, 2024
b1c230f
WIP on tests
aaronc Sep 17, 2024
f871374
WIP on docs
aaronc Sep 17, 2024
19ef1f7
WIP on docs
aaronc Sep 17, 2024
398cb62
WIP
aaronc Sep 18, 2024
218ae06
WIP on docs
aaronc Sep 18, 2024
7bec65d
remove Seq, add unique_id
aaronc Sep 18, 2024
e59e9b1
experimental parallel safe lifetime bounds
aaronc Sep 18, 2024
3811d6b
WIP on state objects, macros
aaronc Sep 18, 2024
bcbe63a
WIP on macros
aaronc Sep 18, 2024
e74bb90
counter codegen basically working
aaronc Sep 18, 2024
743c89f
switch OnCreate -> #[on_create]
aaronc Sep 18, 2024
52c7efc
WIP on docs, examples
aaronc Sep 18, 2024
f46893f
WIP on simple error type
aaronc Sep 18, 2024
380babb
WIP on simple errors
aaronc Sep 19, 2024
1daf298
WIP on macros
aaronc Sep 19, 2024
0a68771
WIP on response
aaronc Sep 19, 2024
2f82783
update uint map
aaronc Sep 19, 2024
0023b05
fix unit_map
tac0turtle Sep 19, 2024
0af88b0
add splitting across files docs
aaronc Sep 19, 2024
f7df8f5
describe parallel safety
aaronc Sep 19, 2024
daec8a7
rename everything to ixc
aaronc Sep 19, 2024
3cae132
update descriptions
aaronc Sep 19, 2024
deb1a77
add no_std decls
aaronc Sep 19, 2024
11b325f
add dep versions for schema
aaronc Sep 19, 2024
f10b2b3
add dep versions for core
aaronc Sep 19, 2024
3caf6eb
add dep versions for state objects
aaronc Sep 19, 2024
d50074d
temporarily remove state objects dep for reserving name
aaronc Sep 19, 2024
85c7d3f
update state objects macros
aaronc Sep 19, 2024
1f15242
add preview warnings, re-add state_objects dep to ixc
aaronc Sep 19, 2024
b63840a
WIP on proto compatibility
aaronc Sep 19, 2024
7648e03
WIP on proto compatibility
aaronc Sep 19, 2024
c6c40bf
update versions
aaronc Sep 19, 2024
c0d8f97
update versions
aaronc Sep 19, 2024
a7d3f54
update versions
aaronc Sep 19, 2024
1830d78
update versions
aaronc Sep 19, 2024
6516221
update README
aaronc Sep 20, 2024
b4b7422
fix .gitignore
aaronc Sep 20, 2024
574b072
chore: unlink crate versions from workspace
aaronc Sep 20, 2024
157fafb
add release plz config
aaronc Sep 20, 2024
e09ff77
chore: fix .gitignore
aaronc Sep 20, 2024
8560647
chore: fix .gitignore
aaronc Sep 20, 2024
d0681b0
chore: update release-plz config
aaronc Sep 20, 2024
9c164d8
chore: update .release-plz.toml
aaronc Sep 20, 2024
42e6988
WIP on allocation
aaronc Sep 22, 2024
55b2143
this works, but uses the regular alloc Box
aaronc Sep 22, 2024
b43dab7
WIP on decoding
aaronc Sep 23, 2024
fb6be61
WIP on codec
aaronc Sep 23, 2024
3c5b36d
WIP on encoding
aaronc Sep 23, 2024
658d5d0
WIP on encoding
aaronc Sep 23, 2024
5a501a9
basic u32 decoding
aaronc Sep 23, 2024
1453b00
first working struct round trip
aaronc Sep 24, 2024
39630ba
WIP on lists
aaronc Sep 24, 2024
dd4f73c
WIP on dyn drop
aaronc Sep 24, 2024
b8eb6e5
working dyn drop
aaronc Sep 24, 2024
54e5edc
rename
aaronc Sep 24, 2024
3e35a47
WIP on internalizing mem mgmt
aaronc Sep 24, 2024
9c0fac3
WIP on internalizing mem mgmt
aaronc Sep 24, 2024
ea20e12
WIP on internalizing mem mgmt
aaronc Sep 24, 2024
f08ea17
working list and struct codec
aaronc Sep 24, 2024
8984314
WIP on docs
aaronc Sep 24, 2024
975d755
WIP on trying to get an e2e example working
aaronc Sep 24, 2024
cbf23b4
WIP on trying to get an e2e example working
aaronc Sep 25, 2024
0c91584
WIP
aaronc Sep 25, 2024
130e121
WIP
aaronc Sep 26, 2024
b23fcaf
WIP
aaronc Sep 26, 2024
afd0de8
WIP
aaronc Sep 27, 2024
d850af3
WIP
aaronc Sep 27, 2024
dd9190e
WIP
aaronc Sep 28, 2024
e4f7cc4
WIP refactoring mem encapsulation
aaronc Sep 29, 2024
b4a3f73
WIP on mem refactor
aaronc Sep 29, 2024
2a466cb
revert mem refactor
aaronc Sep 29, 2024
37371c0
WIP on alloc
aaronc Sep 29, 2024
64cc880
simplify memory management
aaronc Sep 30, 2024
d21d42f
WIP on vec support
aaronc Sep 30, 2024
34ba1fc
take steps to distinguishing [u8] from [T] values
aaronc Sep 30, 2024
addcdaf
impl allocator trait directly
aaronc Sep 30, 2024
0a53340
WIP on context
aaronc Sep 30, 2024
e225188
WIP on state encoding and storage
aaronc Sep 30, 2024
97a327b
WIP on state encoding and storage
aaronc Sep 30, 2024
bad1ada
WIP on state object encoding
aaronc Oct 1, 2024
0a81625
state objects basic impl
aaronc Oct 1, 2024
2baf9ce
WIP on testing
aaronc Oct 1, 2024
005b12b
more schema types, refactoring
aaronc Oct 1, 2024
6d7add2
WIP on getting an example building
aaronc Oct 1, 2024
2b1d02b
make encoders, decoders and visitors object safe
aaronc Oct 1, 2024
8962064
make encoders, decoders and visitors object safe
aaronc Oct 1, 2024
587d400
working SchemaValue macro
aaronc Oct 1, 2024
ae26bc9
properly namespace macro
aaronc Oct 1, 2024
68bffb6
properly namespace macro
aaronc Oct 1, 2024
ff20148
SchemaValue working for structs
aaronc Oct 1, 2024
097fca3
WIP on testing & integration
aaronc Oct 1, 2024
08cc1a6
WIP on testing & integration
aaronc Oct 1, 2024
fbea7eb
fix struct macro lifetimes, finish todos
aaronc Oct 2, 2024
c7672a9
WIP on enums
aaronc Oct 2, 2024
1f4dd95
update macros
aaronc Oct 2, 2024
127bbf7
WIP on integration
aaronc Oct 2, 2024
388cb82
WIP on integration
aaronc Oct 2, 2024
a54e346
WIP on integration, switched to bumpalo
aaronc Oct 3, 2024
0612da3
fix memory error
aaronc Oct 3, 2024
fe0ff03
custom bump allocator, actually really simple...
aaronc Oct 3, 2024
54c2e69
docs
aaronc Oct 3, 2024
c5b0581
make more traits object safe
aaronc Oct 3, 2024
81f3aca
reduce genericism
aaronc Oct 3, 2024
e83e9f5
reduce use of generics
aaronc Oct 3, 2024
a7c4b4a
updates
aaronc Oct 3, 2024
1384e0e
add default vm hack
aaronc Oct 3, 2024
892237e
integration working up to route invoke
aaronc Oct 3, 2024
4e54f3f
basic invocation working
aaronc Oct 3, 2024
6b55c35
store set seems to be working
aaronc Oct 3, 2024
ad646b0
passing test
aaronc Oct 3, 2024
4ae4a3b
passing test
aaronc Oct 3, 2024
c53ddcf
working client macro
aaronc Oct 3, 2024
c650974
work on macros and lifetimes...
aaronc Oct 3, 2024
a6bcfb4
working routing impl
aaronc Oct 4, 2024
9628638
working counter example, except for on_create
aaronc Oct 4, 2024
8a9c5e9
working on_create
aaronc Oct 4, 2024
f887661
WIP on simple_asset example
aaronc Oct 4, 2024
068a958
simplify account creation
aaronc Oct 4, 2024
d6675bf
todos
aaronc Oct 4, 2024
c5d0c1c
fixes
aaronc Oct 4, 2024
3e44e3a
simplifying lifetimes
aaronc Oct 4, 2024
c08b8ce
WIP on state objects & bank
aaronc Oct 4, 2024
7a41d81
refactor macros
aaronc Oct 4, 2024
b48b4ec
WIP on macros
aaronc Oct 4, 2024
5a9f29c
fix macro
aaronc Oct 4, 2024
6020e88
WIP on macros
aaronc Oct 4, 2024
bc2087a
adding missing encoder/decoder impls
aaronc Oct 7, 2024
9fa89f1
WIP on encoding/decoding
aaronc Oct 7, 2024
ca70cda
WIP
aaronc Oct 7, 2024
4f2e3f4
basic round tripping test
aaronc Oct 8, 2024
ba4a57a
WIP on bank
aaronc Oct 8, 2024
b2b2b75
handler_api client traits
aaronc Oct 9, 2024
f86990c
refactor errors
aaronc Oct 9, 2024
1c930a3
bank example working
aaronc Oct 9, 2024
f761c54
WIP on bank v2 example
aaronc Oct 9, 2024
0722800
support mocks
aaronc Oct 10, 2024
c98b2ce
add ability to peek inside handlers
aaronc Oct 10, 2024
c1be15a
WIP on tests
aaronc Oct 10, 2024
647081a
WIP on vesting example
aaronc Oct 10, 2024
0cc9566
working vesting example
aaronc Oct 10, 2024
d33fc9b
add missing impls
aaronc Oct 10, 2024
6610301
cleanup
aaronc Oct 10, 2024
804ef6b
cleanup
aaronc Oct 10, 2024
283fea1
cleanup
aaronc Oct 10, 2024
a410529
add example crate
aaronc Oct 10, 2024
c2e0518
cleanup
aaronc Oct 10, 2024
57dc434
WIP on single import macro path
aaronc Oct 11, 2024
acc9083
for now core_macros only works with ixc::
aaronc Oct 11, 2024
7cb56b9
acceptable single import macros
aaronc Oct 11, 2024
ea55e40
update ixc README.md
aaronc Oct 11, 2024
274e7b7
WIP on docs
aaronc Oct 11, 2024
2915b6d
decouple create_account from just init message
aaronc Oct 11, 2024
5624908
WIP on docs, require Handler type in create_account in order to be le…
aaronc Oct 11, 2024
dc31a3a
docs updates
aaronc Oct 11, 2024
a9e4277
update versions
aaronc Oct 11, 2024
39fd47e
update versions
aaronc Oct 11, 2024
877ea51
update versions
aaronc Oct 11, 2024
0d809ee
update description
aaronc Oct 11, 2024
36c25b3
update deps
aaronc Oct 11, 2024
3b74835
update versions
aaronc Oct 11, 2024
2885c04
fix README
aaronc Oct 11, 2024
e14110b
update README
aaronc Oct 11, 2024
ead7eca
update Cargo.toml
aaronc Oct 11, 2024
8156416
fix(rust/core): error macros
aaronc Oct 11, 2024
cc93e83
refactor(rust/core): rename Context::account_id -> self_account_id
aaronc Oct 11, 2024
5ce53e7
Merge branch 'main' of github.com:cosmos/cosmos-sdk into rust-core
aaronc Oct 11, 2024
c8c5198
update CODEOWNERS
aaronc Oct 11, 2024
ad25e82
add rust CI
aaronc Oct 11, 2024
a32fb88
disable doctest
aaronc Oct 11, 2024
182594c
fix docs
aaronc Oct 11, 2024
5b6e955
remove unsafe &mut transmuting in macros
aaronc Oct 11, 2024
a962c27
docs(rust/core): update README.md
aaronc Oct 11, 2024
e097611
WIP on DESIGN.md
aaronc Oct 11, 2024
fdd65e2
WIP on DESIGN.md and TODO.md
aaronc Oct 11, 2024
0c417d2
chore(rust): bump versions
aaronc Oct 11, 2024
028b47a
update DESIGN.md
aaronc Oct 11, 2024
dfcc9c5
design doc updates
aaronc Oct 14, 2024
caa0f08
design doc updates
aaronc Oct 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,7 @@ Makefile @auricom @julienrbrt @tac0turtle
/docs/sidebars.js @julienrbrt @tac0turtle
/docs/pre.sh @julienrbrt @tac0turtle
/docs/post.sh @julienrbrt @tac0turtle

# rust

rust/ @aaronc
21 changes: 21 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: "Test Suite"
on:
pull_request:
merge_group:
push:
branches:
- main
- release/**
- rust-core
permissions:
contents: read

jobs:
test:
name: cargo test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions-rust-lang/setup-rust-toolchain@v1
- run: cargo test --workspace --all-targets
working-directory: rust
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ vagrant
*.ipr
*.iws
.dir-locals.el
.vscode
.vscode/*
!.vscode/extensions.json
!.vscode/launch.json

# Depinject & Graphviz
dependency-graph.png
Expand Down
16 changes: 16 additions & 0 deletions rust/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
### Rust template
# Generated by Cargo
# will have compiled files and executables
debug/
target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk

# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb

71 changes: 71 additions & 0 deletions rust/.release-plz.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
[workspace]
changelog_update = false
git_tag_enable = false
git_release_enable = false

[changelog]
header = """# Changelog

## [Unreleased]

"""

body = """
{% macro print_commit(commit) -%}
- {% if commit.scope %}*({{ commit.scope }})* {% endif %}\
{% if commit.breaking %}[**breaking**] {% endif %}\
{{ commit.message | upper_first }} - \
([{{ commit.id | truncate(length=7, end="") }}]({{ remote.link }}/commit/{{ commit.id }}))\
{% endmacro -%}

{% if version %}\
{% if previous.version %}\
## [{{ version | trim_start_matches(pat="v") }}]({{ release_link }})
{% else %}\
## [{{ version | trim_start_matches(pat="v") }}]
{% endif %}\
{% endif %}\

{% for group, commits in commits
| filter(attribute="merge_commit", value=false)
| unique(attribute="message")
| group_by(attribute="group") %}
### {{ group | striptags | trim | upper_first }}
{% for commit in commits
| filter(attribute="scope")
| sort(attribute="scope") %}
{{ self::print_commit(commit=commit) }}
{%- endfor -%}
{% raw %}\n{% endraw %}\
{%- for commit in commits %}
{%- if not commit.scope -%}
{{ self::print_commit(commit=commit) }}
{% endif -%}
{% endfor -%}
{% endfor %}\n
"""

commit_parsers = [
{ message = "^feat", group = "<!-- 0 -->⛰️ Features" },
{ message = "^fix", group = "<!-- 1 -->🐛 Bug Fixes" },
{ message = "^doc", group = "<!-- 3 -->📚 Documentation" },
{ message = "^perf", group = "<!-- 4 -->⚡ Performance" },
{ message = "^refactor\\(clippy\\)", skip = true },
{ message = "^refactor", group = "<!-- 2 -->🚜 Refactor" },
{ message = "^style", group = "<!-- 5 -->🎨 Styling" },
{ message = "^test", group = "<!-- 6 -->🧪 Testing" },
{ message = "^chore\\(release\\):", skip = true },
{ message = "^chore: release", skip = true },
{ message = "^chore\\(deps.*\\)", skip = true },
{ message = "^chore\\(pr\\)", skip = true },
{ message = "^chore\\(pull\\)", skip = true },
{ message = "^chore\\(npm\\).*yarn\\.lock", skip = true },
{ message = "^chore|^ci", group = "<!-- 7 -->⚙️ Miscellaneous Tasks" },
{ body = ".*security", group = "<!-- 8 -->🛡️ Security" },
{ message = "^revert", group = "<!-- 9 -->◀️ Revert" },
]

link_parsers = [
{ pattern = "#(\\d+)", href = "{{ remote.link }}/issues/$1" },
{ pattern = "RFC(\\d+)", text = "ietf-rfc$1", href = "https://datatracker.ietf.org/doc/html/rfc$1" },
]
71 changes: 71 additions & 0 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
[workspace]
members = [
"core",
"core_macros",
"state_objects",
"state_objects_macros",
"schema",
"schema_macros",
"message_api",
"testing",
"util/simple_time",
# "codecs/proto", "codecs/evm",
# "vm/wasmtime",
"vm/api",
# "vm/hypervisor",
"example",
]

[workspace.package]
repository = "https://github.com/cosmos/cosmos-sdk"
license = "Apache-2.0"
rust-version = "1.81.0"

[workspace.lints]

[workspace.lints.rust]
missing_docs = "deny"

[workspace.lints.rustdoc]
broken_intra_doc_links = "deny"
private_intra_doc_links = "deny"

[package]
name = "ixc"
edition = "2021"
description = "Interchain SDK"
readme = "README.md"
version = "0.0.5"
repository.workspace = true
license.workspace = true

[dependencies]
ixc_core = { path = "core", version = "0.0.4" }
ixc_schema = { path = "schema", version = "0.0.4", features = ["use_ixc_macro_path"] }
ixc_message_api = { path = "message_api", version = "0.0.4" }
state_objects = { path = "state_objects", version = "0.0.4" }
simple_time = { path = "util/simple_time", version = "0.0.2" }
ixc_core_macros = { path = "core_macros", version = "0.0.4" }
ixc_schema_macros = { path = "schema_macros", version = "0.0.3", features = ["use_ixc_macro_path"] }
state_objects_macros = { path = "state_objects_macros", version = "0.0.3" }
constcat = "0.5.1"
array-concat = "0.5.3"

[dev-dependencies]
ixc_testing = { path = "testing" }
arrayvec = "0.7.6"
thiserror = "1.0.63"
num_enum = "0.7.3"
mockall = "0.13.0"

[lib]
doctest = false

[lints]
workspace = true

[features]
default = []

[profile.release]
lto = true
119 changes: 119 additions & 0 deletions rust/DESIGN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Major Design Decisions

## Account IDs vs Addresses

Originally we were planning to use an `Address` type with 20-32 variable bytes,
but this varies between VMs, in particular the EVM and Cosmos.
Now we are assigning integer account IDs and considering addresses as a pointer
to an account ID which exists at the transaction level.
There could be multiple addresses pointing to the same account ID.

**Design Questions**
* What is the correct size for account IDs? Is 64 bits enough or should we use 128 bits? Ideally, we want to be able to assign account IDs concurrently without needing to lock around an incremental account ID sequence. This will require a different assignment mechanism, possibly we can take 32-bits of the transaction hash and then have a 32-bit sequence number scoped to the 32-bit transaction hash.
* Is it okay for IDs of deleted accounts to be reused?
It would probably be safer to make sure that IDs don't get reused, but this affects our assignment algorithm if we do it concurrently.
We also don't want to need to maintain a list of deleted accounts just for this purpose.
This likely means that we need to include something like the block number in the account ID to prevent reuse.

## Message Selectors & Type IDs

When referencing a message we can either specify the full message name or use some bytes that represent the message name in a compressed way, similar to how Ethereum uses 32-bit function selectors which are based on the hash of the function signature.
This creates more efficient message packets
and is more efficient to route to the correct handler.
The downside of a 32-bit function selector is that there can be collisions.
We can improve the collision resistance by using a 64-bit message selector.

This scheme could be extended to represent type IDs for event structs and other types,
similar to the original amino encoding (which used 4 or 7 bytes for type IDs).

64-bits is probably sufficient for uniqueness, although there could theoretically be collisions if we had to resolve such IDs globally rather than scoped to a specific module. This could maybe, someday be an issue if we have first-class modules.
However, the current implementation doesn't have first-class modules, and we may try to avoid them, so this isn't currently an issue.

**Design Questions**
* How much does the hypervisor layer actually need to be aware of message selectors? Or should this simply be part of the opaque message packet?
* Do we need to encode the volatility of a call in the message selector in such a way that the hypervisor can enforce it? Probably yes, because otherwise it would be valid for one handler to call a "readonly" handler that _actually_ modifies state. Encoding the expected volatility in the message packet makes this a runtime error rather than allowing state to be modified unexpectedly.
* What about protected routes?
For instance the `on_create` method of a handler should only be called by the hypervisor account.
Message pre- and post-handlers are a similar case.
Callback hooks should only be called by the handler expected to call them. Is this something that the hypervisor should enforce through some list of allowed message selectors for an account? Or should handlers be 100% responsible for dealing with this by checking the caller ID?
Likely there will always be cases where handlers
need to check the caller for some hook-like things so we should make sure there is good first-class support
for checking callers. But for routes that really only the hypervisor should call (`on_create`, `on_upgrade`, pre- and post-handlers), it would be more ideal to have some way to enforce this at the hypervisor level, maybe through some protected route flag in the message selector.

## Resolving Accounts IDs

Let's define a first-class module as a handler which:
1. can only be instantiated once (singleton)
2. is the only handler for a given set of message names (i.e. no two modules can handle the same message)

In the current design, we don't have first-class modules so if we want to call `MsgSend` as in the current SDK,
we would need to know the account ID of "bank" before we can send the message. (Whether we can have singleton
handlers is a separate, but related question.)

To resolve account IDs, here are some options:
1. **Hard Code Reserved Range:** hard code account IDs for module-like things in some "reserved" ID range (ex. 1-65535) - this has the downside that it wouldn't be portable between chains
2. **Build-time Config:** use config files to map account aliases (ex. "bank") to account IDs - this could be portable if we find a way to configure this with different IDs at build time without needing to fork the code
3. **Runtime Config:** bind account aliases using a config map at runtime. This would require bundling a config descriptor with the compiled code rather than building it into the binary
4. **Runtime Module Name Resolver:** bind account aliases at runtime using some on-chain list of module names. This has the downside of binding specific APIs to specific module names.
5. **Runtime Message/Service Name Resolver:** bind account aliases at runtime using some on-chain list of service or message names (ex. "cosmos.bank.v1" or "cosmos.bank.v1.MsgSend"). This is almost the way we do it in the current SDK except we'd be resolving a default account ID rather than not knowing the account ID at all.
6. **First-class Module Messages:** meaning we don't need to know any account number, we just need to know the message name, and it will get routed to resolved account. This is different from 5 in that we don't resolve the account ID at all.

It's worth noting that options 1-5 vs any kind of first-class notion of modules have the following advantages:
* message selectors do not need to be globally unique, just unique to an account. This could be used in a rare cases to disambiguate a collision
* the resolved account ID can be used to authenticate hook callbacks. i.e. if I want to implement a bank `OnReceive` hook, I can authenticate
that the real "bank" is the caller of the hook because I know its account ID.

Thinking most generally, there will probably always be a case for 2) **Build-time Config** because
some developers will always want to build handlers related to other existing accounts whether or not
those are considered "first-class" modules or not.
So the simplest starting point is probably to support **Build-time Config** first, which
requires no changes at the hypervisor layer, and see how far that gets us.

## Handler IDs

The basic model we are working with is that there is a root mapping of `account ID -> handler ID`
where handler ID is a pointer to the actual code to run the account in some virtual machine.

A few issues to consider:
* handler IDs should be part of consensus, but different nodes may actually use slightly different
implementations of the same handler or VM.
For instance, it shouldn't be an error to run a functionally identical handler written in Rust or Go,
built into the binary or dynamically linked, as long as there is otherwise consensus that it is the same.
It should also be possible to use different Wasm or EVM implementations.
* it should be possible to create an account with a handler defined in the same compilation unit as our currently executing code just be referring to its Rust or Go type rather than some string
* a handler ID should represent an immutable piece of code, so any migration or upgrade should involve changing the handler ID to a new handler ID, even if it's just a version bump

Possible approaches:
* in Rust, we can use `module_path!()` to get the module path including the crate name, and in Go we can get the package path by reflection
* for SDK modules, we currently use versioned protobuf files to create a module config message, and we should be bumping the version every time we change the module, but I think we're not doing that
* for Wasm, we can use the format `wasm:<hash>:<handler_id>` where `hash` is the hash of the Wasm code and `handler_id` is some handler ID within the Wasm code (maybe coming from a Rust `module_path!()` plus type name in a macro)
* the EVM uses addresses to identify contracts, and all contracts are basically singletons and immutable, so we can just use the format `evm:<address>` and such accounts would never be upgradeable

We can divide the complexity of this problem into two parts: native handlers and VM handlers.
For VM handlers, the problem is simple because we can simply use the hash, and it must be the same for
all nodes even if they use different VM implementations.

For native handlers, if we just took a naive approach of doing something like `rust:<module_path!()>:<type_name>`, then
we have the following problems:
* we can't implement the same handler in Go and Rust, or load the same handler alternatively as a dynamic
library, compiled into the binary or loaded via Wasm
* there is no version information encoded into the handler ID, so if someone just swaps out a binary with
the same handler, then we need to create a separate upgrade path

If we had user-assigned names for Native handlers (like we do with versioned protobuf types), then
we could make the implementation independent of the language and the compilation unit, but then we have these
issues:
* it's harder to refer to a handler in the same compilation unit
* people will probably update binaries without updating the handler ID, so we may need a separate "native" migration path

**Proposed approach:**
* handler IDs follow the format: `<vm>:<package_id>:<handler_id>`
* for true VM handlers, `package_id` is the hash of the code
* for native handlers, `package_id` is either:
* the git hash of the repository at build time (this can be injected with a Rust macro) + the hash of any build-time config data,
* or for golang, some version or hash derived from https://pkg.go.dev/runtime/debug#BuildInfo
* the above would apply for native handlers whether or not they are loaded dynamically or compiled into the binary and would use whatever is the canonical source code for the handler
* when we need to use some other source code for the native handler (such as an alternative Rust version of a Go handler), there should be some "replace" directive mechanism in the native VM to redirect the handler ID to a different implementation
* for native or Wasm handlers, the `handler_id` is the fully qualified Go or Rust package path + type name

## Encoding
Loading
Loading