I have a project where I have a struct that looks like this:
pub struct Msg1Sender {
c_u: Vec<u8>,
secret: StaticSecret,
X_u: PublicKey,
static_secret: EphemeralSecret,
static_public: PublicKey,
APPEUI : Eui64,
kid: Vec<u8>,
auth: [u8; 64], //remove
}
that is constructeed like this:
impl PartyU<Msg1Sender> {
pub fn new(
c_u: Vec<u8>,
ecdh_secret: [u8; 32],
stat_priv: EphemeralSecret,
stat_pub: PublicKey,
APPEUI : Eui64,
kid: Vec<u8>,
) -> PartyU<Msg1Sender> {
// From the secret bytes, create the DH secret
let secret = StaticSecret::from(ecdh_secret);
// and from that build the corresponding public key
let X_u = PublicKey::from(&secret);
// Combine the authentication key pair for convenience
let mut auth = [0; 64]; //remove
PartyU(Msg1Sender {
c_u,
secret,
X_u,
static_secret:stat_priv,
static_public:stat_pub,
APPEUI,
kid,
auth //slettes
})
}
...
and then I have the following code in another file:
let msg1_sender =
PartyU::new(u_c_u, u_priv, v_static_priv, v_static_pub,APPEUI, u_kid);
println!("{:?}", msg1_sender.APPEUI);
Where I am trying to print a field on the struct.
This I can not do. I get the error:
no field `APPEUI` on type `oscore::edhoc::PartyU<oscore::edhoc::api::Msg1Sender>`
unknown field
help: one of the expressions' fields has a field of the same name: `0.`
Adding pub keywords to the fields I am trying to access makes no difference
Which makes no sense to me. the field exists. Why is this happening?
EDIT
I can now understand that the type I am trying to access is of type
PartyU<oscore::edhoc::api::Msg1Sender>
My mistake.
But If I now try to access the msgsender object by writing:
msg1_sender.0.APPEUI
It still fails with:
field `0` of struct `oscore::edhoc::PartyU` is private
Which again is strange to me, since the struct is public:
pub struct PartyU<S: PartyUState>(S);
// Necessary stuff for session types
pub trait PartyUState {}
impl PartyUState for Msg1Sender {}
impl PartyUState for Msg2Receiver {}
//impl PartyUState for Msg2Verifier {}
//impl PartyUState for Msg3Sender {}
/// Contains the state to build the first message.
pub struct Msg1Sender {
c_u: Vec<u8>,
secret: StaticSecret,
x_u: PublicKey,
static_secret: EphemeralSecret,
static_public: PublicKey,
pub APPEUI : Eui64,
kid: Vec<u8>,
auth: [u8; 64], //remove
}
impl PartyU<Msg1Sender> {
What part is it that I need to mark as public?
PartyU is a struct tuple, so in order to access the inner struct you have to access with .0.
Then after that, the Error code is clear:
field 0 of struct oscore::edhoc::PartyU is private
unless marked as pub, struct attributes are private and can only be accessed from the structs current module. You have to options to make them publicly available:
pub makes it public for any scope
pub(crate) makes it public for the crate where the struct lives in
pub struct PartyU(pub Msg1Sender);
pub struct Msg1Sender {
pub c_u: Vec<u8>,
pub secret: StaticSecret,
pub X_u: PublicKey,
pub static_secret: EphemeralSecret,
pub static_public: PublicKey,
pub APPEUI : Eui64,
pub kid: Vec<u8>,
pub auth: [u8; 64], //remove
}
Related
I wonder whether there's a way to preserve the original String using serde_json? Consider this example:
#[derive(Debug, Serialize, Deserialize)]
struct User {
#[serde(skip)]
pub raw: String,
pub id: u64,
pub login: String,
}
{
"id": 123,
"login": "johndoe"
}
My structure would end up containing such values:
User {
raw: String::from(r#"{"id": 123,"login": "johndoe"}"#),
id: 1,
login: String::from("johndoe")
}
Currently, I'm doing that by deserializing into Value, then deserializing this value into the User structure and assigning Value to the raw field, but that doesn't seem right, perhaps there's a better way to do so?
This solution uses the RawValue type from serde_json to first get the original input string. Then a new Deserializer is created from that String to deserialize the User type.
This solution can work with readers, by using Box<serde_json::value::RawValue> as an intermediary type and it can also work with struct which borrow from the input, by using &'de serde_json::value::RawValue as the intermediary. You can test it in the solution by (un-)commenting the borrow field.
use std::marker::PhantomData;
#[derive(Debug, serde::Serialize, serde::Deserialize)]
#[serde(remote = "Self")]
struct User<'a> {
#[serde(skip)]
pub raw: String,
pub id: u64,
pub login: String,
// Test for borrowing input data
// pub borrow: &'a str,
#[serde(skip)]
pub ignored: PhantomData<&'a ()>,
}
impl serde::Serialize for User<'_> {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
Self::serialize(self, serializer)
}
}
impl<'a, 'de> serde::Deserialize<'de> for User<'a>
where
'de: 'a,
{
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
use serde::de::Error;
// Deserializing a `&'a RawValue` would also work here
// but then you loose support for deserializing from readers
let raw: Box<serde_json::value::RawValue> = Box::deserialize(deserializer)?;
// Use this line instead if you have a struct which borrows from the input
// let raw = <&'de serde_json::value::RawValue>::deserialize(deserializer)?;
let mut raw_value_deserializer = serde_json::Deserializer::from_str(raw.get());
let mut user =
User::deserialize(&mut raw_value_deserializer).map_err(|err| D::Error::custom(err))?;
user.raw = raw.get().to_string();
Ok(user)
}
}
fn main() {
// Test serialization
let u = User {
raw: String::new(),
id: 456,
login: "USERNAME".to_string(),
// Test for borrowing input data
// borrow: "foobar",
ignored: PhantomData,
};
let json = serde_json::to_string(&u).unwrap();
println!("{}", json);
// Test deserialization
let u2: User = serde_json::from_str(&json).unwrap();
println!("{:#?}", u2);
}
Test on the Playground.
in the Basic-5 tutorial of the project-serum/anchor repo
How can I replace #[associated]
with something like this:
#[account(seeds = [user_data.deposit_last.as_ref(), &[user_data.__nonce]])]
There is something not correct above, then Anchor fails to read the associated account's values
const userData = await program.account.userData.associated(wallet1, usdcMint);
So what is the correct way to replace this soon-to-be-deprecated #[associated] above the associated account struct?
#[associated]
#[derive(Default)]
pub struct UserData {
pub authority: Pubkey,
pub deposit_last: i64,
pub shares: u64,
pub reward_debt: u64,
}
//UserData is initialized here first
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(init, associated = authority, with = usdc_mint)]
pub user_data: ProgramAccount<'info, UserData>,
...
}
So the seed approach is a PDA, which is actually what #associated was using underneath the hood
You will need a function that initializes the seed with the below init and payer trait. payer should also be the same user who is actually paying the for transaction.
Please note that #[instruction(bump: u8] is matching the signature of the function here, hence you will need to pass in the bump in the signature as the first argument.
#[instruction(bump: u8)]
pub struct Ctx<'info> {
#[account(init, seeds = [user_data.deposit_last.as_ref(), &[bump]], payer = payer)]
pub user_data = ProgramAccount<'info, UserData>,
}
Later on for other functions if you want just want to read the account, you can just use
#[account(seeds = [user_data.deposit_last.as_ref(), &[user_data.__nonce]])]
pub user_data = ProgramAccount<'info, UserData>,
Change your account data to use #[account] instead of #[associated]
#[account]
#[derive(Default)]
pub struct UserData {
pub authority: Pubkey,
pub deposit_last: i64,
pub shares: u64,
pub reward_debt: u64,
}
Here is an example https://github.com/project-serum/anchor/blob/master/examples/misc/programs/misc/src/context.rs#L10
This question already has answers here:
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
Closed 6 months ago.
I'm trying to create a simple collection:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=361258962c9a25b953aab2a9e4999cc9
use std::collections::HashMap;
pub struct User {
pub id: u32,
pub name: String,
}
pub struct UsersIndex<'a> {
list: Vec<User>,
index: HashMap<u32, &'a User>,
}
impl UsersIndex<'_> {
pub fn new() -> Self {
UsersIndex {
list: Vec::new(),
index: HashMap::new(),
}
}
pub fn add(&mut self, user: User) {
self.list.push(user);
self.index.insert(user.id, &user);
}
pub fn get(&self, id: u32) -> Option<&&User> {
self.index.get(&id)
}
}
but can not fix the errors:
use of moved value: user
user does not live long enough
As I understand I have to take ownership of User, but google doesn't help me how to do it.
Rust says that I need to implement the Copy trait, but User contains a field of type String.
The issue with this code is the following:
pub fn add(&mut self, user: User) {
self.list.push(user); // Here, you move user to the list. The list owns user
self.index.insert(user.id, &user); // Then, you create a reference of a moved value
}
So, in your UserIndex struct, you want to store values and references of these values. These are called self-referential structs. With the ownership rules of Rust, you need to use unsafe Rust code to achieve this. If I were you, I'd think of a different way of implementing your collection following the Rust conventions. For example, you could do something like this:
use std::collections::HashMap;
pub struct User {
pub id: u32,
pub name: String,
}
pub struct UsersIndex {
index: HashMap<u32, User>, // I only use the HashMap. The HashMap owns the User structs
}
impl UsersIndex {
pub fn new() -> Self {
UsersIndex {
index: HashMap::new(),
}
}
pub fn add(&mut self, user: User) {
self.index.insert(user.id, user); // user is moved to the HashMap
}
pub fn get(&self, id: u32) -> Option<&User> { // Instead of a nested reference, we get a regular reference
self.index.get(&id)
}
}
fn main() {
let user = User {
id: 42,
name: "test".to_string(),
};
let mut index = UsersIndex::new();
index.add(user);
match index.get(42) {
Some(usr) => println!("{}", usr.name),
_ => println!("Not Found"),
}
}
Here you can find a playground with this implementation.
EDIT
If you need different HashMaps for the same User structs depending on the key used, you can use Rc smart pointers. They allow you to create more than one pointer that owns the same struct. It would look more or less like this:
use std::rc::Rc;
use std::collections::HashMap;
pub struct User {
pub id: u32,
pub name: String,
}
pub struct UsersIndex {
index: HashMap<u32, Rc<User>>, // Keys will be the user indeces
name: HashMap<String, Rc<User>>, // Keys will be the user names
}
impl UsersIndex {
pub fn new() -> Self {
UsersIndex {
index: HashMap::new(),
name: HashMap::new()
}
}
pub fn add(&mut self, user: User) {
// user will be moved, so we copy the keys before that:
let user_id = user.id;
let user_name = user.name.clone();
let user_rc = Rc::new(user); // We create the Rc pointer; user is moved to user_rc
self.index.insert(user_id, user_rc.clone()); // Rc pointers can be cloned
self.name.insert(user_name, user_rc); // user_rc is moved to the self.name HashMap
}
pub fn get(&self, id: u32) -> Option<Rc<User>> {
match self.index.get(&id) {
Some(user) => Some(user.clone()),
None => None
}
}
}
fn main() {
let user = User {
id: 42,
name: "test".to_string(),
};
let mut index = UsersIndex::new();
index.add(user);
match index.get(42) {
Some(usr) => println!("{}", usr.name),
_ => println!("Not Found"),
}
}
Here you can find a playground with this new implementation.
Again, if you also need the User structs to be mutable, then you'll probably need to use an Rc<RefCell<User>> (link here).
Hope you find this useful!
I'm trying to figure out how to add a field that is a cryptographic hash of other fields. I have:
pub struct Message {
pub size: usize,
pub id: MessageId,
pub attribute: MessageAttribute,
}
I'd like to have something like:
pub struct Message {
pub size: usize,
pub id: MessageId,
pub attribute: MessageAttribute,
pub hash: MessageHash,
}
pub struct MessageHash(pub Vec<u8>);
I could create another struct and then compute the hash when setting up the struct:
pub struct HashedMessage {
pub content: Message,
pub hash: MessageHash,
}
pub fn message_hash(data: &Message) -> MessageHash {
let mut hasher = DefaultHasher::new();
data.hash(&mut hasher);
MessageHash(hasher.finalize().to_vec())
}
let content = Message { /* ... */ };
let hash = hash_message(msg);
let msg = HashedMessage { content, hash };
This method introduces another struct, and I would have to change the codebase to use the new struct in place of the old one.
Another way I is to have a new method that receives each member of the struct, and then output the final struct with the hash field computed over the inputs. This seems reasonable. A possible option would be to set the hash to 0 in this method and then compute the hash using message_hash over the Message struct (the first one, with hash field embedded), and then assign it.
Is there another way? What would be an idiomatic, correct way to add a hash? These are messages that will be serialized and sent over the wire, so I can't have a method that will compute the hash every time.
You can use composition like this:
pub struct Message {
pub size: usize,
pub id: MessageId,
pub attribute: MessageAttribute,
}
pub struct Hashed<M> {
pub hash: MessageHash,
pub message: M,
}
impl<M> Hashed<M> {
fn new(message: M) -> Self {
let hash = compute_hash(&message);
Self {
hash,
message,
}
}
}
Then you can use either Message or Hashed<Message>.
If you have a Hashed<Message> but you need a Message, you can borrow that field. Going the other way, you'd have to create a new Hashed<Message> and compute the hash again.
The Rust playground code is here.
I have a struct of Token which has lifetime 'tok, and a scanner has lifetime 'lexer. I'm using both of them in another struct Parser, then I had a problem:
pub struct Token<'tok> {
pub value: Cow<'tok, str>,
pub line: usize,
}
pub struct Scanner {
pub source: Vec<char>,
pub current: usize,
pub line: usize,
}
pub struct Parser<'lexer> {
pub curr: &'lexer Token<'lexer>,
pub prev: &'lexer Token<'lexer>,
scanner: &'lexer mut Scanner,
}
impl <'lexer> Parser<'lexer> {
pub fn advance(&mut self) {
self.prev = self.curr;
self.curr = &self.scanner.next(); // cannot inference lifetime
}
}
I think the problem is Token has lifetime 'tok, and the borrow checker doesn't know the relation between 'tok and 'lexer so it can't inference proper lifetime.
However, I can avoid the problem by modifying it into the updated code:
pub struct Parser<'lexer> {
pub curr: Token<'lexer>,
pub prev: Token<'lexer>,
scanner: &'lexer mut Scanner,
}
impl <'lexer> Parser<'lexer> {
pub fn advance(&mut self) {
let prev = std::mem::replace(&mut self.curr, self.scanner.next());
self.prev = prev;
}
}
And with Token produced by next() is static:
impl Scanner {
pub fn next(&mut self) -> Token<'static> {
Token {
value: Cow::from(""),
line: 0,
}
}
}
It does compile but I think it's not ideal because all tokens are cloned from scanner into parser(they are not references anymore) and living until end of Parser's life. So memory usage is doubled. Is there a more proper way to deal with this?
Actualy your code structure is not ideal to deal with the borrow checker here why:
Token struct should be owned, the struct itself do not require any allocations (as the token is owned some indrection are required to allow prev <-> next switching)
None of the Parser or Lexer should own the base data so it will be easy to bound proper lifetime
In our case Vec<Char> is not a friendly type to work with (we do not need to own the data and this will be harder to make the comipler understand lifetimes), instead we're going to use an &'str but you could reproduce the exact behaviours with an &[char])
Here is an example that compile just fine
pub struct Token<'source> {
pub value: Cow<'source, str>,
pub line: usize,
}
pub struct Scanner<'source> {
pub source: &'source str,
pub current: usize,
pub line: usize,
}
pub struct Parser<'source> {
pub curr: Option<Token<'source>>,
pub prev: Option<Token<'source>>,
scanner: Scanner<'source>,
}
impl <'source>Scanner<'source> {
pub fn next(&'source /* DONT Forget to bound 'source to `self` */ self) -> Token<'source> {
Token {
value: Cow::from(self.source), /* `self.source` is bound to `'source` so the compiler understand that the token lifetime is the same than the source's one */
line: 0,
}
}
}
impl <'lexer> Parser<'lexer> {
pub fn advance(&'lexer mut self) {
self.prev = self.curr.take();
self.curr = Some(self.scanner.next());
}
}