-
Notifications
You must be signed in to change notification settings - Fork 72
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
doc:
nearcore
migration guide to 1.0.0
- Loading branch information
dj8yf0μl
committed
Aug 16, 2023
1 parent
80d5ba1
commit abed9d5
Showing
2 changed files
with
354 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,352 @@ | ||
# `0.10.2` -> `1.0.0-alpha.3` nearcore upgrade *migration guide* | ||
|
||
The link to `nearcore` pr is [chore: update borsh dependency](https://github.com/near/nearcore/pull/9432) | ||
|
||
Steps: | ||
|
||
## 1. update dependencies in `nearcore` workspace `Cargo.toml` | ||
|
||
```diff | ||
-borsh = { version = "0.10.2", features = ["rc"] } | ||
+borsh = { version = "1.0.0-alpha.3", features = ["derive", "rc"] } | ||
``` | ||
|
||
## 2. next we encounter error in `near-primitives` package: | ||
|
||
```bash | ||
1 error[E0433]: failed to resolve: could not find `maybestd` in `borsh` ▐ | ||
--> core/primitives/src/receipt.rs:1:19 ▐ | ||
| ▐ | ||
1 | use crate::borsh::maybestd::collections::HashMap; ▐ | ||
| ^^^^^^^^ could not find `maybestd` in `borsh` ▐ | ||
``` | ||
|
||
`maybestd` has moved to a `__private` package in `borsh`, and is not supposed to be | ||
accessed directly now besides from within code, derived in `borsh` traits implementations. | ||
|
||
As `near-primitives` crate is not supposed to be used in `no_std` context, we can | ||
replace import with standard collections `HashMap`: | ||
|
||
```diff | ||
diff --git a/core/primitives/src/receipt.rs b/core/primitives/src/receipt.rs | ||
index 30af36fb9..d5a6632ed 100644 | ||
--- a/core/primitives/src/receipt.rs | ||
+++ b/core/primitives/src/receipt.rs | ||
@@ -1,11 +1,11 @@ | ||
-use crate::borsh::maybestd::collections::HashMap; | ||
+use std::collections::HashMap; | ||
``` | ||
|
||
Otherwise, we would've imported from `hashbrown`: | ||
|
||
```diff | ||
-use crate::borsh::maybestd::collections::HashMap; | ||
+#[cfg(feature = "std")] | ||
+use std::collections::HashMap; | ||
+#[cfg(not(feature = "std"))] | ||
+use hashbrown::HashMap; | ||
``` | ||
|
||
## 3. next we encounter a bunch of similar errors in `near-primitives` with `#[borsh_init(...)]`: | ||
|
||
```bash | ||
1 error: cannot find attribute `borsh_init` in this scope ▐ | ||
--> core/primitives/src/block_header.rs:267:3 ▐ | ||
| ▐ | ||
267 | #[borsh_init(init)] ▐ | ||
| ^^^^^^^^^^ help: a derive helper attribute with a similar name exists: `borsh_skip`▐ | ||
``` | ||
|
||
The syntax of this attribute has changed. We change all of these occurencies according to | ||
`#[borsh(init=<initialization_method>)]` syntax. The following diff is shortened to first and last | ||
occurencies: | ||
|
||
```diff | ||
diff --git a/core/primitives/src/block_header.rs b/core/primitives/src/block_header.rs | ||
index 38491b52c..84ab48238 100644 | ||
--- a/core/primitives/src/block_header.rs | ||
+++ b/core/primitives/src/block_header.rs | ||
@@ -266,3 +266,3 @@ impl ApprovalMessage { | ||
#[derive(BorshSerialize, BorshDeserialize, serde::Serialize, Debug, Clone, Eq, PartialEq)] | ||
-#[borsh_init(init)] | ||
+#[borsh(init=init)] | ||
pub struct BlockHeaderV1 { | ||
... | ||
diff --git a/core/primitives/src/transaction.rs b/core/primitives/src/transaction.rs | ||
index 912120b56..2de7a1d52 100644 | ||
--- a/core/primitives/src/transaction.rs | ||
+++ b/core/primitives/src/transaction.rs | ||
@@ -58,3 +58,3 @@ impl Transaction { | ||
)] | ||
-#[borsh_init(init)] | ||
+#[borsh(init=init)] | ||
pub struct SignedTransaction { | ||
``` | ||
|
||
### 4. next we encounter a large number of similar syntax errors in `near-primitives` package | ||
|
||
```bash | ||
1 error: cannot find attribute `borsh_skip` in this scope ▐ | ||
--> core/primitives/src/transaction.rs:196:7 ▐ | ||
| ▐ | ||
196 | #[borsh_skip] ▐ | ||
| ^^^^^^^^^^ ▐ | ||
▐ | ||
``` | ||
|
||
We change all of these occurencies according to | ||
`#[borsh(skip)]` syntax. The following diff is shortened to first and last | ||
occurencies: | ||
|
||
```diff | ||
diff --git a/core/primitives/src/block_header.rs b/core/primitives/src/block_header.rs | ||
index 84ab48238..6514f8222 100644 | ||
--- a/core/primitives/src/block_header.rs | ||
+++ b/core/primitives/src/block_header.rs | ||
@@ -279,3 +279,3 @@ pub struct BlockHeaderV1 { | ||
/// Cached value of hash for this block. | ||
- #[borsh_skip] | ||
+ #[borsh(skip)] | ||
pub hash: CryptoHash, | ||
... | ||
diff --git a/core/primitives/src/transaction.rs b/core/primitives/src/transaction.rs | ||
index 2de7a1d52..f3ac54ba8 100644 | ||
--- a/core/primitives/src/transaction.rs | ||
+++ b/core/primitives/src/transaction.rs | ||
@@ -62,5 +62,5 @@ pub struct SignedTransaction { | ||
pub signature: Signature, | ||
- #[borsh_skip] | ||
+ #[borsh(skip)] | ||
hash: CryptoHash, | ||
- #[borsh_skip] | ||
+ #[borsh(skip)] | ||
size: u64, | ||
... | ||
``` | ||
|
||
|
||
|
||
## 5. next we encounter 2 errors in `near-primitives` package similar to those in point 2.: | ||
|
||
```bash | ||
1 error[E0433]: failed to resolve: could not find `maybestd` in `borsh` | ||
--> core/primitives/src/action/delegate.rs:119:41 | ||
| | ||
119 | fn deserialize_reader<R: borsh::maybestd::io::Read>( | ||
| ^^^^^^^^ could not find `maybestd` in `borsh` | ||
2 error[E0433]: failed to resolve: could not find `maybestd` in `borsh` | ||
--> core/primitives/src/action/delegate.rs:121:50 | ||
| | ||
121 | ) -> ::core::result::Result<Self, borsh::maybestd::io::Error> { | ||
| ^^^^^^^^ could not find `maybestd` i | ||
n `borsh` | ||
``` | ||
As `near-primitives` crate is not supposed to be used in `no_std` context, we can | ||
replace import with `std::io`: | ||
```diff | ||
diff --git a/core/primitives/src/action/delegate.rs b/core/primitives/src/action/delegate.rs | ||
index 25db73022..ebd009a44 100644 | ||
--- a/core/primitives/src/action/delegate.rs | ||
+++ b/core/primitives/src/action/delegate.rs | ||
@@ -14,3 +14,3 @@ use near_primitives_core::types::{AccountId, Nonce}; | ||
use serde::{Deserialize, Serialize}; | ||
-use std::io::{Error, ErrorKind}; | ||
+use std::io::{Error, ErrorKind, Read}; | ||
|
||
@@ -118,5 +118,5 @@ mod private_non_delegate_action { | ||
impl borsh::de::BorshDeserialize for NonDelegateAction { | ||
- fn deserialize_reader<R: borsh::maybestd::io::Read>( | ||
+ fn deserialize_reader<R: Read>( | ||
rd: &mut R, | ||
- ) -> ::core::result::Result<Self, borsh::maybestd::io::Error> { | ||
+ ) -> ::core::result::Result<Self, Error> { | ||
match u8::deserialize_reader(rd)? { | ||
``` | ||
Otherwise, we would've imported from `borsh::nostd_io`: | ||
```diff | ||
+#[cfg(feature = "std")] | ||
+use std::io; | ||
+#[cfg(not(feature = "std"))] | ||
+use borsh::nostd_io as io; | ||
``` | ||
## 6. next we encounter an error with `BorshDeserialize` trait derivation: | ||
```bash | ||
1 error[E0277]: the trait bound `&T: borsh::BorshDeserialize` is not satisfied | ||
--> core/primitives/src/signable_message.rs:58:26 | ||
| | ||
58 | #[derive(BorshSerialize, BorshDeserialize)] | ||
| ^^^^^^^^^^^^^^^^ the trait `borsh::BorshDeserialize` is not i | ||
mplemented for `&T` | ||
``` | ||
on | ||
```rust | ||
/// A wrapper around a message that should be signed using this scheme. | ||
/// | ||
/// Only used for constructing a signature, not used to transmit messages. The | ||
/// discriminant prefix is implicit and should be known by the receiver based on | ||
/// the context in which the message is received. | ||
#[derive(BorshSerialize, BorshDeserialize)] | ||
pub struct SignableMessage<'a, T> { | ||
pub discriminant: MessageDiscriminant, | ||
pub msg: &'a T, | ||
} | ||
``` | ||
On version change `0.10.3` -> `1.0.0-alpha.3` bounds derivation in `borsh` has changed: | ||
From bounds on the types of the fields: | ||
```rust | ||
impl<'a, T> borsh::de::BorshDeserialize for SignableMessage<'a, T> | ||
where | ||
MessageDiscriminant: borsh::de::BorshDeserialize, | ||
&'a T: borsh::de::BorshDeserialize, | ||
``` | ||
to bounds on type parameters, encountered in fields: | ||
```rust | ||
impl<'a, T> borsh::de::BorshDeserialize for SignableMessage<'a, T> | ||
where | ||
T: borsh::de::BorshDeserialize, | ||
``` | ||
We could potentially patch the bounds on struct to make it compile: | ||
```rust | ||
#[derive(BorshSerialize, BorshDeserialize)] | ||
pub struct SignableMessage<'a, T> { | ||
pub discriminant: MessageDiscriminant, | ||
#[borsh(bound(deserialize="&'a T: borsh::de::BorshDeserialize"))] | ||
pub msg: &'a T, | ||
} | ||
``` | ||
which would transform into following bould on trait's implementation: | ||
```rust | ||
where | ||
&'a T: borsh::de::BorshDeserialize, | ||
``` | ||
But the real issue here is that `borsh` doesn't have a generic implementation | ||
of `BorshDeserialize` for `&'a T`, where `T: borsh::de::BorshDeserialize` (nor did it have it in 0.10.2 version), | ||
and that the derived `BorshDeserialize` wasn't used (and it couldn't be for such a field's type). | ||
So the right change is to remove `BorshDeserialize` derive from the struct: | ||
```diff | ||
diff --git a/core/primitives/src/signable_message.rs b/core/primitives/src/signable_message.rs | ||
index efdd489ac..db97eb1fd 100644 | ||
--- a/core/primitives/src/signable_message.rs | ||
+++ b/core/primitives/src/signable_message.rs | ||
@@ -57,3 +57,3 @@ pub struct MessageDiscriminant { | ||
/// the context in which the message is received. | ||
-#[derive(BorshSerialize, BorshDeserialize)] | ||
+#[derive(BorshSerialize)] | ||
pub struct SignableMessage<'a, T> { | ||
``` | ||
### 7. next we encounter an error in `near-network` package: | ||
```rust | ||
1 error: You have to specify `#[borsh(use_discriminant=true)]` or `#[borsh(use_discriminant=false)]` for all enums with explicit discriminant ▐ | ||
--> chain/network/src/types.rs:56:10 ▐ | ||
| ▐ | ||
56 | pub enum ReasonForBan { ▐ | ||
| ^^^^^^^^^^^^ ▐ | ||
``` | ||
```rust | ||
#[derive(borsh::BorshSerialize, borsh::BorshDeserialize, Debug, Clone, PartialEq, Eq, Copy)] | ||
pub enum ReasonForBan { | ||
None = 0, | ||
BadBlock = 1, | ||
BadBlockHeader = 2, | ||
HeightFraud = 3, | ||
BadHandshake = 4, | ||
BadBlockApproval = 5, | ||
Abusive = 6, | ||
InvalidSignature = 7, | ||
InvalidPeerId = 8, | ||
InvalidHash = 9, | ||
InvalidEdge = 10, | ||
InvalidDistanceVector = 11, | ||
Blacklisted = 14, | ||
} | ||
``` | ||
We fix it with `#[borsh(use_discriminant=false)]` to preserve the behaviour of borsh before | ||
1.0 release which serialized `ReasonForBan::Blacklisted` as 12 instead of 14 | ||
(borsh 0.10 and older [ignored explicit discriminant values in enum definitions](https://github.com/near/borsh-rs/issues/137)): | ||
```diff | ||
diff --git a/chain/network/src/types.rs b/chain/network/src/types.rs | ||
index b2dd97c32..ea2d67f2d 100644 | ||
--- a/chain/network/src/types.rs | ||
+++ b/chain/network/src/types.rs | ||
@@ -55,2 +55,3 @@ pub struct KnownProducer { | ||
#[derive(borsh::BorshSerialize, borsh::BorshDeserialize, Debug, Clone, PartialEq, Eq, Copy)] | ||
+#[borsh(use_discriminant=false)] | ||
pub enum ReasonForBan { | ||
``` | ||
### 8. change in behaviour, unit test error in ci in `near-primitives` package | ||
Assertion fails: | ||
```rust | ||
#[test] | ||
fn test_delegate_action_deserialization() { | ||
// Expected an error. Buffer is empty | ||
assert_eq!( | ||
NonDelegateAction::try_from_slice(Vec::new().as_ref()).map_err(|e| e.kind()), | ||
Err(ErrorKind::InvalidInput) | ||
); | ||
``` | ||
```bash | ||
--- STDERR: near-primitives action::delegate::tests::test_delegate_action_deserialization --- | ||
thread 'action::delegate::tests::test_delegate_action_deserialization' panicked at 'assertion failed: `(left == right)` | ||
left: `Err(InvalidData)`, | ||
right: `Err(InvalidInput)`', core/primitives/src/action/delegate.rs:172:9 | ||
``` | ||
The `ErrorKind` in error in `borsh` has changed, so we apply the following diff: | ||
```diff | ||
diff --git a/core/primitives/src/action/delegate.rs b/core/primitives/src/action/delegate.rs | ||
index ebd009a44..80a0475b6 100644 | ||
--- a/core/primitives/src/action/delegate.rs | ||
+++ b/core/primitives/src/action/delegate.rs | ||
@@ -173,3 +173,3 @@ mod tests { | ||
NonDelegateAction::try_from_slice(Vec::new().as_ref()).map_err(|e| e.kind()), | ||
- Err(ErrorKind::InvalidInput) | ||
+ Err(ErrorKind::InvalidData) | ||
); | ||
``` | ||
And there's also a similar error in | ||
```bash | ||
--- STDERR: near-store tests::test_save_to_file --- | ||
thread 'tests::test_save_to_file' panicked at 'assertion failed: `(left == right)` | ||
left: `InvalidInput`, | ||
right: `InvalidData`', core/store/src/lib.rs:1096:9 | ||
``` | ||
with similar fix. | ||
## 9. errors similar to previous ones, in `near-store`, `near-network` and `near-state-viewer` packages | ||
There was a bunch of `borsh::maybestd` imports, which got replaced by their direct from-`std` counterparts. |