-
Notifications
You must be signed in to change notification settings - Fork 98
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
Rust protobuf API #525
Rust protobuf API #525
Conversation
I know, you don't need to tell me that there are too many vendored files that we don't need :( No idea how to improve that. Edit: this might be the culprit: |
Did you try with a |
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.
Very cool! Actually, amazing. A couple items to discuss:
- would it make sense work on this in a separate "prost" branch?
- I'd personally prefer to wait for prost release; we're not in a hurry, are we
- try
cargo +nightly vendor -Z avoid-dev-deps
or something like that
This is a working demo
It's not really a demo anymore. It does process a valid API call, even though it's just one for now.
tools/prost-build/src/main.rs
Outdated
// limitations under the License. | ||
|
||
fn main() { | ||
let messages_dir = std::env::var("MESSAGES_DIR").expect("MESSAGES_DIR env var not set"); |
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.
Why not use a command line flag?
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.
My issue with env vars is I see this:
MESSAGES_DIR=${CMAKE_CURRENT_SOURCE_DIR}
cargo run --manifest-path=${CMAKE_SOURCE_DIR}/tools/prost-build/Cargo.toml
and I have no idea whether it was a mistake, typo or MESSAGES_DIR
is really used in the next command.
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.
idk, seemed consistent with OUT_DIR imposed by prost-build. And no CLI parsing needed ;)
I will look into it.
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.
yeah, that's even more confusing imho:
prost_build::compile_protos(&["hww.proto"], &[&messages_dir]).unwrap();
So, compile_protos
takes in what to compile in function arguments, but somehow it wants an env var for the output... that looks very inconsistent, wouldn't you agree?
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.
i think OUT_DIR is imposed by the rust build.rs architecture 🤷
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.
I'm just saying that the reason that prost-build uses OUT_DIR
is because cargo sets that environment variable when it runs a build.rs
file. You should, on the other hand, use command line arguments to pass input files and output dirs.
I think build.rs
files are useful for rust-only projects, but they are kind of evil in that they can do arbitrary things at compile time (like fetching stuff from ze internets). So I try to avoid them. In your case it is better to create a separate tool (like you've done) and run it separately from cargo. This reduces the number of deps on your main project and (when you move it to docker) reduces the overall build time.
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.
I'm split regarding if the generated sources should be committed. One benefit of committing them is that you notice if you by mistake use a tool that generates new/different output. (Maybe you locally have the wrong version installed for some reason..)
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.
Like @benma, I'd prefer to check in generated sources. We already do it in py/bitbox02 here and in api-go, api-js. Also, similar with vendoring Go pkgs in the wallet app. It's always nice to rely on git and see what's changed.
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.
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.
Hmm somehow I didn't push properly. Pushed again now.
it's not a dev dependency though. |
Ah right. Didn't pay enough attention. |
That helped. 3755 files down to 185 👏 Fork here: https://github.com/digitalbitbox/bytes/tree/bitbox02-firmware-20200702 |
334f641
to
3b2c083
Compare
Almost forgot: add clippy to pass over |
To reiterate what I said in a thread. I think it makes sense to compile the tool when you create the docker image instead of every time you compile the sources. So I think the tool should take "OUT_DIR" and "MESSAGES_DIR" as the two input arguments. You don't need especially sophisticated arg parsing: fn main() {
let mut args = std::env::args().into_iter();
let _ = args.next().unwrap(); // executable name
let out_dir = args.next().unwrap();
let messages_dir = args.next().unwrap();
println!("{} {}", out_dir, messages_dir);
} |
I think |
Hmm I just recompiled and almost didn't notice the compilation, was very quick, definitely nowhere near a minute.
But I really much prefer named args over positional args, and the code is much nicer too :O
Edit: tried with |
WAT.. haha edit: or maybe it slowed down the overall thing because it added more time to the compilation of the tool than it removed from the run time? |
Yeah I meant the compile time, in response to
Run time is probably better, but compiling those handful of proto files is fast no matter what. |
@NickeZ didn't you also suggest to add the compiled tool to the docker image? :) Also, @benma @NickeZ is |
Re: clap. At the end of the day, how often are we going to regenerate proto sources. I think quite rarely if they're checked in. |
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.
Cool! One other very minor thing:
Almost forgot: add clippy to pass over tools/prost-build/ or tools/...? I know it's just 2 lines for code but maybe we'll have more with time.
license = "Apache-2.0" | ||
|
||
[dependencies] | ||
clap = "3.0.0-beta.1" |
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.
Why not the latest non-beta release 2.33
?
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.
Why non-beta? beta is working.
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.
stability? otherwise, why call things "beta".
git master/HEAD is also working. why not always pull from latest git all the deps then :)
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.
api stability is out anyway, as 2.33 -> 3.0.0 is breaking. I expect less work to upgrade to 3.0.0 from the beta than from 2.33. Probably no work, would be a surprise if they changed the api that breaks our 4 line use of it.
If you insist I can do it, but imho it's working okay ;)
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.
I expect less work to upgrade to 3.0.0 from the beta than from 2.33
That's the explanation I expected! Makes sense. Good as is then, considering it's 4 lines like you said. 👍
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.
Well, not expected really but it makes sense either way.
CI will do it everytime, right, as to the CI, the .proto files are always new. So probably worth it to put it into the Docker image eventually to shorten CI time. |
Exactly, so that should make long compile time of clap less annoying. |
So, what's left here, this?
and clippy to run over |
I am not sure my cmake skills are up to the task. The only thing I can come up is to make another custom target like |
Sounds good without clippy!
…On 7/9/20 11:50 PM, benma wrote:
> and clippy to run over `tools/...`
I am not sure my cmake skills are up to the task. The only thing I can come up is to make another custom target like `rust-clippy-tools`, which kinda sucks, but it is in a different `WORKING_DIRECTORY`. i am inclined to just skip it, seeing that the tool is totally trivial.
|
Rebased. |
We make a small cli tool, used in CMakeLists, similar to nanopb. The generated file lands in the source folder and is committed. I prefer this over generating into the build folder. The advantages are: - Less reliance on the tool to work when you check out and old commit - The rust crates do not depend on CMake in this way, which should make it easier to use standard Rust tooling (though more work is - needed there).
Used in bitbox02-rust to decode and encode protobuf messages.
Added a commit resolving this part too, PTAL. Imho we shouldn't wait longer for the prost release, and use the GitHub dependency as is in this PR. The release will come when it will come. In the meantime, we shouldn't be blocked from going further with Rust api call processing. WDYT? |
5907bd5
to
523c79c
Compare
👍 let me try this on a dev device... |
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.
It appears clippy isn't running and a tiny bit unhappy. We should add it to the CI.
return mock(); | ||
} | ||
|
||
static void _test_api_set_device_name(void** state) |
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.
Too bad this commit deletes a unit test without an equivalent replacement, or there one in rust that I don't see?
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.
If not, any chance to export commander_api_set_device_name
from rust to use here in the test?
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.
Imho we should start thinking about how to properly unit test Rust code that references C code, and then add some tests for all code. Propably will involve some extra traits, but not quite clear. This has been a blocker to write good unit tests in Rust in general. Happy to maximize coverage then.
There is no big loss in removing this test until we have that.
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.
👍
/// `input` is a hww.proto Request message, protobuf encoded. | ||
/// Returns a protobuf encoded hww.proto Response message. | ||
pub async fn process(input: Vec<u8>) -> Vec<u8> { | ||
use prost::Message; |
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.
I thought we agreed to use global imports with an exception of enums where makes sense, or did I misunderstood?
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.
Yeah this line preceeds this discussion.
I plan to split the individual api calls into individual files after this is merged, so I would move the use
to the top level then, ok?
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.
👍
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.
Actually I thought we were in the device name api function. Fixed it for prost::Message
, which will stay in this file even when I move the api calls to other files.
// All A-Okay. | ||
will_return(__wrap_workflow_confirm_blocking, true); | ||
will_return(__wrap_memory_set_device_name, true); | ||
assert_int_equal(COMMANDER_OK, commander_api_set_device_name(&request)); |
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.
The func declaration is still in test/unit-test/framework/includes/test_commander.h. That should be removed too, right.
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.
Good catch, fixed!
fixed and added to CI. PTAL |
Moving the commander states check calls from C to Rust makes sure that API calls handled in Rust obey the same rules, e.g. that SetDeviceName cannot be called in the middle of a Bitcoin tx signing session.
api::api is bad (clippy), so we move it to mod.rs.
LGTM. Hope to see more tests soon! |
This is a working demo of how to use Prost to handle our protobuf api in an async manner.
I am using the prost deps from github as the no_std fixes are not released yet, see https://github.com/danburkert/prost/issues/329. We can discuss if we should move ahead anyway or wait for the release.
bitbox02_rust::hww::api::process
corresponds to the Ccommander()
.Still missing:
commander_states_can_call()
check fromcommander()
- I didn't add it yet to keep the code smaller for review, will add as soon as the concept is approved.