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
WIP: Implement TransactionSet
derivation
#539
Conversation
I'm afraid this is the most is possible to do right now with derivation. It could be possible to force transactions within |
I wonder can we implement derivation on top of the rust enums with the some attributes? #[derive(TransactionSet)]
#[transaction_set(service_id = "10")]
enum MyTransactions {
TxFirst {
from: PublicKey,
data: Vec<u8>,
},
TxSecond {
from: PublicKey,
data: String
}
} There is one limitation: we can't use constants in the attributes. |
@alekseysidorov That's an interesting idea: to automatically create message types for variants. That is, the code above would generate pub struct TxFirst {
raw: RawMessage,
}
impl TxFirst {
// ...
}
// other auto-gen implementations currently generated by `messages!` May be worth a try (and if proc macros are processed before "ordinary" ones, it would be easy to prototype, too - just read variants and shove them into a enum Transactions<'a> {
TxFirst {
pub from: &'a PublicKey,
pub data: &'a [u8],
},
TxSecond {
pub from: &'a PublicKey,
pub data: &'a str,
}
} (in which case transactions become non-owning thin wrappers around byte buffers - not quite sure it will bode well with the current paradigm of transaction processing, tbh), or somehow determine ownership and map types correspondingly when processing the macro. Do I understand correctly that you propose the second approach? Or is your proposition will be most valid after changing transaction serialization principles?
What do you mean? I think we can make at least this to work: pub const SERVICE_ID: u16 = 10;
#[derive(TransactionSet)]
#[exonum(service_id = "SERVICE_ID")]
enum MyTransactions { /* ... */ } just as |
Now we can invoke |
Looks promising, but I'm a little bit concerned about one aspect of this change. |
@DarkEld3r
But it does declare a separate type for the let tx = Transactions::Transfer {
public_key: &my_pubkey,
to: &some_other_pubkey,
amount: 100,
seed: 1,
};
let tx: Box<Transaction> = tx
.sign(&my_secret_key)
.into(); This is, imo, quite an improvement over the current syntax of transaction creation. |
As for me, transactions first of all isn't just some data type. It is exonum transaction: specific logic plus data. 🙃 |
One more thought. Can we (theoretically and in the future) expand |
interesting can we generate json spec for light client in the transaction documentation? |
Here is a very rough sketch of how codegen might look like if we take my idea about non-owning transactions (the user code is at the bottom). I'll give it a try in the next couple of days. The only worry is that it can become obsolete if we choose owning transactions when serialization is changed.
Seems like it, but it can probably wait 😃 |
- `Check` checks a raw message against schema - `Read` reads from a raw message - `Write` creates a message
(`SegmentField` and `StorageValue` traits.)
I've managed to make borrowed transactions to work; see this file for an example of what it looks like. Couple of comments: 1. Changes are backward-compatible (seemingly; needs more testing) 2. Transaction payload and wire format are completely separated. If you look at // in `exonum::messages`
pub struct Wrapper<T> {
raw: RawMessage,
_marker: ::std::marker::PhantomData<T>,
}
// implementations of `Message`, `ExonumJson`, etc. However, this currently doesn't work, because |
It allows to fix code for owned fields in `MessageSet` derivation.
...That is, variants like `CreateWallet(&'a PublicKey, &'a str)`. The support is a little sketchy.
} | ||
|
||
/// Writes given field taken by a shared reference to the given offset. | ||
pub fn write_ref<'a, F: Field<'a>>(&'a mut self, field: &F, from: Offset, to: Offset) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the reason behind adding new method? Let's pass field
by reference in the original write
Can we close this and repeat work sometimes later? @DarkEld3r @slowli |
Severely outdated. |
Seeing the struggles with #532, I've decided to try implementing it with procedural macros:
I'd be eager to expand the approach to the messages themselves as well, but it is hindered by uncertainties with their serialization.