Remove hash reversal (#1270)

* Remove hash reversing

* Move toBig to pow.go

* Update some tests
This commit is contained in:
Elichai Turkel 2020-12-23 12:42:37 +02:00 committed by GitHub
parent 729e3db145
commit 273c271771
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 27 additions and 27 deletions

View File

@ -132,8 +132,8 @@ func TestTx(t *testing.T) {
// TestTxHash tests the ability to generate the hash of a transaction accurately. // TestTxHash tests the ability to generate the hash of a transaction accurately.
func TestTxHashAndID(t *testing.T) { func TestTxHashAndID(t *testing.T) {
txHash1Str := "c2ac1e792c5c49260103ad9f86caf749d431958b7c7e5e5129346ceab8b709cf" txHash1Str := "cf09b7b8ea6c3429515e7e7c8b9531d449f7ca869fad030126495c2c791eacc2"
txID1Str := "47ce12a5ee5727cf97c0481eebedad0d80646b743305b0921a2403f1836f8b37" txID1Str := "378b6f83f103241a92b00533746b64800dadedeb1e48c097cf2757eea512ce47"
wantTxID1, err := transactionid.FromString(txID1Str) wantTxID1, err := transactionid.FromString(txID1Str)
if err != nil { if err != nil {
t.Fatalf("NewTxIDFromStr: %v", err) t.Fatalf("NewTxIDFromStr: %v", err)
@ -174,7 +174,7 @@ func TestTxHashAndID(t *testing.T) {
tx1Hash := tx1.TxHash() tx1Hash := tx1.TxHash()
if *tx1Hash != (externalapi.DomainHash)(*wantTxHash1) { if *tx1Hash != (externalapi.DomainHash)(*wantTxHash1) {
t.Errorf("TxHash: wrong hash - got %v, want %v", 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. // 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)) spew.Sprint(tx1ID), spew.Sprint(wantTxID1))
} }
hash2Str := "6b769655a1420022e4690a4f7bb9b1c381185ebbefe3070351f06fb573a0600c" hash2Str := "0c60a073b56ff0510307e3efbb5e1881c3b1b97b4f0a69e4220042a15596766b"
wantHash2, err := hashes.FromString(hash2Str) wantHash2, err := hashes.FromString(hash2Str)
if err != nil { if err != nil {
t.Errorf("NewTxIDFromStr: %v", err) t.Errorf("NewTxIDFromStr: %v", err)
return return
} }
id2Str := "af916032e271adaaa21f02bee4b44db2cca4dad9149dcaebc188009c7313ec68" id2Str := "68ec13739c0088c1ebca9d14d9daa4ccb24db4e4be021fa2aaad71e2326091af"
wantID2, err := transactionid.FromString(id2Str) wantID2, err := transactionid.FromString(id2Str)
if err != nil { if err != nil {
t.Errorf("NewTxIDFromStr: %v", err) t.Errorf("NewTxIDFromStr: %v", err)

View File

@ -8,12 +8,8 @@ const DomainHashSize = 32
// DomainHash is the domain representation of a Hash // DomainHash is the domain representation of a Hash
type DomainHash [DomainHashSize]byte type DomainHash [DomainHashSize]byte
// String returns the Hash as the hexadecimal string of the byte-reversed // String returns the Hash as the hexadecimal string of the hash.
// hash.
func (hash DomainHash) String() string { 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[:]) return hex.EncodeToString(hash[:])
} }

View File

@ -1,13 +1,14 @@
package pow package pow
import ( import (
"math/big"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing" "github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/hashes" "github.com/kaspanet/kaspad/domain/consensus/utils/hashes"
"github.com/kaspanet/kaspad/domain/consensus/utils/serialization" "github.com/kaspanet/kaspad/domain/consensus/utils/serialization"
"github.com/kaspanet/kaspad/util" "github.com/kaspanet/kaspad/util"
"github.com/pkg/errors" "github.com/pkg/errors"
"math/big"
) )
// CheckProofOfWorkWithTarget check's if the block has a valid PoW according to the provided target // 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 { if err != nil {
panic(errors.Wrap(err, "this should never happen. Hash digest should never return an error")) 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[:])
} }

View File

@ -9,7 +9,7 @@ import (
func TestNewErrMissingTxOut(t *testing.T) { func TestNewErrMissingTxOut(t *testing.T) {
outer := NewErrMissingTxOut([]*externalapi.DomainOutpoint{{TransactionID: externalapi.DomainTransactionID{255, 255, 255}, Index: 5}}) 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{} inner := &ErrMissingTxOut{}
if !errors.As(outer, inner) { if !errors.As(outer, inner) {
t.Fatal("TestWrapInRuleError: Outer should contain ErrMissingTxOut in it") t.Fatal("TestWrapInRuleError: Outer should contain ErrMissingTxOut in it")
@ -41,7 +41,7 @@ func TestNewErrMissingTxOut(t *testing.T) {
func TestNewErrInvalidTransactionsInNewBlock(t *testing.T) { func TestNewErrInvalidTransactionsInNewBlock(t *testing.T) {
outer := NewErrInvalidTransactionsInNewBlock([]InvalidTransaction{{&externalapi.DomainTransaction{Fee: 1337}, ErrNoTxInputs}}) outer := NewErrInvalidTransactionsInNewBlock([]InvalidTransaction{{&externalapi.DomainTransaction{Fee: 1337}, ErrNoTxInputs}})
//TODO: Implement Stringer for `DomainTransaction` //TODO: Implement Stringer for `DomainTransaction`
expectedOuterErr := "ErrInvalidTransactionsInNewBlock: [(4ea5363088df94b7b52afa9df9db7b44561e0a2219f2bf85b2f1d699cade933e: ErrNoTxInputs)]" expectedOuterErr := "ErrInvalidTransactionsInNewBlock: [(3e93deca99d6f1b285bff219220a1e56447bdbf99dfa2ab5b794df883036a54e: ErrNoTxInputs)]"
inner := &ErrInvalidTransactionsInNewBlock{} inner := &ErrInvalidTransactionsInNewBlock{}
if !errors.As(outer, inner) { if !errors.As(outer, inner) {
t.Fatal("TestNewErrInvalidTransactionsInNewBlock: Outer should contain ErrInvalidTransactionsInNewBlock in it") t.Fatal("TestNewErrInvalidTransactionsInNewBlock: Outer should contain ErrInvalidTransactionsInNewBlock in it")

View File

@ -8,7 +8,7 @@ import (
) )
// FromString creates a DomainHash from a hash string. The string should be // 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. // result in zero padding at the end of the Hash.
func FromString(hash string) (*externalapi.DomainHash, error) { func FromString(hash string) (*externalapi.DomainHash, error) {
ret := new(externalapi.DomainHash) ret := new(externalapi.DomainHash)
@ -19,8 +19,7 @@ func FromString(hash string) (*externalapi.DomainHash, error) {
return ret, nil return ret, nil
} }
// decode decodes the byte-reversed hexadecimal string encoding of a Hash to a // decode decodes the hexadecimal string encoding of a Hash to a destination.
// destination.
func decode(dst *externalapi.DomainHash, src string) error { func decode(dst *externalapi.DomainHash, src string) error {
expectedSrcLength := externalapi.DomainHashSize * 2 expectedSrcLength := externalapi.DomainHashSize * 2
// Return error if hash string is too long. // Return error if hash string is too long.
@ -40,19 +39,11 @@ func decode(dst *externalapi.DomainHash, src string) error {
copy(srcBytes[1:], src) copy(srcBytes[1:], src)
} }
// Hex decode the source bytes to a temporary destination. // Hex decode the source bytes
var reversedHash externalapi.DomainHash _, err := hex.Decode(dst[externalapi.DomainHashSize-hex.DecodedLen(len(srcBytes)):], srcBytes)
_, err := hex.Decode(reversedHash[externalapi.DomainHashSize-hex.DecodedLen(len(srcBytes)):], srcBytes)
if err != nil { if err != nil {
return errors.Wrap(err, "couldn't decode hash hex") 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 return nil
} }