Transaction
7C09FB5788A05D…DED17B30C6CC
Block 166,003 · index 0 · indexed
Summary
- Hash
- 7C09FB5788A05D4995FBFF870D5A5B1188D7277210530EC140ADDED17B30C6CC
- Block
- 166,003
- Size
- 9167 bytes
- Gas used
- 11,225,892 / 15,000,000
- Fee
- 15000 ugnot
- Status
- success
Messages
Arguments · 13
- #1murmur3
- #2README.md
- #3# MurmurHash3 Package Package implements Austin Appleby's MurmurHash3 algorithm. MurmurHash3 is a fast, non-cryptographic hash function well suited for hash tables, bloom filters, data partitioning, and deduplication where speed and good distribution matter more than cryptographic security. Repository can be found at [jeronimoalbi/gnome](https://github.com/jeronimoalbi/gnome), as part of `jeronimoalbi`'s Gno smart contracts monorepo. ## Usage [embedmd]:# (filetests/readme_filetest.gno go) ```go package main import "gno.land/p/g17khqpukees4237dtn3astzapmp462vjhsz6st4/murmur3" func main() { data := []byte("Hello, world!") seed := uint32(42) // Hash32 without seed h32 := murmur3.New32() h32.Write(data) sum32 := uint64(h32.Sum32()) println(murmur3.EncodeToString(sum32)) // Hash32 with seed h32 = murmur3.NewWithSeed32(seed) h32.Write(data) sum32 = uint64(h32.Sum32()) println(murmur3.EncodeToString(sum32)) // Hash32 without seed using a helper function sum32 = uint64(murmur3.Sum32(data)) println(murmur3.EncodeToString(sum32)) // Hash32 with seed using a helper function sum32 = uint64(murmur3.Sum32WithSeed(data, seed)) println(murmur3.EncodeToString(sum32)) // Hash64 without seed h64 := murmur3.New64() h64.Write(data) sum64 := h64.Sum64() println(murmur3.EncodeToString(sum64)) // Hash64 with seed h64 = murmur3.NewWithSeed64(0, seed) h64.Write(data) sum64 = h64.Sum64() println(murmur3.EncodeToString(sum64)) // Hash64 without seed using a helper function sum64 = murmur3.Sum64(data) println(murmur3.EncodeToString(sum64)) // Hash64 with seed using a helper function sum64 = murmur3.Sum64WithSeed(data, 0, seed) println(murmur3.EncodeToString(sum64)) } // Output: // c0363e43 // 2c8c8533 // c0363e43 // 2c8c8533 // c0363e43aa5dc85b // c0363e432c8c8533 // c0363e43aa5dc85b // c0363e432c8c8533 ```
- #4gnomod.toml
- #5module = "gno.land/p/g17khqpukees4237dtn3astzapmp462vjhsz6st4/murmur3" gno = "0.9"
- #6murmur32.gno
- #7// Package murmur3 implements the MurmurHash3 hash algorithm. // // Package implements Austin Appleby's MurmurHash3 algorithm. // // MurmurHash3 is a fast, non-cryptographic hash function well suited for hash // tables, bloom filters, data partitioning, and deduplication where speed and // good distribution matter more than cryptographic security. // // References: // // https://en.wikipedia.org/wiki/MurmurHash#Algorithm // https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp package murmur3 import "strconv" // EncodeToString returns the hexadecimal encoding of a hash value. func EncodeToString(sum uint64) string { return strconv.FormatUint(sum, 16) }
- #8murmur3_32.gno
- #9package murmur3 import ( "hash" "math/bits" ) const ( c1 = 0xcc9e2d51 c2 = 0x1b873593 r1 = 15 r2 = 13 blockSize32 = 4 hashSize32 = 4 ) type digest32 struct { seed uint32 h1 uint32 tail [4]byte tailBytesCount int writtenLen int } // New32 returns a new hash.Hash32 computing the MurmurHash3 hash. // It can generate 2 to the power of 32 unique 32-bit values ranging // from 0 to 4_294_967_296. // Hash is not collision safe, so it's recommended to handle potential // collisions when dealing with more than 65_536 values which is when // probability raises. func New32() hash.Hash32 { return &digest32{} } // NewWithSeed32 returns a new hash.Hash32 computing the MurmurHash3 // hash with the given seed. // It can generate 2 to the power of 32 unique 32-bit values ranging // from 0 to 4_294_967_296. // Hash is not collision safe, so it's recommended to handle potential // collisions when dealing with more than 65_536 values which is when // provability raises. func NewWithSeed32(seed uint32) hash.Hash32 { return &digest32{seed: seed, h1: seed} } // Sum32 returns the MurmurHash3 hash of the specified data. func Sum32(data []byte) uint32 { return Sum32WithSeed(data, 0) } // Sum32WithSeed returns the MurmurHash3 hash of the specified data // using the given seed. func Sum32WithSeed(data []byte, seed uint32) uint32 { h := NewWithSeed32(seed) h.Write(data) return h.Sum32() } func (digest32) BlockSize() int { return blockSize32 } func (digest32) Size() int { return hashSize32 } func (d *digest32) Reset() { d.h1 = d.seed d.tailBytesCount = 0 d.writtenLen = 0 } func (d *digest32) Write(bz []byte) (int, error) { // Keep track of all written bytes total := len(bz) d.writtenLen += total // If there are leftover bytes in the tail, // try to fill a block with the new data. if d.tailBytesCount > 0 { need := blockSize32 - d.tailBytesCount if len(bz) < need { // Append more data to the block copy(d.tail[d.tailBytesCount:], bz) d.tailBytesCount += len(bz) // Tail block is still not filled return total, nil } // Append remaining block data and process current block copy(d.tail[d.tailBytesCount:], bz[:need]) d.processBlock(d.tail[:]) // Update data to exclude the appended processed data bz = bz[need:] d.tailBytesCount = 0 } // Process full 4-byte blocks for len(bz) >= blockSize32 { d.processBlock(bz[:blockSize32]) bz = bz[blockSize32:] } // Save remaining bytes in the tail. Remaining data can be left // out of the last block when data size is less than 4 bytes. if len(bz) > 0 { d.tailBytesCount = copy(d.tail[:], bz) } return total, nil } func (d digest32) Sum32() uint32 { h1 := d.h1 // Process tail bytes when they exist. Blocks have 4 bytes, so depending // on the size of the data some bytes might not be processed after the last // write if the last block has less than 4 bytes. var k1 uint32 switch d.tailBytesCount { case 3: k1 ^= uint32(d.tail[2]) << 16 fallthrough case 2: k1 ^= uint32(d.tail[1]) << 8 fallthrough case 1: k1 ^= uint32(d.tail[0]) k1 *= c1 k1 = bits.RotateLeft32(k1, r1) k1 *= c2 h1 ^= k1 } // Finalization mix h1 ^= uint32(d.writtenLen) h1 ^= h1 >> 16 h1 *= 0x85ebca6b h1 ^= h1 >> r2 h1 *= 0xc2b2ae35 h1 ^= h1 >> 16 return h1 } func (d digest32) Sum(bz []byte) []byte { // Append hash in little-endian order s := d.Sum32() return append(bz, byte(s), byte(s>>8), byte(s>>16), byte(s>>24)) } // processBlock reads a 4-byte little-endian block // and mixes it into the hash state. func (d *digest32) processBlock(bz []byte) { k1 := uint32(bz[0]) | uint32(bz[1])<<8 | uint32(bz[2])<<16 | uint32(bz[3])<<24 k1 *= c1 k1 = bits.RotateLeft32(k1, r1) k1 *= c2 d.h1 ^= k1 d.h1 = bits.RotateLeft32(d.h1, r2) d.h1 = d.h1*5 + 0xe6546b64 // MurmurHash3 "m" = 5, "n" = 0xe6546b64 }
- #10murmur3_64.gno
- #11package murmur3 import "hash" const hashSize64 = 8 type digest64 struct { d1 digest32 d2 digest32 } // New64 returns a new hash.Hash64 computing a 64-bit MurmurHash3 // hash using two 32-bit hashes with different seeds. // It can generate 2 to the power of 64 unique 64-bit values. // Hash is not collision safe, so it's recommended to handle potential // collisions when dealing with more than 4_294_967_296 values which is // when probability raises. func New64() hash.Hash64 { return &digest64{ d1: digest32{}, d2: digest32{seed: 1, h1: 1}, } } // NewWithSeed64 returns a new hash.Hash64 computing a 64-bit // MurmurHash3 hash. The first 32-bit hash uses seed1 and the // second uses seed2. The two seeds should ideally be different. // It can generate 2 to the power of 64 unique 64-bit values. // Hash is not collision safe, so it's recommended to handle potential // collisions when dealing with more than 4_294_967_296 values which is // when provability raises. func NewWithSeed64(seed1, seed2 uint32) hash.Hash64 { return &digest64{ d1: digest32{seed: seed1, h1: seed1}, d2: digest32{seed: seed2, h1: seed2}, } } // Sum64 returns the 64-bit MurmurHash3 hash of the specified data. func Sum64(data []byte) uint64 { return Sum64WithSeed(data, 0, 1) } // Sum64WithSeed returns the 64-bit MurmurHash3 hash of the specified // data using the given seeds. func Sum64WithSeed(data []byte, seed1, seed2 uint32) uint64 { h := NewWithSeed64(seed1, seed2) h.Write(data) return h.Sum64() } func (digest64) BlockSize() int { // Use a 32-bit hash block size because writes are // done to two hash32 hashes using the same data. return blockSize32 } func (digest64) Size() int { return hashSize64 } func (d *digest64) Reset() { d.d1.Reset() d.d2.Reset() } func (d *digest64) Write(bz []byte) (int, error) { d.d1.Write(bz) return d.d2.Write(bz) } func (d digest64) Sum64() uint64 { return uint64(d.d1.Sum32())<<32 | uint64(d.d2.Sum32()) } func (d digest64) Sum(bz []byte) []byte { s := d.Sum64() return append(bz, byte(s), byte(s>>8), byte(s>>16), byte(s>>24), byte(s>>32), byte(s>>40), byte(s>>48), byte(s>>56), ) }
- #12/gno.MemPackageType
- #13 MPUserAll
Result log
msg:0,success:true,log:,events:[]