-
Notifications
You must be signed in to change notification settings - Fork 1
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
Blake2b F precompile #2
Conversation
Also added myself as an author
Should have a working geth precompile and initial benchmarks shortly
While 2046's cheaper precompile contract calls aren't a requirement for this EIP's implementation, shipping this precompile without EIP-2046 would make the F function expensive for some of the motivating usecases.
## Implementation | ||
<!--The implementations must be completed before any EIP is given status "Final", but it need not be completed before the EIP is accepted. While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of "rough consensus and running code" is still useful when it comes to resolving many discussions of API details.--> | ||
|
||
Implementations are in progress, and can be followed along in our [Golang Blake2 library fork](https://github.com/keep-network/blake2-f) as well as our fork of [go-ethereum](https://github.com/keep-network/go-ethereum). |
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.
This is only F
function implementation extracted from Golang Blake2 lib, should we make it clear here?
(Original Golang Blake2 lib does not export F
out)
## Specification | ||
<!--The technical specification should describe the syntax and semantics of any new feature. The specification should be detailed enough to allow competing, interoperable implementations for any of the current Ethereum platforms (go-ethereum, parity, cpp-ethereum, ethereumj, ethereumjs, and [others](https://github.com/ethereum/wiki/wiki/Clients)).--> | ||
|
||
Adds a precompile at address `0x0d` which accepts [ABI encoded](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI) arguments corresponding to the function signature |
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.
Per our discussion, we should update the part about ABI encoded parameters.
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 recommend we move implementation discussion to the blake2-f library's first PR- WDYT?
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.
@carterpy Can you please repost your questions in the PR referenced by @mhluongo? I can happily answer them there.
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.
@pdyraga, questions removed because they were actually silly :$
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.
Here is an alternative proposition about how to call the F
function.
Instead of ABI-encoded parameters (no precompile currently do that) we can use a standard staticcall
.
I'd propose the following structure:
[ bytes32[0] | bytes32[1] ][ bytes32[2] | bytes32[3] | bytes32[4] | bytes32[5] ]
[ 64 bytes for h ][ 128 bytes for m ]
[ bytes32[6] ][ bytes32[7] ]
[ 24 bytes padding | 8 bytes for t_0 ][ 24 bytes padding | 8 bytes for t_1 ]
[ bytes32[8] ][ bytes32[9] ]
[ 31 bytes padding | 1 byte for f ][ 28 bytes padding | 4 bytes for rounds]
where:
h
- state vectorm
- message block vectort_0, t_1
- offset counterf
- final block indicator flagrounds
- number of rounds
This way we pack data in equal 32-byte (256-bit) slots, we are compatible with the rest of precompile calls and we do not require any bitwise juggling from callers.
For convenience, one may expose a wrapping function, similar to F
:
function F(bytes32[2] memory h, bytes32[4] memory m, uint64[2] memory t, bool f, uint32 rounds) public view returns (bytes32[2] memory) {
bytes32[2] memory output;
bytes32 _t0 = bytes32(uint256(t[0]));
bytes32 _t1 = bytes32(uint256(t[1]));
bytes32 _f;
if (f) {
_f = hex"0000000000000000000000000000000000000000000000000000000000000001";
}
bytes32 _rounds = bytes32(uint256(rounds));
bytes32[10] memory args = [ h[0], h[1], m[0], m[1], m[2], m[3], _t0, _t1, _f, _rounds ];
assembly {
if iszero(staticcall(not(0), 0x09, args, 0x140, output, 0x40)) {
revert(0, 0)
}
}
return output;
}
function callF() public view returns (bytes32[2] memory) {
bytes32[2] memory h;
h[0] = hex"6a09e627f3bcc909bb67ae8484caa73b3c6ef372fe94b82ba54ff53a5f1d36f1";
h[1] = hex"510e527fade682d19b05688c2b3e6c1f1f83d9abfb41bd6b5be0cd19137e2179";
bytes32[4] memory m;
m[0] = hex"278400340e6b05c5752592c52c4f121292eafc51cc01a997b4aed13409298fad";
m[1] = hex"0d99ccc8f76453d9b3661e5c4d325d7751147db17489046d1682d50eefa4a1da";
m[2] = hex"0000000000000000000000000000000000000000000000000000000000000000";
m[3] = hex"0000000000000000000000000000000000000000000000000000000000000000";
uint64[2] memory t;
t[0] = 18446744073709551552;
t[1] = 18446744073709551615;
bool f = true;
uint32 rounds = 12;
return F(h, m, t, f, rounds);
}
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.
(this looks terrible at the first sight, but this is similar to how other precompiles are called with assembly 🤷♀ - they are all equally terrible).
|
||
Interoperability with Zcash could enable contracts like trustless atomic swaps between the chains, which could provide a much needed aspect of privacy to the very public Ethereum blockchain. | ||
|
||
## Specification |
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.
Discussing gas price based on benchmarks from the implementation and using the same approach as we did for EIP-1108...
Let's assume ecrecover
is perfectly priced. It costs 3000
gas and takes 180.3
microseconds on my Mac to execute. It's about 16.66
gas per microsecond of ecrecover
work.
With this in mind, F
took 402
nanoseconds on average, it is equal to 0.402
microseconds so the invocation (assuming the same input parameters) should cost 0.402 * 16.66
= 6.7
gas.
Those benchmarks were done with 12 rounds, so it's 0.56
per round.
In the original EIP there was mentioned a price of 37
gas per round.
We have it either heavily optimized or I am too tired to see where is the mistake in my calculations...
Replace the existing ABI encoding interface to the BLAKE2b `F` precompile with a loosely pack struct that's `staticcall`-friendly. H/t to @pdyraga for putting together the interface!
2c59c17
to
764ff73
Compare
|
||
The BLAKE2b algorithm is highly optimized for 64-bit CPUs, and is faster than MD5 on modern processors. | ||
|
||
Interoperability with Zcash could enable contracts like trustless atomic swaps between the chains, which could provide a much needed aspect of privacy to the very public Ethereum blockchain. |
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.
Might also mention Sia and Handshake?
Let's not relitigate precompiles, WASM, etc in thie EIP :)
## Specification | ||
<!--The technical specification should describe the syntax and semantics of any new feature. The specification should be detailed enough to allow competing, interoperable implementations for any of the current Ethereum platforms (go-ethereum, parity, cpp-ethereum, ethereumj, ethereumjs, and [others](https://github.com/ethereum/wiki/wiki/Clients)).--> | ||
|
||
We propose adding a precompiled contract at address `0x09` wrapping the [BLAkE2b `F` compression function](https://tools.ietf.org/html/rfc7693#section-3.2). Rather than the ABI-encoded call structure proposed in [#152](https://github.com/ethereum/EIPs/issues/152), this design better matches other precompiles and works well with a standard `staticcall`. |
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.
example of other
If a conflicting EIP is moving forward the EIP editor can assign a new address
@prestwich thanks fore the comments- will address in a more public EIP |
Closing in favor of an upstream PR ethereum#2129 |
Adapt ethereum#152 into the proper format.
Confirming a couple details before I open this against upstream. cc @pdyraga