-
Notifications
You must be signed in to change notification settings - Fork 5k
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
Bring web3 sha3 API in line with Solidity sha3 #445
Comments
Needs something for BigNumber.js, probably. |
related #226 |
If |
That's a valid concern, but honestly at some point you just have to correct blatant errors with a breaking update. |
This change is VERY needed! I just spent hours trying to find out how to do this. The function given is good, but to make it work with negative numbers, I had to change the 'number' handling to this:
|
I took the suggestions from this issue and wrapped them all up into an npm library: Here's the source code in its entirety: import Web3 from 'web3'
import leftPad from 'left-pad'
const web3 = new Web3()
// the size of a character in a hex string in bytes
const HEX_CHAR_SIZE = 4
// the size to hash an integer if not explicity provided
const DEFAULT_SIZE = 256
const isHex = val => val.toString().slice(0, 2) === '0x'
/** Encodes a values in hex and adds padding to the given size if needed. Curried args. */
const encodeWithPadding = size => value => {
return typeof value === 'string' && !isHex(value)
// non-hex string
? web3.toHex(value)
// numbers, big numbers, and hex strings
: leftPad(web3.toHex(value >>> 0).slice(2), size / HEX_CHAR_SIZE, value < 0 ? 'F' : '0')
}
/** Hashes one or more arguments, using a default size for numbers. */
export default (...args) => {
const paddedArgs = args.map(encodeWithPadding(DEFAULT_SIZE)).join('')
return web3.sha3(paddedArgs, { encoding: 'hex' })
}
/** Hashes a single value at the given size. */
export const sha3withsize = (value, size) => {
const paddedArgs = encodeWithPadding(size)(value)
return web3.sha3(paddedArgs, { encoding: 'hex' })
} |
Great! |
This is actually implemented in ethereumjs-abi too: var abi = require('ethereumjs-abi')
var BN = require('bn.js')
abi.soliditySHA3(
[ "address", "address", "uint", "uint" ],
[ new BN("43989fb883ba8111221e89123897538475893837", 16), 0, 10000, 1448075779 ]
).toString('hex') |
@axic Thanks... kind of a bummer to have done duplicate work, but I'm glad to know. I'll make a note to myself to find what docs this should go in so that it is not so secret. None of us on the gitter channel were aware of this. |
@raineorshine It was no secret, it was there since last November :) I think I've linked to it on stackexchange. |
If I ask about sha3 on gitter, StackExchange, google it, write a library
|
Hey, why can't we merge this into |
Can someone explain me the issue better? |
Let's think about the use cases:
I don't know for sure, but I imagine that #2 would be more common when it comes to dapp development. It is at least common enough that myself and several others have been bit by this issue. The problem is that Similar counterintuitive results occur when you try to hash tightly packed arguments, arrays, and BigNumber instances. If this is considered special treatment, I would suggest two functions:
Or vice versa:
Personally I think the latter is the correct decision and the more common sticking point for developers. Look forward to hearing your thoughts! |
Here it is: http://web3js.readthedocs.io/en/1.0/web3-utils.html#soliditysha3 Will be in the 1.0 once its out |
Thanks Fabian! |
@frozeman I noticed the |
hi all, has anybody taken a look at this case? solidity-sha3 is still failing for me with negative big number... can anybody check ? |
@saveriocastellano try the solution with ethereumjs-abi, works like a charm. |
I had to spend a lot of time figuring out how to get sha3 to produce the same hashes in web3 and in my contracts. I think we should consider giving them both the same API. Here is a function that should do it:
The text was updated successfully, but these errors were encountered: