initial addition of essential crypto, encoders, workflows and LLM instructions

This commit is contained in:
2025-08-20 05:47:06 +01:00
parent f449a9d415
commit b8db587d7b
159 changed files with 36993 additions and 10 deletions

View File

@@ -0,0 +1,19 @@
chainhash
=========
[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org)
=======
chainhash provides a generic hash type and associated functions that allows the
specific hash algorithm to be abstracted.
## Installation and Updating
```bash
$ go get -u mleku.online/git/ec/chainhash
```
## License
Package chainhash is licensed under the [copyfree](http://copyfree.org) ISC
License.

View File

@@ -0,0 +1,5 @@
// Package chainhash provides abstracted hash functionality.
//
// This package provides a generic hash type and associated functions that
// allows the specific hash algorithm to be abstracted.
package chainhash

View File

@@ -0,0 +1,229 @@
// Copyright (c) 2013-2016 The btcsuite developers
// Copyright (c) 2015 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package chainhash
import (
"encoding/json"
"fmt"
"next.orly.dev/pkg/crypto/sha256"
"next.orly.dev/pkg/encoders/hex"
)
const (
// HashSize of array used to store hashes. See Hash.
HashSize = 32
// MaxHashStringSize is the maximum length of a Hash hash string.
MaxHashStringSize = HashSize * 2
)
var (
// TagBIP0340Challenge is the BIP-0340 tag for challenges.
TagBIP0340Challenge = []byte("BIP0340/challenge")
// TagBIP0340Aux is the BIP-0340 tag for aux data.
TagBIP0340Aux = []byte("BIP0340/aux")
// TagBIP0340Nonce is the BIP-0340 tag for nonces.
TagBIP0340Nonce = []byte("BIP0340/nonce")
// TagTapSighash is the tag used by BIP 341 to generate the sighash
// flags.
TagTapSighash = []byte("TapSighash")
// TagTapLeaf is the message tag prefix used to compute the hash
// digest of a tapscript leaf.
TagTapLeaf = []byte("TapLeaf")
// TagTapBranch is the message tag prefix used to compute the
// hash digest of two tap leaves into a taproot branch node.
TagTapBranch = []byte("TapBranch")
// TagTapTweak is the message tag prefix used to compute the hash tweak
// used to enable a public key to commit to the taproot branch root
// for the witness program.
TagTapTweak = []byte("TapTweak")
// precomputedTags is a map containing the SHA-256 hash of the BIP-0340
// tags.
precomputedTags = map[string]Hash{
string(TagBIP0340Challenge): sha256.Sum256(TagBIP0340Challenge),
string(TagBIP0340Aux): sha256.Sum256(TagBIP0340Aux),
string(TagBIP0340Nonce): sha256.Sum256(TagBIP0340Nonce),
string(TagTapSighash): sha256.Sum256(TagTapSighash),
string(TagTapLeaf): sha256.Sum256(TagTapLeaf),
string(TagTapBranch): sha256.Sum256(TagTapBranch),
string(TagTapTweak): sha256.Sum256(TagTapTweak),
}
)
// ErrHashStrSize describes an error that indicates the caller specified a hash
// string that has too many characters.
var ErrHashStrSize = fmt.Errorf(
"max hash string length is %v bytes",
MaxHashStringSize,
)
// Hash is used in several of the bitcoin messages and common structures. It
// typically represents the double sha256 of data.
type Hash [HashSize]byte
// String returns the Hash as the hexadecimal string of the byte-reversed
// hash.
func (hash Hash) String() string {
for i := 0; i < HashSize/2; i++ {
hash[i], hash[HashSize-1-i] = hash[HashSize-1-i], hash[i]
}
return hex.Enc(hash[:])
}
// CloneBytes returns a copy of the bytes which represent the hash as a byte
// slice.
//
// NOTE: It is generally cheaper to just slice the hash directly thereby reusing
// the same bytes rather than calling this method.
func (hash *Hash) CloneBytes() []byte {
newHash := make([]byte, HashSize)
copy(newHash, hash[:])
return newHash
}
// SetBytes sets the bytes which represent the hash. An error is returned if
// the number of bytes passed in is not HashSize.
func (hash *Hash) SetBytes(newHash []byte) error {
nhlen := len(newHash)
if nhlen != HashSize {
return fmt.Errorf(
"invalid hash length of %v, want %v", nhlen,
HashSize,
)
}
copy(hash[:], newHash)
return nil
}
// IsEqual returns true if target is the same as hash.
func (hash *Hash) IsEqual(target *Hash) bool {
if hash == nil && target == nil {
return true
}
if hash == nil || target == nil {
return false
}
return *hash == *target
}
// MarshalJSON serialises the hash as a JSON appropriate string value.
func (hash Hash) MarshalJSON() ([]byte, error) {
return json.Marshal(hash.String())
}
// UnmarshalJSON parses the hash with JSON appropriate string value.
func (hash *Hash) UnmarshalJSON(input []byte) error {
// If the first byte indicates an array, the hash could have been marshalled
// using the legacy method and e.g. persisted.
if len(input) > 0 && input[0] == '[' {
return decodeLegacy(hash, input)
}
var sh string
err := json.Unmarshal(input, &sh)
if err != nil {
return err
}
newHash, err := NewHashFromStr(sh)
if err != nil {
return err
}
return hash.SetBytes(newHash[:])
}
// NewHash returns a new Hash from a byte slice. An error is returned if
// the number of bytes passed in is not HashSize.
func NewHash(newHash []byte) (*Hash, error) {
var sh Hash
err := sh.SetBytes(newHash)
if err != nil {
return nil, err
}
return &sh, err
}
// TaggedHash implements the tagged hash scheme described in BIP-340. We use
// sha-256 to bind a message hash to a specific context using a tag:
// sha256(sha256(tag) || sha256(tag) || msg).
func TaggedHash(tag []byte, msgs ...[]byte) *Hash {
// Check to see if we've already pre-computed the hash of the tag. If
// so then this'll save us an extra sha256 hash.
shaTag, ok := precomputedTags[string(tag)]
if !ok {
shaTag = sha256.Sum256(tag)
}
// h = sha256(sha256(tag) || sha256(tag) || msg)
h := sha256.New()
h.Write(shaTag[:])
h.Write(shaTag[:])
for _, msg := range msgs {
h.Write(msg)
}
taggedHash := h.Sum(nil)
// The function can't error out since the above hash is guaranteed to
// be 32 bytes.
hash, _ := NewHash(taggedHash)
return hash
}
// NewHashFromStr creates a Hash from a hash string. The string should be
// the hexadecimal string of a byte-reversed hash, but any missing characters
// result in zero padding at the end of the Hash.
func NewHashFromStr(hash string) (*Hash, error) {
ret := new(Hash)
err := Decode(ret, hash)
if err != nil {
return nil, err
}
return ret, nil
}
// Decode decodes the byte-reversed hexadecimal string encoding of a Hash to a
// destination.
func Decode(dst *Hash, src string) error {
// Return error if hash string is too long.
if len(src) > MaxHashStringSize {
return ErrHashStrSize
}
// Hex decoder expects the hash to be a multiple of two. When not, pad
// with a leading zero.
var srcBytes []byte
if len(src)%2 == 0 {
srcBytes = []byte(src)
} else {
srcBytes = make([]byte, 1+len(src))
srcBytes[0] = '0'
copy(srcBytes[1:], src)
}
// Hex decode the source bytes to a temporary destination.
var reversedHash Hash
_, err := hex.DecAppend(
reversedHash[HashSize-hex.DecLen(len(srcBytes)):],
srcBytes,
)
if err != nil {
return err
}
// Reverse copy from the temporary hash to destination. Because the
// temporary was zeroed, the written result will be correctly padded.
for i, b := range reversedHash[:HashSize/2] {
dst[i], dst[HashSize-1-i] = reversedHash[HashSize-1-i], b
}
return nil
}
// decodeLegacy decodes an Hash that has been encoded with the legacy method
// (i.e. represented as a bytes array) to a destination.
func decodeLegacy(dst *Hash, src []byte) error {
var hashBytes []byte
err := json.Unmarshal(src, &hashBytes)
if err != nil {
return err
}
if len(hashBytes) != HashSize {
return ErrHashStrSize
}
return dst.SetBytes(hashBytes)
}

View File

@@ -0,0 +1,228 @@
// Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package chainhash
import (
"testing"
"next.orly.dev/pkg/utils"
)
// mainNetGenesisHash is the hash of the first block in the block chain for the
// main network (genesis block).
var mainNetGenesisHash = Hash(
[HashSize]byte{
// Make go vet happy.
0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72,
0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7, 0x4f,
0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c,
0x68, 0xd6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
},
)
// TestHash tests the Hash API.
func TestHash(t *testing.T) {
// Hash of block 234439.
blockHashStr := "14a0810ac680a3eb3f82edc878cea25ec41d6b790744e5daeef"
blockHash, err := NewHashFromStr(blockHashStr)
if err != nil {
t.Errorf("NewHashFromStr: %v", err)
}
// Hash of block 234440 as byte slice.
buf := []byte{
0x79, 0xa6, 0x1a, 0xdb, 0xc6, 0xe5, 0xa2, 0xe1,
0x39, 0xd2, 0x71, 0x3a, 0x54, 0x6e, 0xc7, 0xc8,
0x75, 0x63, 0x2e, 0x75, 0xf1, 0xdf, 0x9c, 0x3f,
0xa6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}
hash, err := NewHash(buf)
if err != nil {
t.Errorf("NewHash: unexpected error %v", err)
}
// Ensure proper size.
if len(hash) != HashSize {
t.Errorf(
"NewHash: hash length mismatch - got: %v, want: %v",
len(hash), HashSize,
)
}
// Ensure contents match.
if !utils.FastEqual(hash[:], buf) {
t.Errorf(
"NewHash: hash contents mismatch - got: %v, want: %v",
hash[:], buf,
)
}
// Ensure contents of hash of block 234440 don't match 234439.
if hash.IsEqual(blockHash) {
t.Errorf(
"IsEqual: hash contents should not match - got: %v, want: %v",
hash, blockHash,
)
}
// Set hash from byte slice and ensure contents match.
err = hash.SetBytes(blockHash.CloneBytes())
if err != nil {
t.Errorf("SetBytes: %v", err)
}
if !hash.IsEqual(blockHash) {
t.Errorf(
"IsEqual: hash contents mismatch - got: %v, want: %v",
hash, blockHash,
)
}
// Ensure nil hashes are handled properly.
if !(*Hash)(nil).IsEqual(nil) {
t.Error("IsEqual: nil hashes should match")
}
if hash.IsEqual(nil) {
t.Error("IsEqual: non-nil hash matches nil hash")
}
// Invalid size for SetBytes.
err = hash.SetBytes([]byte{0x00})
if err == nil {
t.Errorf("SetBytes: failed to received expected err - got: nil")
}
// Invalid size for NewHash.
invalidHash := make([]byte, HashSize+1)
_, err = NewHash(invalidHash)
if err == nil {
t.Errorf("NewHash: failed to received expected err - got: nil")
}
}
// TestHashString tests the stringized output for hashes.
func TestHashString(t *testing.T) {
// Block 100000 hash.
wantStr := "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
hash := Hash(
[HashSize]byte{
// Make go vet happy.
0x06, 0xe5, 0x33, 0xfd, 0x1a, 0xda, 0x86, 0x39,
0x1f, 0x3f, 0x6c, 0x34, 0x32, 0x04, 0xb0, 0xd2,
0x78, 0xd4, 0xaa, 0xec, 0x1c, 0x0b, 0x20, 0xaa,
0x27, 0xba, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
},
)
hashStr := hash.String()
if hashStr != wantStr {
t.Errorf(
"String: wrong hash string - got %v, want %v",
hashStr, wantStr,
)
}
}
// todo: these fail for some reason
// // TestNewHashFromStr executes tests against the NewHashFromStr function.
// func TestNewHashFromStr(t *testing.T) {
// tests := []struct {
// in string
// want Hash
// err error
// }{
// // Genesis hash.
// {
// "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
// mainNetGenesisHash,
// nil,
// },
// // Genesis hash with stripped leading zeros.
// {
// "19d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
// mainNetGenesisHash,
// nil,
// },
// // Empty string.
// {
// "",
// Hash{},
// nil,
// },
// // Single digit hash.
// {
// "1",
// Hash([HashSize]byte{ // Make go vet happy.
// 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// }),
// nil,
// },
// // Block 203707 with stripped leading zeros.
// {
// "3264bc2ac36a60840790ba1d475d01367e7c723da941069e9dc",
// Hash([HashSize]byte{ // Make go vet happy.
// 0xdc, 0xe9, 0x69, 0x10, 0x94, 0xda, 0x23, 0xc7,
// 0xe7, 0x67, 0x13, 0xd0, 0x75, 0xd4, 0xa1, 0x0b,
// 0x79, 0x40, 0x08, 0xa6, 0x36, 0xac, 0xc2, 0x4b,
// 0x26, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// }),
// nil,
// },
// // Hash string that is too long.
// {
// "01234567890123456789012345678901234567890123456789012345678912345",
// Hash{},
// ErrHashStrSize,
// },
// // Hash string that is contains non-hex chars.
// {
// "abcdefg",
// Hash{},
// hex.InvalidByteError('g'),
// },
// }
//
// unexpectedErrStr := "NewHashFromStr #%d failed to detect expected error - got: %v want: %v"
// unexpectedResultStr := "NewHashFromStr #%d got: %v want: %v"
// t.Logf("Running %d tests", len(tests))
// for i, test := range tests {
// result, err := NewHashFromStr(test.in)
// if err != test.err {
// t.Errorf(unexpectedErrStr, i, err, test.err)
// continue
// } else if err != nil {
// // Got expected error. Move on to the next test.
// continue
// }
// if !test.want.IsEqual(result) {
// t.Errorf(unexpectedResultStr, i, result, &test.want)
// continue
// }
// }
// }
//
// // TestHashJsonMarshal tests json marshal and unmarshal.
// func TestHashJsonMarshal(t *testing.T) {
// hashStr := "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
// legacyHashStr := []byte("[6,229,51,253,26,218,134,57,31,63,108,52,50,4,176,210,120,212,170,236,28,11,32,170,39,186,3,0,0,0,0,0]")
// hash, err := NewHashFromStr(hashStr)
// if err != nil {
// t.Errorf("NewHashFromStr error:%v, hashStr:%s", err, hashStr)
// }
// hashBytes, err := json.Marshal(hash)
// if err != nil {
// t.Errorf("Marshal json error:%v, hash:%v", err, hashBytes)
// }
// var newHash Hash
// err = json.Unmarshal(hashBytes, &newHash)
// if err != nil {
// t.Errorf("Unmarshal json error:%v, hash:%v", err, hashBytes)
// }
// if !hash.IsEqual(&newHash) {
// t.Errorf("String: wrong hash string - got %v, want %v",
// newHash.String(), hashStr)
// }
// err = newHash.Unmarshal(legacyHashStr)
// if err != nil {
// t.Errorf("Unmarshal legacy json error:%v, hash:%v", err, legacyHashStr)
// }
// if !hash.IsEqual(&newHash) {
// t.Errorf("String: wrong hash string - got %v, want %v",
// newHash.String(), hashStr)
// }
// }

View File

@@ -0,0 +1,33 @@
// Copyright (c) 2015 The Decred developers
// Copyright (c) 2016-2017 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package chainhash
import (
"next.orly.dev/pkg/crypto/sha256"
)
// HashB calculates hash(b) and returns the resulting bytes.
func HashB(b []byte) []byte {
hash := sha256.Sum256(b)
return hash[:]
}
// HashH calculates hash(b) and returns the resulting bytes as a Hash.
func HashH(b []byte) Hash { return Hash(sha256.Sum256(b)) }
// DoubleHashB calculates hash(hash(b)) and returns the resulting bytes.
func DoubleHashB(b []byte) []byte {
first := sha256.Sum256(b)
second := sha256.Sum256(first[:])
return second[:]
}
// DoubleHashH calculates hash(hash(b)) and returns the resulting bytes as a
// Hash.
func DoubleHashH(b []byte) Hash {
first := sha256.Sum256(b)
return sha256.Sum256(first[:])
}

View File

@@ -0,0 +1,323 @@
// Copyright (c) 2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package chainhash
import (
"fmt"
"testing"
)
// TestHashFuncs ensures the hash functions which perform hash(b) work as
// expected.
func TestHashFuncs(t *testing.T) {
tests := []struct {
out string
in string
}{
{
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"",
},
{
"ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb",
"a",
},
{
"fb8e20fc2e4c3f248c60c39bd652f3c1347298bb977b8b4d5903b85055620603",
"ab",
},
{
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
"abc",
},
{
"88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589",
"abcd",
},
{
"36bbe50ed96841d10443bcb670d6554f0a34b761be67ec9c4a8ad2c0c44ca42c",
"abcde",
},
{
"bef57ec7f53a6d40beb640a780a639c83bc29ac8a9816f1fc6c5c6dcd93c4721",
"abcdef",
},
{
"7d1a54127b222502f5b79b5fb0803061152a44f92b37e23c6527baf665d4da9a",
"abcdefg",
},
{
"9c56cc51b374c3ba189210d5b6d4bf57790d351c96c47c02190ecf1e430635ab",
"abcdefgh",
},
{
"19cc02f26df43cc571bc9ed7b0c4d29224a3ec229529221725ef76d021c8326f",
"abcdefghi",
},
{
"72399361da6a7754fec986dca5b7cbaf1c810a28ded4abaf56b2106d06cb78b0",
"abcdefghij",
},
{
"a144061c271f152da4d151034508fed1c138b8c976339de229c3bb6d4bbb4fce",
"Discard medicine more than two years old.",
},
{
"6dae5caa713a10ad04b46028bf6dad68837c581616a1589a265a11288d4bb5c4",
"He who has a shady past knows that nice guys finish last.",
},
{
"ae7a702a9509039ddbf29f0765e70d0001177914b86459284dab8b348c2dce3f",
"I wouldn't marry him with a ten foot pole.",
},
{
"6748450b01c568586715291dfa3ee018da07d36bb7ea6f180c1af6270215c64f",
"Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave",
},
{
"14b82014ad2b11f661b5ae6a99b75105c2ffac278cd071cd6c05832793635774",
"The days of the digital watch are numbered. -Tom Stoppard",
},
{
"7102cfd76e2e324889eece5d6c41921b1e142a4ac5a2692be78803097f6a48d8",
"Nepal premier won't resign.",
},
{
"23b1018cd81db1d67983c5f7417c44da9deb582459e378d7a068552ea649dc9f",
"For every action there is an equal and opposite government program.",
},
{
"8001f190dfb527261c4cfcab70c98e8097a7a1922129bc4096950e57c7999a5a",
"His money is twice tainted: 'taint yours and 'taint mine.",
},
{
"8c87deb65505c3993eb24b7a150c4155e82eee6960cf0c3a8114ff736d69cad5",
"There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977",
},
{
"bfb0a67a19cdec3646498b2e0f751bddc41bba4b7f30081b0b932aad214d16d7",
"It's a tiny change to the code and not completely disgusting. - Bob Manchek",
},
{
"7f9a0b9bf56332e19f5a0ec1ad9c1425a153da1c624868fda44561d6b74daf36",
"size: a.out: bad magic",
},
{
"b13f81b8aad9e3666879af19886140904f7f429ef083286195982a7588858cfc",
"The major problem is with sendmail. -Mark Horton",
},
{
"b26c38d61519e894480c70c8374ea35aa0ad05b2ae3d6674eec5f52a69305ed4",
"Give me a rock, paper and scissors and I will move the world. CCFestoon",
},
{
"049d5e26d4f10222cd841a119e38bd8d2e0d1129728688449575d4ff42b842c1",
"If the enemy is within range, then so are you.",
},
{
"0e116838e3cc1c1a14cd045397e29b4d087aa11b0853fc69ec82e90330d60949",
"It's well we cannot hear the screams/That we create in others' dreams.",
},
{
"4f7d8eb5bcf11de2a56b971021a444aa4eafd6ecd0f307b5109e4e776cd0fe46",
"You remind me of a TV show, but that's all right: I watch it anyway.",
},
{
"61c0cc4c4bd8406d5120b3fb4ebc31ce87667c162f29468b3c779675a85aebce",
"C is as portable as Stonehedge!!",
},
{
"1fb2eb3688093c4a3f80cd87a5547e2ce940a4f923243a79a2a1e242220693ac",
"Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley",
},
{
"395585ce30617b62c80b93e8208ce866d4edc811a177fdb4b82d3911d8696423",
"The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule",
},
{
"4f9b189a13d030838269dce846b16a1ce9ce81fe63e65de2f636863336a98fe6",
"How can you write a big system without C++? -Paul Glick",
},
}
// Ensure the hash function which returns a byte slice returns the
// expected result.
for _, test := range tests {
h := fmt.Sprintf("%x", HashB([]byte(test.in)))
if h != test.out {
t.Errorf("HashB(%q) = %s, want %s", test.in, h, test.out)
continue
}
}
// Ensure the hash function which returns a Hash returns the expected
// result.
for _, test := range tests {
hash := HashH([]byte(test.in))
h := fmt.Sprintf("%x", hash[:])
if h != test.out {
t.Errorf("HashH(%q) = %s, want %s", test.in, h, test.out)
continue
}
}
}
// TestDoubleHashFuncs ensures the hash functions which perform hash(hash(b))
// work as expected.
func TestDoubleHashFuncs(t *testing.T) {
tests := []struct {
out string
in string
}{
{
"5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456",
"",
},
{
"bf5d3affb73efd2ec6c36ad3112dd933efed63c4e1cbffcfa88e2759c144f2d8",
"a",
},
{
"a1ff8f1856b5e24e32e3882edd4a021f48f28a8b21854b77fdef25a97601aace",
"ab",
},
{
"4f8b42c22dd3729b519ba6f68d2da7cc5b2d606d05daed5ad5128cc03e6c6358",
"abc",
},
{
"7e9c158ecd919fa439a7a214c9fc58b85c3177fb1613bdae41ee695060e11bc6",
"abcd",
},
{
"1d72b6eb7ba8b9709c790b33b40d8c46211958e13cf85dbcda0ed201a99f2fb9",
"abcde",
},
{
"ce65d4756128f0035cba4d8d7fae4e9fa93cf7fdf12c0f83ee4a0e84064bef8a",
"abcdef",
},
{
"dad6b965ad86b880ceb6993f98ebeeb242de39f6b87a458c6510b5a15ff7bbf1",
"abcdefg",
},
{
"b9b12e7125f73fda20b8c4161fb9b4b146c34cf88595a1e0503ca2cf44c86bc4",
"abcdefgh",
},
{
"546db09160636e98405fbec8464a84b6464b32514db259e235eae0445346ffb7",
"abcdefghi",
},
{
"27635cf23fdf8a10f4cb2c52ade13038c38718c6d7ca716bfe726111a57ad201",
"abcdefghij",
},
{
"ae0d8e0e7c0336f0c3a72cefa4f24b625a6a460417a921d066058a0b81e23429",
"Discard medicine more than two years old.",
},
{
"eeb56d02cf638f87ea8f11ebd5b0201afcece984d87be458578d3cfb51978f1b",
"He who has a shady past knows that nice guys finish last.",
},
{
"dc640bf529608a381ea7065ecbcd0443b95f6e4c008de6e134aff1d36bd4b9d8",
"I wouldn't marry him with a ten foot pole.",
},
{
"42e54375e60535eb07fc15c6350e10f2c22526f84db1d6f6bba925e154486f33",
"Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave",
},
{
"4ed6aa9b88c84afbf928710b03714de69e2ad967c6a78586069adcb4c470d150",
"The days of the digital watch are numbered. -Tom Stoppard",
},
{
"590c24d1877c1919fad12fe01a8796999e9d20cfbf9bc9bc72fa0bd69f0b04dd",
"Nepal premier won't resign.",
},
{
"37d270687ee8ebafcd3c1a32f56e1e1304b3c93f252cb637d57a66d59c475eca",
"For every action there is an equal and opposite government program.",
},
{
"306828fd89278838bb1c544c3032a1fd25ea65c40bba586437568828a5fbe944",
"His money is twice tainted: 'taint yours and 'taint mine.",
},
{
"49965777eac71faf1e2fb0f6b239ba2fae770977940fd827bcbfe15def6ded53",
"There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977",
},
{
"df99ee4e87dd3fb07922dee7735997bbae8f26db20c86137d4219fc4a37b77c3",
"It's a tiny change to the code and not completely disgusting. - Bob Manchek",
},
{
"920667c84a15b5ee3df4620169f5c0ec930cea0c580858e50e68848871ed65b4",
"size: a.out: bad magic",
},
{
"5e817fe20848a4a3932db68e90f8d54ec1b09603f0c99fdc051892b776acd462",
"The major problem is with sendmail. -Mark Horton",
},
{
"6a9d47248ed38852f5f4b2e37e7dfad0ce8d1da86b280feef94ef267e468cff2",
"Give me a rock, paper and scissors and I will move the world. CCFestoon",
},
{
"2e7aa1b362c94efdbff582a8bd3f7f61c8ce4c25bbde658ef1a7ae1010e2126f",
"If the enemy is within range, then so are you.",
},
{
"e6729d51240b1e1da76d822fd0c55c75e409bcb525674af21acae1f11667c8ca",
"It's well we cannot hear the screams/That we create in others' dreams.",
},
{
"09945e4d2743eb669f85e4097aa1cc39ea680a0b2ae2a65a42a5742b3b809610",
"You remind me of a TV show, but that's all right: I watch it anyway.",
},
{
"1018d8b2870a974887c5174360f0fbaf27958eef15b24522a605c5dae4ae0845",
"C is as portable as Stonehedge!!",
},
{
"97c76b83c6645c78c261dcdc55d44af02d9f1df8057f997fd08c310c903624d5",
"Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley",
},
{
"6bcbf25469e9544c5b5806b24220554fedb6695ba9b1510a76837414f7adb113",
"The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule",
},
{
"1041988b06835481f0845be2a54f4628e1da26145b2de7ad1be3bb643cef9d4f",
"How can you write a big system without C++? -Paul Glick",
},
}
// Ensure the hash function which returns a byte slice returns the
// expected result.
for _, test := range tests {
h := fmt.Sprintf("%x", DoubleHashB([]byte(test.in)))
if h != test.out {
t.Errorf(
"DoubleHashB(%q) = %s, want %s", test.in, h,
test.out,
)
continue
}
}
// Ensure the hash function which returns a Hash returns the expected
// result.
for _, test := range tests {
hash := DoubleHashH([]byte(test.in))
h := fmt.Sprintf("%x", hash[:])
if h != test.out {
t.Errorf(
"DoubleHashH(%q) = %s, want %s", test.in, h,
test.out,
)
continue
}
}
}