Skip to content

Commit

Permalink
StateProofs: New block header field - SHA256 merkle root of the trans…
Browse files Browse the repository at this point in the history
…actions (#3829)

Currently, the TxnRoot block header contains the root of the merkle tree
built from the transactions in the block, using the SHA512_256 hash function.
Since the Ethereum VM (and others) does not support SHA512_256 natively,
we have added a new header, which will be used by the Light Clients
deployed on other networks in order to verify Algorand blocks.

Co-authored-by: algoidan <79864820+algoidan@users.noreply.github.com>
  • Loading branch information
Aharonee and id-ms authored May 10, 2022
1 parent 683d95a commit bd18d04
Show file tree
Hide file tree
Showing 42 changed files with 3,121 additions and 2,212 deletions.
469 changes: 269 additions & 200 deletions agreement/msgp_gen.go

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions catchup/fetcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func buildTestLedger(t *testing.T, blk bookkeeping.Block) (ledger *data.Ledger,
b.Payset = []transactions.SignedTxnInBlock{
txib,
}
b.TxnRoot, err = b.PaysetCommit()
b.TxnCommitments, err = b.PaysetCommit()
require.NoError(t, err)
require.NoError(t, ledger.AddBlock(b, agreement.Certificate{Round: next}))
return
Expand All @@ -116,7 +116,7 @@ func addBlocks(t *testing.T, ledger *data.Ledger, blk bookkeeping.Block, numBloc
for i := 0; i < numBlocks; i++ {
blk.BlockHeader.Round++
blk.BlockHeader.TimeStamp += int64(crypto.RandUint64() % 100 * 1000)
blk.TxnRoot, err = blk.PaysetCommit()
blk.TxnCommitments, err = blk.PaysetCommit()
require.NoError(t, err)

err := ledger.AddBlock(blk, agreement.Certificate{Round: blk.BlockHeader.Round})
Expand Down
7 changes: 7 additions & 0 deletions config/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,11 @@ type ConsensusParams struct {

// UnifyInnerTxIDs enables a consistent, unified way of computing inner transaction IDs
UnifyInnerTxIDs bool

// EnableSHA256TxnCommitmentHeader enables the creation of a transaction vector commitment tree using SHA256 hash function. (vector commitment extends Merkle tree by having a position binding property).
// This new header is in addition to the existing SHA512_256 merkle root.
// It is useful for verifying transaction on different blockchains, as some may not support SHA512_256 OPCODE natively but SHA256 is common.
EnableSHA256TxnCommitmentHeader bool
}

// PaysetCommitType enumerates possible ways for the block header to commit to
Expand Down Expand Up @@ -1144,6 +1149,8 @@ func initConsensusProtocols() {

vFuture.UnifyInnerTxIDs = true

vFuture.EnableSHA256TxnCommitmentHeader = true

Consensus[protocol.ConsensusFuture] = vFuture
}

Expand Down
2 changes: 1 addition & 1 deletion crypto/compactcert/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (

// Params defines common parameters for the verifier and builder.
type Params struct {
Msg crypto.Hashable // Message to be cerified
Msg crypto.Hashable // Message to be certified
ProvenWeight uint64 // Weight threshold proven by the certificate
SigRound basics.Round // The round for which the ephemeral key is committed to
SecKQ uint64 // Security parameter (k+q) from analysis document
Expand Down
10 changes: 9 additions & 1 deletion crypto/hashes.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package crypto

import (
"crypto/sha256"
"crypto/sha512"
"errors"
"fmt"
Expand All @@ -41,7 +42,7 @@ func (h HashType) Validate() error {
const (
Sha512_256 HashType = iota
Sumhash

Sha256
MaxHashType
)

Expand All @@ -53,6 +54,7 @@ const MaxHashDigestSize = SumhashDigestSize
const (
Sha512_256Size = sha512.Size256
SumhashDigestSize = sumhash.Sumhash512DigestSize
Sha256Size = sha256.Size
)

// HashFactory is responsible for generating new hashes accordingly to the type it stores.
Expand All @@ -71,6 +73,8 @@ func (h HashType) String() string {
return "sha512_256"
case Sumhash:
return "sumhash"
case Sha256:
return "sha256"
default:
return ""
}
Expand All @@ -83,6 +87,8 @@ func UnmarshalHashType(s string) (HashType, error) {
return Sha512_256, nil
case "sumhash":
return Sumhash, nil
case "sha256":
return Sha256, nil
default:
return 0, fmt.Errorf("HashType not supported: %s", s)
}
Expand All @@ -96,6 +102,8 @@ func (z HashFactory) NewHash() hash.Hash {
return sha512.New512_256()
case Sumhash:
return sumhash.New512(nil)
case Sha256:
return sha256.New()
// This shouldn't be reached, when creating a new hash, one would know the type of hash they wanted,
// in addition to that, unmarshalling of the hashFactory verifies the HashType of the factory.
default:
Expand Down
3 changes: 3 additions & 0 deletions crypto/hashes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ func TestHashFactoryCreatingNewHashes(t *testing.T) {
a.NotNil(h)
a.Equal(SumhashDigestSize, h.Size())

h = HashFactory{HashType: Sha256}.NewHash()
a.NotNil(h)
a.Equal(Sha256Size, h.Size())
}

func TestHashSum(t *testing.T) {
Expand Down
Loading

0 comments on commit bd18d04

Please sign in to comment.