Open heathdutton opened 2 years ago
Good work! This is so useful. I wanted to suggest a simpler alternative that in the vast majority of situations saves more gas for a typical user.
The usecase of the 4 leading zero-bytes is to be able to cast an address to a uint128 rather than a uint160. Specifically, if you have 2 of these addresses with 4 leading zero-bytes, you can pack both of them into a single uint256 storage slot. You can take advantage of this in your own custom contracts to parse each address from the front/back of the storage slot and prepend the 8 zeroes afterwards. If you plan on using both addresses frequently in your code, this saves a cool ~2000 gas during runtime in solidity. However, this usecase is extremely niche, and never used in the wild such that a typical user could take advantage.
A more generalized --gas option would be for finding the highest total of zero-bytes within the address. This takes advantage of the much more applicable Gtxdatazero, which saves 12 gas compared to every non-zero byte in the address.
Gtxdatazero | 4 Paid for every zero byte of data or code for a transaction.
Gtxdatanonzero | 16 Paid for every non-zero byte of data or code for a transaction
This allows you to find addresses with more zero-bytes than the more restricting condition that 4 zero-bytes must lead.
__kernel void profanity_score_leading(__global mp_number * const pInverse, __global result * const pResult, __constant const uchar * const data1, __constant const uchar * const data2, const uchar scoreMax) {
const size_t id = get_global_id(0);
__global const uchar * const hash = pInverse[id].d;
int score = 0;
for (int i = 0; i < 20; ++i) {
score += (hash[i] == 0);
}
profanity_result_update(id, hash, pResult, score, scoreMax);
}
You are correct of course! A wallet user only cares about the number of zero bytes probably. I was making contracts, so this worked better for my needs at the time.
Can you elaborate a bit more on the making contracts? Because doing a contract with less bytes also utilizes less gas too? I'm only asking because If theres something more useful that i'm not seeing here I would love the insight or at least a point in the direction that your utilizing it for.
To @plotchy's point, a more generic gas optimization is better for most cases, so I simplified it.
Leading/trailing/contiguous zero-bytes is generally better for a contract because you can pack it in less bytecode. Think of clone/proxy contracts in particular.
...but... the results took much longer when trying to get to something like that.
I found the generic version was faster and suffices just fine for most cases. Even on my M1 Mac it performs well:
./profanity.x64 --gas --contract -I 20000
Got me:
Time: 36s Score: 4 Private: ...
Time: 36s Score: 5 Private: ...
Time: 635s Score: 6 Private: ...
Time: 42077s Score: 7 Private: ...
Time: 121087s Score: 8 Private: ...
(granted, this was a bit lucky... still really fantastic!)
https://eip2535diamonds.substack.com/p/introduction-to-the-diamond-standard and utilizing above references seems fun.
Based on https://github.com/johguse/profanity/issues/57