Skip to content

Commit

Permalink
accountsHash determinism, and global types.Hash use
Browse files Browse the repository at this point in the history
  • Loading branch information
jchappelow committed Dec 4, 2024
1 parent d560978 commit 674526b
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 31 deletions.
9 changes: 4 additions & 5 deletions app/shared/display/message.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package display

import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
Expand Down Expand Up @@ -112,9 +111,9 @@ func (r *RespTxQuery) MarshalJSON() ([]byte, error) {
out.Warn = "ERROR encoding transaction: " + err.Error()
} else if r.WithRaw {
out.Raw = hex.EncodeToString(raw)
hash := sha256.Sum256(raw)
hash := types.HashBytes(raw)
if hash != r.Msg.Hash {
out.Warn = fmt.Sprintf("HASH MISMATCH: requested %s; received %x",
out.Warn = fmt.Sprintf("HASH MISMATCH: requested %s; received %s",
r.Msg.Hash, hash)
}
}
Expand Down Expand Up @@ -155,9 +154,9 @@ Log: %s`,
if r.WithRaw {
msg += "\nRaw: " + hex.EncodeToString(raw)
}
hash := sha256.Sum256(raw)
hash := types.HashBytes(raw)
if hash != r.Msg.Hash {
msg += fmt.Sprintf("\nWARNING! HASH MISMATCH:\n\tRequested %s\n\tReceived %x",
msg += fmt.Sprintf("\nWARNING! HASH MISMATCH:\n\tRequested %s\n\tReceived %s",
r.Msg.Hash, hash)
}
}
Expand Down
8 changes: 3 additions & 5 deletions cmd/kwil-cli/cmds/utils/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ package utils

import (
"bytes"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -57,8 +55,8 @@ func (t *transaction) MarshalJSON() ([]byte, error) {
}

func (t *transaction) MarshalText() ([]byte, error) {
txHash := sha256.Sum256(t.Raw) // tmhash is sha256
msg := fmt.Sprintf(`Transaction ID: %x
txHash := types.HashBytes(t.Raw)
msg := fmt.Sprintf(`Transaction ID: %s
Sender: %s
Description: %s
Payload type: %s
Expand All @@ -69,7 +67,7 @@ Signature type: %s
Signature: %s
`,
txHash,
hex.EncodeToString(t.Tx.Sender), // hex because it's an address or pubkey, probably address
t.Tx.Sender.String(),
t.Tx.Body.Description,
t.Tx.Body.PayloadType,
t.Tx.Body.ChainID,
Expand Down
2 changes: 1 addition & 1 deletion core/types/hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func HashBytes(b []byte) Hash {
}

// Hasher is like the standard library's hash.Hash, but with fewer methods and
// returning a Hash instead of a byte slice. Use [NewHasher] to get a Hasher.
// returning a [Hash] instead of a byte slice. Use [NewHasher] to get a Hasher.
type Hasher interface {
// Write more data to the running hash. It never returns an error.
io.Writer
Expand Down
11 changes: 10 additions & 1 deletion core/types/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package types

import (
"bytes"
"encoding"
"encoding/binary"
"encoding/json"
"errors"
Expand Down Expand Up @@ -43,7 +44,7 @@ type Transaction struct {
Serialization SignedMsgSerializationType `json:"serialization"`

// Sender is the user identifier, which is generally an address but may be
// a public key of the sender.
// a public key of the sender, hence bytes that encode as hexadecimal.
Sender HexBytes `json:"sender"`

strictUnmarshal bool
Expand Down Expand Up @@ -258,6 +259,8 @@ func (t *TransactionBody) SerializeMsg(mst SignedMsgSerializationType) ([]byte,
return nil, errors.New("invalid serialization type")
}

var _ encoding.BinaryMarshaler = (*Transaction)(nil)

// MarshalBinary produces the full binary serialization of the transaction,
// which is the form used in p2p messaging and blockchain storage.
func (t *Transaction) MarshalBinary() ([]byte, error) {
Expand All @@ -278,6 +281,8 @@ func (t *Transaction) ReadFrom(r io.Reader) (int64, error) {
return int64(n), nil
}

var _ encoding.BinaryUnmarshaler = (*Transaction)(nil)

func (t *Transaction) UnmarshalBinary(data []byte) error {
r := bytes.NewReader(data)
n, err := t.deserialize(r)
Expand All @@ -296,6 +301,8 @@ func (t *Transaction) UnmarshalBinary(data []byte) error {
return nil
}

var _ encoding.BinaryMarshaler = (*TransactionBody)(nil)

func (tb *TransactionBody) MarshalBinary() ([]byte, error) {
buf := new(bytes.Buffer)

Expand Down Expand Up @@ -386,6 +393,8 @@ func (tb *TransactionBody) ReadFrom(r io.Reader) (int64, error) {
return int64(n), nil
}

var _ encoding.BinaryUnmarshaler = (*TransactionBody)(nil)

func (tb *TransactionBody) UnmarshalBinary(data []byte) error {
buf := bytes.NewReader(data)
n, err := tb.ReadFrom(buf)
Expand Down
30 changes: 17 additions & 13 deletions node/consensus/block_executor.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package consensus

import (
"bytes"
"context"
"crypto/sha256"
"encoding/binary"
"encoding/hex"
"fmt"
"slices"
"sort"

"github.com/kwilteam/kwil-db/common"
Expand Down Expand Up @@ -74,15 +75,15 @@ func (ce *ConsensusEngine) executeBlock() (err error) {

// TODO: log tracker

var txResults []ktypes.TxResult
txResults := make([]ktypes.TxResult, len(ce.state.blkProp.blk.Txns))

for _, tx := range ce.state.blkProp.blk.Txns {
for i, tx := range ce.state.blkProp.blk.Txns {
decodedTx := &ktypes.Transaction{}
if err := decodedTx.UnmarshalBinary(tx); err != nil {
ce.log.Error("Failed to unmarshal the block tx", "err", err)
return err
}
txHash := sha256.Sum256(tx)
txHash := types.HashBytes(tx)

auth := auth.GetAuthenticator(decodedTx.Signature.Type)

Expand Down Expand Up @@ -118,7 +119,7 @@ func (ce *ConsensusEngine) executeBlock() (err error) {
txResult.Log = "success"
}

txResults = append(txResults, txResult)
txResults[i] = txResult
}
}

Expand Down Expand Up @@ -195,7 +196,7 @@ func (ce *ConsensusEngine) executeBlock() (err error) {
// nextAppHash calculates the appHash that encapsulates the state changes occurred during the block execution.
// sha256(prevAppHash || changesetHash || valUpdatesHash || accountsHash || txResultsHash)
func (ce *ConsensusEngine) nextAppHash(prevAppHash, changesetHash, valUpdatesHash, accountsHash, txResultsHash types.Hash) types.Hash {
hasher := sha256.New()
hasher := ktypes.NewHasher()

hasher.Write(prevAppHash[:])
hasher.Write(changesetHash[:])
Expand All @@ -204,29 +205,32 @@ func (ce *ConsensusEngine) nextAppHash(prevAppHash, changesetHash, valUpdatesHas
hasher.Write(txResultsHash[:])

ce.log.Info("AppState updates: ", "prevAppHash", prevAppHash, "changesetsHash", changesetHash, "valUpdatesHash", valUpdatesHash, "accountsHash", accountsHash, "txResultsHash", txResultsHash)
return types.Hash(hasher.Sum(nil))
return hasher.Sum(nil)
}

func txResultsHash(results []ktypes.TxResult) types.Hash {
hasher := sha256.New()
hasher := ktypes.NewHasher()
for _, res := range results {
binary.Write(hasher, binary.BigEndian, res.Code)
binary.Write(hasher, binary.BigEndian, res.Gas)
}

return types.Hash(hasher.Sum(nil))
return hasher.Sum(nil)
}

func (ce *ConsensusEngine) accountsHash() types.Hash {
accounts := ce.accounts.Updates()
hasher := sha256.New()
slices.SortFunc(accounts, func(a, b *ktypes.Account) int {
return bytes.Compare(a.Identifier, b.Identifier)
})
hasher := ktypes.NewHasher()
for _, acc := range accounts {
hasher.Write(acc.Identifier)
binary.Write(hasher, binary.BigEndian, acc.Balance.Bytes())
binary.Write(hasher, binary.BigEndian, acc.Nonce)
}

return types.Hash(hasher.Sum(nil))
return hasher.Sum(nil)
}

func validatorUpdatesHash(updates map[string]*ktypes.Validator) types.Hash {
Expand All @@ -239,15 +243,15 @@ func validatorUpdatesHash(updates map[string]*ktypes.Validator) types.Hash {
}
sort.Strings(keys)

hash := sha256.New()
hash := ktypes.NewHasher()
for _, k := range keys {
// hash the validator address
hash.Write(updates[k].PubKey)
// hash the validator power
binary.Write(hash, binary.BigEndian, updates[k].Power)
}

return types.Hash(hash.Sum(nil))
return hash.Sum(nil)
}

// Commit method commits the block to the blockstore and postgres database.
Expand Down
7 changes: 3 additions & 4 deletions node/types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package types

import (
"bytes"
"crypto/sha256"
"encoding/binary"
"fmt"
"io"
Expand Down Expand Up @@ -208,9 +207,9 @@ func EncodeBlockHeader(hdr *BlockHeader) []byte {
}

func (bh *BlockHeader) Hash() Hash {
hasher := sha256.New()
hasher := types.NewHasher()
bh.writeBlockHeader(hasher)
return Hash(hasher.Sum(nil))
return hasher.Sum(nil)
}

/*func encodeBlockHeaderOneAlloc(hdr *BlockHeader) []byte {
Expand Down Expand Up @@ -296,7 +295,7 @@ func CalcMerkleRoot(leaves []Hash) Hash {
for i := range len(leaves) / 2 {
copy(left, leaves[i*2][:])
copy(right, leaves[i*2+1][:])
leaves[i] = sha256.Sum256(both)
leaves[i] = types.HashBytes(both)
}
leaves = leaves[:len(leaves)/2]
}
Expand Down
4 changes: 2 additions & 2 deletions node/types/block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package types

import (
"bytes"
"crypto/sha256"
"encoding/binary"
"testing"
"time"

"github.com/kwilteam/kwil-db/core/crypto"
"github.com/kwilteam/kwil-db/core/types"

"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -120,7 +120,7 @@ func TestCalcMerkleRoot(t *testing.T) {
var buf [HashLen * 2]byte
copy(buf[:HashLen], leaf1[:])
copy(buf[HashLen:], leaf2[:])
expected := sha256.Sum256(buf[:])
expected := types.HashBytes(buf[:])

if root != expected {
t.Errorf("got root %x, want %x", root, expected)
Expand Down

0 comments on commit 674526b

Please sign in to comment.