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

refactor: Introduce strictly typed and assuredly validated AccountId #4440

Merged
merged 32 commits into from
Jul 29, 2021

Conversation

miraclx
Copy link
Contributor

@miraclx miraclx commented Jun 30, 2021

This PR introduces a strictly typed structure - AccountId that enforces account ID validation.
This way, we can ensure validity and thereby fail fast before an invalid account name is used.

This also, optionally, ensures validation on {,de}serialization so, yeah..

The structure is defined within its own self-contained crate near-account-id to allow for easy publishing.
The extra dependencies - borsh, serde are made optional to allow the crate to be lightweight enough to be depended upon.

Within nearcore, the structure is reexported via near_primitives::AccountId and the crate via near_primitives{,_core}::account::id with default features (borsh, serde) but you can opt-out of those by depending on it directly.

Resolves #2074, supersedes #2831.

Testing Plan

  • Existing unit tests pass with minor updates
  • Nayduck tests pass without modifications
  • Manually ensured that the protocol is not changed

@miraclx
Copy link
Contributor Author

miraclx commented Jun 30, 2021

Since we now preemptively perform account ID validation, cases like these are ensured and extra testing is unnecessarily redundant. However, this, in turn, leads to having variants like InvalidTxError::InvalidReceiverId that are unused:

InvalidReceiverId { receiver_id: AccountId },

Would be nice if we could clean that up a bit, without breaking a lot.

@miraclx
Copy link
Contributor Author

miraclx commented Jun 30, 2021

Also, throughout the repo, a debug view has been used on AccountId before this change. Back when it was simply a String this was okay.. But now, it's a lot more verbose (perhaps more descriptive, depending on how you look at it)

As an example:

 format!("{:?}", AccountId("miraclx.near")) 
before "miraclx.near"
after "AccountId(\"miraclx.near\")"

We could manually impl Debug and remain consistent with the former behavior but the proper Debug view seems more reasonable to me, what do you think?

I bring this up because it's one of the issues with failing tests in CI

