From 273c271771061a9bb14a0ee5798b0c39f473a295 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Wed, 23 Dec 2020 12:42:37 +0200 Subject: [PATCH] Remove hash reversal (#1270) * Remove hash reversing * Move toBig to pow.go * Update some tests --- app/appmessage/p2p_msgtx_test.go | 10 +++++----- domain/consensus/model/externalapi/hash.go | 6 +----- domain/consensus/model/pow/pow.go | 17 +++++++++++++++-- domain/consensus/ruleerrors/rule_error_test.go | 4 ++-- domain/consensus/utils/hashes/strings.go | 17 ++++------------- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/app/appmessage/p2p_msgtx_test.go b/app/appmessage/p2p_msgtx_test.go index c1dba1885..dd124e653 100644 --- a/app/appmessage/p2p_msgtx_test.go +++ b/app/appmessage/p2p_msgtx_test.go @@ -132,8 +132,8 @@ func TestTx(t *testing.T) { // TestTxHash tests the ability to generate the hash of a transaction accurately. func TestTxHashAndID(t *testing.T) { - txHash1Str := "c2ac1e792c5c49260103ad9f86caf749d431958b7c7e5e5129346ceab8b709cf" - txID1Str := "47ce12a5ee5727cf97c0481eebedad0d80646b743305b0921a2403f1836f8b37" + txHash1Str := "cf09b7b8ea6c3429515e7e7c8b9531d449f7ca869fad030126495c2c791eacc2" + txID1Str := "378b6f83f103241a92b00533746b64800dadedeb1e48c097cf2757eea512ce47" wantTxID1, err := transactionid.FromString(txID1Str) if err != nil { t.Fatalf("NewTxIDFromStr: %v", err) @@ -174,7 +174,7 @@ func TestTxHashAndID(t *testing.T) { tx1Hash := tx1.TxHash() if *tx1Hash != (externalapi.DomainHash)(*wantTxHash1) { t.Errorf("TxHash: wrong hash - got %v, want %v", - spew.Sprint(tx1Hash), spew.Sprint(wantTxID1)) + spew.Sprint(tx1Hash), spew.Sprint(wantTxHash1)) } // Ensure the TxID for coinbase transaction is the same as TxHash. @@ -184,14 +184,14 @@ func TestTxHashAndID(t *testing.T) { spew.Sprint(tx1ID), spew.Sprint(wantTxID1)) } - hash2Str := "6b769655a1420022e4690a4f7bb9b1c381185ebbefe3070351f06fb573a0600c" + hash2Str := "0c60a073b56ff0510307e3efbb5e1881c3b1b97b4f0a69e4220042a15596766b" wantHash2, err := hashes.FromString(hash2Str) if err != nil { t.Errorf("NewTxIDFromStr: %v", err) return } - id2Str := "af916032e271adaaa21f02bee4b44db2cca4dad9149dcaebc188009c7313ec68" + id2Str := "68ec13739c0088c1ebca9d14d9daa4ccb24db4e4be021fa2aaad71e2326091af" wantID2, err := transactionid.FromString(id2Str) if err != nil { t.Errorf("NewTxIDFromStr: %v", err) diff --git a/domain/consensus/model/externalapi/hash.go b/domain/consensus/model/externalapi/hash.go index e7080e1bc..d52feac3c 100644 --- a/domain/consensus/model/externalapi/hash.go +++ b/domain/consensus/model/externalapi/hash.go @@ -8,12 +8,8 @@ const DomainHashSize = 32 // DomainHash is the domain representation of a Hash type DomainHash [DomainHashSize]byte -// String returns the Hash as the hexadecimal string of the byte-reversed -// hash. +// String returns the Hash as the hexadecimal string of the hash. func (hash DomainHash) String() string { - for i := 0; i < DomainHashSize/2; i++ { - hash[i], hash[DomainHashSize-1-i] = hash[DomainHashSize-1-i], hash[i] - } return hex.EncodeToString(hash[:]) } diff --git a/domain/consensus/model/pow/pow.go b/domain/consensus/model/pow/pow.go index 17edd68dc..c3fe5a717 100644 --- a/domain/consensus/model/pow/pow.go +++ b/domain/consensus/model/pow/pow.go @@ -1,13 +1,14 @@ package pow import ( + "math/big" + "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing" "github.com/kaspanet/kaspad/domain/consensus/utils/hashes" "github.com/kaspanet/kaspad/domain/consensus/utils/serialization" "github.com/kaspanet/kaspad/util" "github.com/pkg/errors" - "math/big" ) // CheckProofOfWorkWithTarget check's if the block has a valid PoW according to the provided target @@ -47,5 +48,17 @@ func calcPowValue(header *externalapi.DomainBlockHeader) *big.Int { if err != nil { panic(errors.Wrap(err, "this should never happen. Hash digest should never return an error")) } - return hashes.ToBig(writer.Finalize()) + return toBig(writer.Finalize()) +} + +// ToBig converts a externalapi.DomainHash into a big.Int treated as a little endian string. +func toBig(hash *externalapi.DomainHash) *big.Int { + // We treat the Hash as little-endian for PoW purposes, but the big package wants the bytes in big-endian, so reverse them. + buf := hash.Clone() + blen := len(buf) + for i := 0; i < blen/2; i++ { + buf[i], buf[blen-1-i] = buf[blen-1-i], buf[i] + } + + return new(big.Int).SetBytes(buf[:]) } diff --git a/domain/consensus/ruleerrors/rule_error_test.go b/domain/consensus/ruleerrors/rule_error_test.go index 5c95aafff..025f83ff9 100644 --- a/domain/consensus/ruleerrors/rule_error_test.go +++ b/domain/consensus/ruleerrors/rule_error_test.go @@ -9,7 +9,7 @@ import ( func TestNewErrMissingTxOut(t *testing.T) { outer := NewErrMissingTxOut([]*externalapi.DomainOutpoint{{TransactionID: externalapi.DomainTransactionID{255, 255, 255}, Index: 5}}) - expectedOuterErr := "ErrMissingTxOut: missing the following outpoint: [(0000000000000000000000000000000000000000000000000000000000ffffff: 5)]" + expectedOuterErr := "ErrMissingTxOut: missing the following outpoint: [(ffffff0000000000000000000000000000000000000000000000000000000000: 5)]" inner := &ErrMissingTxOut{} if !errors.As(outer, inner) { t.Fatal("TestWrapInRuleError: Outer should contain ErrMissingTxOut in it") @@ -41,7 +41,7 @@ func TestNewErrMissingTxOut(t *testing.T) { func TestNewErrInvalidTransactionsInNewBlock(t *testing.T) { outer := NewErrInvalidTransactionsInNewBlock([]InvalidTransaction{{&externalapi.DomainTransaction{Fee: 1337}, ErrNoTxInputs}}) //TODO: Implement Stringer for `DomainTransaction` - expectedOuterErr := "ErrInvalidTransactionsInNewBlock: [(4ea5363088df94b7b52afa9df9db7b44561e0a2219f2bf85b2f1d699cade933e: ErrNoTxInputs)]" + expectedOuterErr := "ErrInvalidTransactionsInNewBlock: [(3e93deca99d6f1b285bff219220a1e56447bdbf99dfa2ab5b794df883036a54e: ErrNoTxInputs)]" inner := &ErrInvalidTransactionsInNewBlock{} if !errors.As(outer, inner) { t.Fatal("TestNewErrInvalidTransactionsInNewBlock: Outer should contain ErrInvalidTransactionsInNewBlock in it") diff --git a/domain/consensus/utils/hashes/strings.go b/domain/consensus/utils/hashes/strings.go index 3c4b9625e..022dd94bf 100644 --- a/domain/consensus/utils/hashes/strings.go +++ b/domain/consensus/utils/hashes/strings.go @@ -8,7 +8,7 @@ import ( ) // FromString creates a DomainHash from a hash string. The string should be -// the hexadecimal string of a byte-reversed hash, but any missing characters +// the hexadecimal string of a hash, but any missing characters // result in zero padding at the end of the Hash. func FromString(hash string) (*externalapi.DomainHash, error) { ret := new(externalapi.DomainHash) @@ -19,8 +19,7 @@ func FromString(hash string) (*externalapi.DomainHash, error) { return ret, nil } -// decode decodes the byte-reversed hexadecimal string encoding of a Hash to a -// destination. +// decode decodes the hexadecimal string encoding of a Hash to a destination. func decode(dst *externalapi.DomainHash, src string) error { expectedSrcLength := externalapi.DomainHashSize * 2 // Return error if hash string is too long. @@ -40,19 +39,11 @@ func decode(dst *externalapi.DomainHash, src string) error { copy(srcBytes[1:], src) } - // Hex decode the source bytes to a temporary destination. - var reversedHash externalapi.DomainHash - _, err := hex.Decode(reversedHash[externalapi.DomainHashSize-hex.DecodedLen(len(srcBytes)):], srcBytes) + // Hex decode the source bytes + _, err := hex.Decode(dst[externalapi.DomainHashSize-hex.DecodedLen(len(srcBytes)):], srcBytes) if err != nil { return errors.Wrap(err, "couldn't decode hash hex") } - - // 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[:externalapi.DomainHashSize/2] { - dst[i], dst[externalapi.DomainHashSize-1-i] = reversedHash[externalapi.DomainHashSize-1-i], b - } - return nil }