Repository: ChainSafe/forest (Rust)

Issue:
Include the networkID when converting an address from str
**Issue summary**
<!-- A clear and concise description of what the task is. -->
When the string address is valid and contains a valid *network id* and protocol type [Protocol::ID](https://github.com/ChainSafe/forest/blob/main/vm/address/src/lib.rs#L186), the parsed address is being constructed using the default network id instead of the one included in the string being parsed. 
for example:

`let address = Address::from_str("f01")`

then, calling the `to_string()` method will give:

`t01` and not the initial `f01`  

which I think is not correct, unless there are some assumptions or restrictions I do not know about?
The network_id should be included, so something like this would be better?:

```
           if protocol == Protocol::ID {                                                               
               if raw.len() > 20 {                                                                     
                   // 20 is max u64 as string                                                          
                   return Err(Error::InvalidLength);                                                   
               }                                                                                       
               let id = raw.parse::<u64>()?;                                                           
               let mut address = Address::new_id(id);                                                  
               address.set_network(network);                                                           
               return Ok(address);                                                                         
             } 
```  

**Other information and links**
<!-- Add any other context or screenshots about the issue here. -->



<!-- Thank you 🙏 -->


Discussion:
ah, yeah, this was intentionally left out before because the network prefix was never serialized as bytes so there was never any need to store it (the prefix would still be lost whenever an address is serialized as bytes with the current protocol).

I was just leaving to see if they change to serialize the network prefix to bytes before I made this change, but I assume this might be final. 

I just have to think about what is the best way to set this up, since it would be equally as confusing to retain the prefix on stringifying but not on bytes serialization, with also the negative of keeping more data in memory with every address.

Edit: Would you just need a string encode function with a network parameter, like the go implementation, or is there a reason for storing this network prefix with the address?

for ref:
go address string fn: https://github.com/filecoin-project/go-address/blob/6ca104a432f9e6b3353c183773d5645f574a3118/address.go#L92

encode fn (with network param): https://github.com/filecoin-project/go-address/blob/6ca104a432f9e6b3353c183773d5645f574a3118/address.go#L236
I understand It makes sense. 

> Would you just need a string encode function with a network parameter,

about the go-like encode function, no I do not need that, the current stringifying function includes it.

>  or is there a reason for storing this network prefix with the address?

actually, the network id is already part of the address:
```
#[derive(PartialEq, Eq, Clone, Debug, Hash, Copy)]                                                  
 pub struct Address {                                                                                
        network: Network,                                                                               
        payload: Payload,                                                                               
 }  
```
what we need is to be able to get the "exact" address from the string and compare them, although the id is not part of it when serialize to bytes, but it is part of the string being parsed. I see that the id is being included in the other cases where the protocol is different than ID, so I think to keep consistency, we might just include/update it when the protocol ID is used? does it make sense?
 
> actually, the network id is already part of the address:

Honestly been so long since I made that change I had a brain lapse there. Fixed in #611
wow that was fast. Thank you !!



Patch:
diff --git a/vm/address/Cargo.toml b/vm/address/Cargo.toml
index 5c7545ad9069..d3802b84ac8c 100644
--- a/vm/address/Cargo.toml
+++ b/vm/address/Cargo.toml
@@ -2,7 +2,7 @@
 name = "forest_address"
 description = "Filecoin addresses for use in Forest"
 license = "MIT OR Apache-2.0"
-version = "0.2.1"
+version = "0.2.2"
 authors = ["ChainSafe Systems <info@chainsafe.io>"]
 edition = "2018"
 repository = "https://github.com/ChainSafe/forest"
diff --git a/vm/address/src/lib.rs b/vm/address/src/lib.rs
index 814cbcd6a14a..a3920fa2fb7b 100644
--- a/vm/address/src/lib.rs
+++ b/vm/address/src/lib.rs
@@ -189,7 +189,10 @@ impl FromStr for Address {
                 return Err(Error::InvalidLength);
             }
             let id = raw.parse::<u64>()?;
-            return Ok(Address::new_id(id));
+            return Ok(Address {
+                network,
+                payload: Payload::ID(id),
+            });
         }
 
         // decode using byte32 encoding


Test patch:
diff --git a/vm/address/tests/address_test.rs b/vm/address/tests/address_test.rs
index 1ebc56053f6d..8df4068c6dbf 100644
--- a/vm/address/tests/address_test.rs
+++ b/vm/address/tests/address_test.rs
@@ -560,6 +560,16 @@ fn set_network() {
     assert_eq!(addr.to_string(), "f01");
 }
 
+#[test]
+fn from_string_retains_network() {
+    let addr_str = "f01";
+    let addr: Address = addr_str.parse().unwrap();
+    assert_eq!(addr.network(), Network::Mainnet);
+
+    let addr_to_string = addr.to_string();
+    assert_eq!(addr_str, &addr_to_string);
+}
+
 #[test]
 fn invalid_strings_tests() {
     let invalid_strings = &[