Replies: 24 comments
-
I think your proposal simply adds In my view:
|
Beta Was this translation helpful? Give feedback.
-
Fair point.
This serializing (adding the hash type on the end) is consensus-y stuff, right? Perhaps we move to using "encode" in identifiers that do consensus, Bitcoin specified, stuff and leave "serialize" for serde? |
Beta Was this translation helpful? Give feedback.
-
It matches the consensus encoding, yes, but it's also just the standard encoding of these objects (defined by SECG or ASN.1 or whatever) and there isn't really any other encoding. It's common to throw signatures, keys, hashes, etc., into configuration files or caches in ad-hoc ways and I worry that we shouldn't make users use the consensus |
Beta Was this translation helpful? Give feedback.
-
I'm fine with |
Beta Was this translation helpful? Give feedback.
-
FWIW in Fediming we have our own consensus and consensus encoding that is modeled (copied?) from rust-bitcoin one, it's also called "encoding" (Encodabe/Decodable) and it grow on my that "encoding" is for consensus and "serialize" for other serde. |
Beta Was this translation helpful? Give feedback.
-
I think this would make the serialization function harder to find, and that The problem in my view is not about confusing serde with non-serde serializations, but confusing cheap serializers from allocating ones. |
Beta Was this translation helpful? Give feedback.
-
I assume you mean heap allocations only, not stack allocations. FTR I don't care too much. Let's pick a rule and apply it consistently. |
Beta Was this translation helpful? Give feedback.
-
Right -- that's my point. We have a number of places where we call this method (or the same one on (And yes, by "allocation" I mean the kind of allocation that involves a syscall, potentially causes memory fragementation, and requires an allocator be available. Vs the kind where you increment a stack pointer register.) |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
Responding to both the above, what about let serialized = TweakedPublicKey::stack_encode();
foo(&pk.stack_encode());
And for And for this one
```rust
pub fn serialized_signature(&self) -> SerializedSignature { Note that in other places we seem to use 'encode' to serialize to a writer and 'serialize' to serialize to a vector (or String) - this is in line with your comment, right @apoelstra? |
Beta Was this translation helpful? Give feedback.
-
Not really anything referring to the memory location - it's actually caller-decided whether it ends up on stack! We just say stack informally here because that's the intended use case. I guess it should both refer to bytes and to possibly costly transformation of the value into bytes. |
Beta Was this translation helpful? Give feedback.
-
huh? #[inline]
/// Serializes the key as a byte-encoded x coordinate value (32 bytes).
pub fn serialize(&self) -> [u8; constants::SCHNORR_PUBLIC_KEY_SIZE] {
let mut ret = [0u8; constants::SCHNORR_PUBLIC_KEY_SIZE];
unsafe {
let err = ffi::secp256k1_xonly_pubkey_serialize(
ffi::secp256k1_context_no_precomp,
ret.as_mut_c_ptr(),
self.as_c_ptr(),
);
debug_assert_eq!(err, 1);
}
ret
} |
Beta Was this translation helpful? Give feedback.
-
The type returned may end up on heap if you write |
Beta Was this translation helpful? Give feedback.
-
Yeah but that is still clear as to whats happening - allocate some memory and copy something into it. |
Beta Was this translation helpful? Give feedback.
-
That's just the more obvious version. If different pieces of code combined do that you may not see it directly and it ends up on heap after inlining. But the main idea is that while we do say "this method allocates" for allocating code, we should never say "this type is certainly on stack". And nowhere in Rust is |
Beta Was this translation helpful? Give feedback.
-
I agree we shouldn't say @Kixunil yeah, I also agree that |
Beta Was this translation helpful? Give feedback.
-
Is that even possible given upstream doesn't guarantee the layout? Or is it going to stabilize/already stable? |
Beta Was this translation helpful? Give feedback.
-
It's possible because we vendor a specific version of upstream. |
Beta Was this translation helpful? Give feedback.
-
Do we want to go that far given there was interest in dynamic linking? We could obviously not use the Rust code if linking is dynamic but maybe that's too much? |
Beta Was this translation helpful? Give feedback.
-
When we do dynamic linking we probably want to do some sanity checks anyway. One of those could be "does the dynamic library encode points and signatures the way we expect". In practice I think this check would never trigger (upstream has never changed the format of these types without also changing their size, which is a breaking API change according to their own rules) but it would mean that if it did trigger, it'd be a visible failure not a "silently wrong crypto" one. Alternately, we could define our own internal format for signatures and public keys and internally convert before doing "real" crypto. I believe we could set this up so that we never paid the FFI cost except when we were already paying a 10s-of-microsecond crypto cost. Note that for signatures and uncompressed keys, the libsecp parsing code is almost free since it just memcpys and does some range checks. So I think we have some options, and we don't need to say "can't ever rustify the parsing code" on account of dynamic linking. |
Beta Was this translation helpful? Give feedback.
-
Do we really need to check anything else than version? We know that if major version matches it's OK unless whoever built the library made some non-standard changes in which case they get UB but they would get it regardless of our checks.
I really like this. Especially given that maybe we can somehow detect that the format is actually the same and then just pass the pointer without conversion. This also goes hand in hand with making the sys crate optional. |
Beta Was this translation helpful? Give feedback.
-
cc @LLFourn because we were talking about exactly this on the weekend. |
Beta Was this translation helpful? Give feedback.
-
I think it's fine to have It would be great if sys crate could be optional with some clever encoded newtypes used instead of types that need ffi calls to do encoding etc. I don't see why it wouldn't work but my knowledge is limited. |
Beta Was this translation helpful? Give feedback.
-
Converted to a discussion because as an issue there was no action that could close it. Opened #2583 also. |
Beta Was this translation helpful? Give feedback.
-
Currently we overload serialization terms and there is no obvious and easy way to distinguish them
serde
: Usesserialize
anddeserialize
Encodable
,consensus_encode
,Decodable
,consensus_decode
serialize
, sometimesto_bytes
Possible solution
serde
, includes any arbitrary serializationconsensus::Encode::encode
andconsensus::Decode::decode
for things that are governed by consensus rulesmarshal
andunmarshal
for things that have a specific custom serialization governed by a convention or BIP eg, PSBTBeta Was this translation helpful? Give feedback.
All reactions