snapshot (CI)
---- adapters::tests::test_convert_block_changes_to_transactions stdout ----
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Snapshot Differences ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Snapshot file: chain/rosetta-rpc/src/adapters/snapshots/near_rosetta_rpc__adapters__tests__validators_update_transaction.snap
Snapshot: validators_update_transaction
Source: chain/rosetta-rpc/src/adapters/mod.rs:992
-old snapshot
+new results
────────────────────────────────────────────────────────────────────────────────
validators_update_transaction
────────────┬───────────────────────────────────────────────────────────────────
   12    12 │             status: Some(
   13    13 │                 Success,
   14    14 │             ),
   15    15 │             account: AccountIdentifier {
-  16       │-                address: "nfvalidator1.near",
+        16 │+                address: AccountId(
+        17 │+                    "nfvalidator1.near",
+        18 │+                ),
   17    19 │                 sub_account: None,
   18    20 │             },
   19    21 │             amount: Some(
   20    22 │                 Amount {
┈┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
   37    39 │             status: Some(
   38    40 │                 Success,
   39    41 │             ),
   40    42 │             account: AccountIdentifier {
-  41       │-                address: "nfvalidator2.near",
+        43 │+                address: AccountId(
+        44 │+                    "nfvalidator2.near",
+        45 │+                ),
   42    46 │                 sub_account: None,
   43    47 │             },
   44    48 │             amount: Some(
   45    49 │                 Amount {
────────────┴───────────────────────────────────────────────────────────────────
thread 'adapters::tests::test_convert_block_changes_to_transactions' panicked at 'snapshot assertion for 'validators_update_transaction' failed in line 992', /var/lib/buildkite-agent/.cargo/registry/src/github.com-1ecc6299db9ec823/insta-1.6.3/src/runtime.rs:1026:9

@miraclx
Copy link
Contributor Author

miraclx commented Jun 30, 2021

Also, node_key.json has a field account_id that previously held an empty string. CI fails for this exact reason. To mitigate this, this PR uses the "node" account id instead to ensure validity. This file has to be reset on CI systems.

cc @chefsale

Or should I engineer a workaround within this PR?

@miraclx miraclx added A-security Area: Security issues A-testing Area: Unit testing / integration testing C-enhancement Category: An issue proposing an enhancement or a PR with one. C-housekeeping Category: Refactoring, cleanups, code quality labels Jun 30, 2021
@chefsale
Copy link
Contributor

So, the CI machines are destroyed on every run, so we don't store the keys, but rather generate them on every run. I believe the issue is rather caused by some code change where we have missed something. I assume this failure comes from account ids being invalid and this is throwing an error now? I assume there is some part of code which generates this node key which we need to adapt. cc: @bowenwang1996 @frol

Also just to verify we do not change the account id structure in the current generated key json files at all, but just have this additional check? If we do, we should ensure to be backwards compatible.

Copy link
Contributor

@chefsale chefsale left a comment

Choose a reason for hiding this comment

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

Let's figure out how to fix the tests.

@miraclx miraclx force-pushed the strict-account-id-validity branch from d2ac817 to 4a830d6 Compare July 28, 2021 11:42
@miraclx
Copy link
Contributor Author

miraclx commented Jul 28, 2021


let n = 1;
let mut receipts = generate_receipts(small_transfer, n);
let invalid_account_id = "Invalid".to_string();
Copy link
Member

Choose a reason for hiding this comment

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

Cool these errors are statically prevented

}
// We retain these checks here as to maintain backwards compatibility
// with AccountId validation since we illegally parse an AccountId
// in near-vm-logic/logic.rs#fn(VMLogic::read_and_parse_account_id)
Copy link
Member

Choose a reason for hiding this comment

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

👍

Copy link
Member

@ailisp ailisp left a comment

Choose a reason for hiding this comment

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

Looks good. Nice hard and meticulous work!

Copy link
Contributor

@chefsale chefsale left a comment

Choose a reason for hiding this comment

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

Good luck with resolving conflicts 🗡️

@miraclx miraclx requested a review from matklad July 28, 2021 19:54
@frol frol changed the title Introduce strictly typed and assuredly validated AccountId refactor: Introduce strictly typed and assuredly validated AccountId Jul 29, 2021
@near-bulldozer near-bulldozer bot merged commit a3805ee into near:master Jul 29, 2021
@miraclx miraclx deleted the strict-account-id-validity branch July 29, 2021 14:08
bowenwang1996 added a commit that referenced this pull request Jul 29, 2021
bowenwang1996 added a commit that referenced this pull request Jul 30, 2021
#4601)

* Revert "refactor: Introduce strictly typed and assuredly validated AccountId (#4440)"

This reverts commit a3805ee.

* add missing tests

Co-authored-by: Michal Nazarewicz <mina86@mina86.com>
miraclx added a commit to miraclx/nearcore that referenced this pull request Aug 2, 2021
…ear#4440)

This PR introduces a strictly typed structure - `AccountId` that enforces account ID validation.
This way, we can ensure validity and thereby fail fast before an invalid account name is used.

This also, optionally, ensures validation on {,de}serialization so, yeah..

The structure is defined within its own self-contained crate `near-account-id` to allow for easy publishing.
The extra dependencies - `borsh`, `serde` are made optional to allow the crate to be lightweight enough to be depended upon.

Within `nearcore`, the structure is reexported via `near_primitives::AccountId` and the crate via `near_primitives{,_core}::account::id` with default features (`borsh`, `serde`) but you can opt-out of those by depending on it directly.

Resolves near#2074, supersedes near#2831.

# Testing Plan

* [x] Existing unit tests pass with minor updates
* [x] Nayduck tests pass without modifications
* [x] Manually ensured that the protocol is not changed
miraclx added a commit that referenced this pull request Aug 2, 2021
…4440)

This PR introduces a strictly typed structure - `AccountId` that enforces account ID validation.
This way, we can ensure validity and thereby fail fast before an invalid account name is used.

This also, optionally, ensures validation on {,de}serialization so, yeah..

The structure is defined within its own self-contained crate `near-account-id` to allow for easy publishing.
The extra dependencies - `borsh`, `serde` are made optional to allow the crate to be lightweight enough to be depended upon.

Within `nearcore`, the structure is reexported via `near_primitives::AccountId` and the crate via `near_primitives{,_core}::account::id` with default features (`borsh`, `serde`) but you can opt-out of those by depending on it directly.

Resolves #2074, supersedes #2831.

* [x] Existing unit tests pass with minor updates
* [x] Nayduck tests pass without modifications
* [x] Manually ensured that the protocol is not changed
frol pushed a commit that referenced this pull request Aug 5, 2021
# refactor: Introduce strictly typed and assuredly validated AccountId (#4440)

This PR introduces a strictly typed structure - `AccountId` that enforces account ID validation.
This way, we can ensure validity and thereby fail fast before an invalid account name is used.

This also, optionally, ensures validation on {,de}serialization so, yeah..

The structure is defined within its own self-contained crate `near-account-id` to allow for easy publishing.
The extra dependencies - `borsh`, `serde` are made optional to allow the crate to be lightweight enough to be depended upon.

Within `nearcore`, the structure is reexported via `near_primitives::AccountId` and the crate via `near_primitives{,_core}::account::id` with default features (`borsh`, `serde`) but you can opt-out of those by depending on it directly.

Resolves #2074, supersedes #2831.

* [x] Existing unit tests pass with minor updates
* [x] Nayduck tests pass without modifications
* [x] Manually ensured that the protocol is not changed


# impl workaround for invalid AccessKey-s in genesis records (resolves #4600)

* [x] Manually booted a testnet node to ensure genesis loads properly and that no further AccountId-related issues occur.
* [x] Ensured unit tests pass with no further updates
* [x] Nayduck tests pass without modifications
near-bulldozer bot pushed a commit that referenced this pull request Dec 5, 2022
Fixes the following clippy error:
```
error: the since field must contain a semver-compliant version
   --> core/account-id/src/lib.rs:302:18
    |
302 |     #[deprecated(since = "#4440", note = "AccountId construction without validation is illegal")]
    |                  ^^^^^^^^^^^^^^^
    |
    = note: `#[deny(clippy::deprecated_semver)]` on by default
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_semver
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-security Area: Security issues A-testing Area: Unit testing / integration testing C-enhancement Category: An issue proposing an enhancement or a PR with one. C-housekeeping Category: Refactoring, cleanups, code quality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Define AccountId to hold a contract of being valid
9 participants