github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/merkle/merkle_tree.go (about)

     1  /*
     2   * Copyright (C) 2018 The ontology Authors
     3   * This file is part of The ontology library.
     4   *
     5   * The ontology is free software: you can redistribute it and/or modify
     6   * it under the terms of the GNU Lesser General Public License as published by
     7   * the Free Software Foundation, either version 3 of the License, or
     8   * (at your option) any later version.
     9   *
    10   * The ontology is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU Lesser General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU Lesser General Public License
    16   * along with The ontology.  If not, see <http://www.gnu.org/licenses/>.
    17   */
    18  
    19  package merkle
    20  
    21  import (
    22  	"encoding/binary"
    23  	"errors"
    24  	"fmt"
    25  
    26  	"github.com/sixexorg/magnetic-ring/common"
    27  	"github.com/sixexorg/magnetic-ring/log"
    28  )
    29  
    30  // const UINT256_SIZE int = 32
    31  
    32  // type common.Uint256 [UINT256_SIZE]byte
    33  
    34  var EMPTY_HASH = common.Hash{}
    35  
    36  // CompactMerkleTree calculate merkle tree with compact hash store in HashStore
    37  type CompactMerkleTree struct {
    38  	mintree_h uint
    39  	hashes    []common.Hash
    40  	hasher    TreeHasher
    41  	hashStore HashStore
    42  	rootHash  common.Hash
    43  	treeSize  uint64
    44  }
    45  
    46  // NewTree returns a CompactMerkleTree instance
    47  func NewTree(tree_size uint64, hashes []common.Hash, store HashStore) *CompactMerkleTree {
    48  
    49  	tree := &CompactMerkleTree{
    50  		mintree_h: 0,
    51  		hashes:    nil,
    52  		hasher:    TreeHasher{},
    53  		hashStore: store,
    54  		rootHash:  EMPTY_HASH,
    55  	}
    56  
    57  	tree._update(tree_size, hashes)
    58  	return tree
    59  }
    60  
    61  func (self *CompactMerkleTree) Hashes() []common.Hash {
    62  	return self.hashes
    63  }
    64  
    65  func (self *CompactMerkleTree) TreeSize() uint64 {
    66  	return self.treeSize
    67  }
    68  
    69  func (self *CompactMerkleTree) Marshal() ([]byte, error) {
    70  	length := 8 + len(self.hashes)*common.HashLength
    71  	buf := make([]byte, 8, length)
    72  	binary.BigEndian.PutUint64(buf[0:], self.treeSize)
    73  	for _, h := range self.hashes {
    74  		buf = append(buf, h[:]...)
    75  	}
    76  	return buf, nil
    77  }
    78  
    79  func (self *CompactMerkleTree) UnMarshal(buf []byte) error {
    80  	tree_size := binary.BigEndian.Uint64(buf[0:8])
    81  	nhashes := countBit(tree_size)
    82  	if len(buf) < 8+int(nhashes)*common.HashLength {
    83  		return errors.New("Too short input buf length")
    84  	}
    85  	hashes := make([]common.Hash, nhashes, nhashes)
    86  	for i := 0; i < int(nhashes); i++ {
    87  		copy(hashes[i][:], buf[8+i*common.HashLength:])
    88  	}
    89  	self._update(tree_size, hashes)
    90  	return nil
    91  }
    92  
    93  func (self *CompactMerkleTree) _update(tree_size uint64, hashes []common.Hash) {
    94  	numBit := countBit(tree_size)
    95  	if len(hashes) != int(numBit) {
    96  		panic("number of hashes != num bit in tree_size")
    97  	}
    98  	self.treeSize = tree_size
    99  	self.hashes = hashes
   100  	self.mintree_h = lowBit(tree_size)
   101  	self.rootHash = EMPTY_HASH
   102  
   103  }
   104  
   105  // Root returns root hash of merkle tree
   106  func (self *CompactMerkleTree) Root() common.Hash {
   107  	if self.rootHash == EMPTY_HASH {
   108  		if len(self.hashes) != 0 {
   109  			self.rootHash = self.hasher._hash_fold(self.hashes)
   110  		} else {
   111  			self.rootHash = self.hasher.hash_empty()
   112  		}
   113  	}
   114  	return self.rootHash
   115  }
   116  
   117  // GetRootWithNewLeaf returns the new root hash if newLeaf is appended to the merkle tree
   118  func (self *CompactMerkleTree) GetRootWithNewLeaf(newLeaf common.Hash) common.Hash {
   119  	hashes := append(self.hashes, newLeaf)
   120  	root := self.hasher._hash_fold(hashes)
   121  
   122  	return root
   123  }
   124  
   125  // Append appends a leaf to the merkle tree and returns the audit path
   126  func (self *CompactMerkleTree) Append(leafv []byte) []common.Hash {
   127  	leaf := self.hasher.hash_leaf(leafv)
   128  
   129  	return self.AppendHash(leaf)
   130  }
   131  
   132  // AppendHash appends a leaf hash to the merkle tree and returns the audit path
   133  func (self *CompactMerkleTree) AppendHash(leaf common.Hash) []common.Hash {
   134  	size := len(self.hashes)
   135  	auditPath := make([]common.Hash, size, size)
   136  	storehashes := make([]common.Hash, 0)
   137  	// reverse
   138  	for i, v := range self.hashes {
   139  		auditPath[size-i-1] = v
   140  	}
   141  
   142  	storehashes = append(storehashes, leaf)
   143  	self.mintree_h = 1
   144  	for s := self.treeSize; s%2 == 1; s = s >> 1 {
   145  		self.mintree_h += 1
   146  		leaf = self.hasher.hash_children(self.hashes[size-1], leaf)
   147  		storehashes = append(storehashes, leaf)
   148  		size -= 1
   149  	}
   150  	if self.hashStore != nil {
   151  		self.hashStore.Append(storehashes)
   152  		self.hashStore.Flush()
   153  	}
   154  	self.treeSize += 1
   155  	self.hashes = self.hashes[0:size]
   156  	self.hashes = append(self.hashes, leaf)
   157  	self.rootHash = EMPTY_HASH
   158  
   159  	return auditPath
   160  }
   161  
   162  func (self *CompactMerkleTree) Subtract() {
   163  
   164  }
   165  
   166  func (self *CompactMerkleTree) DumpStatus() {
   167  	log.Error("tree root:", self.rootHash)
   168  	log.Error("tree size:", self.treeSize)
   169  	log.Error("hashes size:", len(self.hashes))
   170  	log.Error("hashes  ", self.hashes)
   171  	log.Error("mintree_h  ", self.mintree_h)
   172  }
   173  
   174  // 1 based n
   175  func getSubTreeSize(n uint64) []uint64 {
   176  	nhashes := countBit(n)
   177  	subtreesize := make([]uint64, nhashes, nhashes)
   178  	for i, id := nhashes-1, uint64(1); n != 0; n = n >> 1 {
   179  		id = id * 2
   180  		if n%2 == 1 {
   181  			subtreesize[i] = id - 1
   182  			i -= 1
   183  		}
   184  	}
   185  
   186  	return subtreesize
   187  }
   188  
   189  // 1-based n and return value
   190  func getSubTreePos(n uint64) []uint64 {
   191  	nhashes := countBit(n)
   192  	hashespos := make([]uint64, nhashes, nhashes)
   193  	for i, id := nhashes-1, uint64(1); n != 0; n = n >> 1 {
   194  		id = id * 2
   195  		if n%2 == 1 {
   196  			hashespos[i] = id - 1
   197  			i -= 1
   198  		}
   199  	}
   200  
   201  	for i := uint(1); i < nhashes; i++ {
   202  		hashespos[i] += hashespos[i-1]
   203  	}
   204  
   205  	return hashespos
   206  }
   207  
   208  // return merkle root of D[0:n] not include n
   209  func (self *CompactMerkleTree) merkleRoot(n uint64) common.Hash {
   210  	hashespos := getSubTreePos(n)
   211  	nhashes := uint(len(hashespos))
   212  
   213  	hashes := make([]common.Hash, nhashes, nhashes)
   214  	for i := uint(0); i < nhashes; i++ {
   215  		hashes[i], _ = self.hashStore.GetHash(hashespos[i] - 1)
   216  	}
   217  	return self.hasher._hash_fold(hashes)
   218  }
   219  
   220  // ConsistencyProof returns consistency proof
   221  func (self *CompactMerkleTree) ConsistencyProof(m, n uint64) []common.Hash {
   222  	if m > n || self.treeSize < n || self.hashStore == nil {
   223  		return nil
   224  	}
   225  
   226  	return self.subproof(m, n, true)
   227  }
   228  
   229  // m, n 1-based
   230  func (self *CompactMerkleTree) subproof(m, n uint64, b bool) []common.Hash {
   231  	offset := uint64(0)
   232  	var hashes []common.Hash
   233  	for m < n {
   234  		k := uint64(1 << (highBit(n-1) - 1))
   235  		if m <= k {
   236  			pos := getSubTreePos(n - k)
   237  			subhashes := make([]common.Hash, len(pos), len(pos))
   238  			for p := range pos {
   239  				pos[p] += offset + k*2 - 1
   240  				subhashes[p], _ = self.hashStore.GetHash(pos[p] - 1)
   241  			}
   242  			rootk2n := self.hasher._hash_fold(subhashes)
   243  			hashes = append(hashes, rootk2n)
   244  			n = k
   245  		} else {
   246  			offset += k*2 - 1
   247  			root02k, _ := self.hashStore.GetHash(offset - 1)
   248  			hashes = append(hashes, root02k)
   249  			m -= k
   250  			n -= k
   251  			b = false
   252  		}
   253  	}
   254  
   255  	//assert m == n
   256  	if b == false {
   257  		pos := getSubTreePos(n)
   258  		//assert len(pos) == 1
   259  		if len(pos) != 1 {
   260  			panic("assert error")
   261  		}
   262  		root02n, _ := self.hashStore.GetHash(pos[0] + offset - 1)
   263  		hashes = append(hashes, root02n)
   264  	}
   265  
   266  	length := len(hashes)
   267  	reverse := make([]common.Hash, length, length)
   268  	for k, _ := range reverse {
   269  		reverse[k] = hashes[length-k-1]
   270  	}
   271  
   272  	return reverse
   273  }
   274  
   275  // InclusionProof returns the proof d[m] in D[0:n]
   276  // m zero based index, n size 1-based
   277  func (self *CompactMerkleTree) InclusionProof(m, n uint64) ([]common.Hash, error) {
   278  	if m >= n {
   279  		return nil, errors.New("wrong parameters")
   280  	} else if self.treeSize < n {
   281  		return nil, errors.New("not available yet")
   282  	} else if self.hashStore == nil {
   283  		return nil, errors.New("hash store not available")
   284  	}
   285  
   286  	offset := uint64(0)
   287  	var hashes []common.Hash
   288  	for n != 1 {
   289  		k := uint64(1 << (highBit(n-1) - 1))
   290  		if m < k {
   291  			pos := getSubTreePos(n - k)
   292  			subhashes := make([]common.Hash, len(pos), len(pos))
   293  			for p := range pos {
   294  				pos[p] += offset + k*2 - 1
   295  				subhashes[p], _ = self.hashStore.GetHash(pos[p] - 1)
   296  			}
   297  			rootk2n := self.hasher._hash_fold(subhashes)
   298  			hashes = append(hashes, rootk2n)
   299  			n = k
   300  		} else {
   301  			offset += k*2 - 1
   302  			root02k, _ := self.hashStore.GetHash(offset - 1)
   303  			hashes = append(hashes, root02k)
   304  			m -= k
   305  			n -= k
   306  		}
   307  	}
   308  
   309  	length := len(hashes)
   310  	reverse := make([]common.Hash, length, length)
   311  	for k := range reverse {
   312  		reverse[k] = hashes[length-k-1]
   313  	}
   314  
   315  	return reverse, nil
   316  }
   317  
   318  // MerkleVerifier verify inclusion and consist proof
   319  type MerkleVerifier struct {
   320  	hasher TreeHasher
   321  }
   322  
   323  func NewMerkleVerifier() *MerkleVerifier {
   324  	return &MerkleVerifier{
   325  		hasher: TreeHasher{},
   326  	}
   327  }
   328  
   329  /*
   330     Verify a Merkle Audit PATH.
   331  
   332     leaf_hash: The hash of the leaf for which the proof was provided.
   333     leaf_index: Index of the leaf in the tree.
   334     proof: A list of SHA-256 hashes representing the  Merkle audit path.
   335     tree_size: The size of the tree
   336     root_hash: The root hash of the tree
   337  
   338     Returns:
   339         nil when the proof is valid
   340  */
   341  func (self *MerkleVerifier) VerifyLeafHashInclusion(leaf_hash common.Hash,
   342  	leaf_index uint64, proof []common.Hash, root_hash common.Hash, tree_size uint64) error {
   343  
   344  	if tree_size <= leaf_index {
   345  		return errors.New("Wrong params: the tree size is smaller than the leaf index")
   346  	}
   347  
   348  	calculated_root_hash, err := self.calculate_root_hash_from_audit_path(leaf_hash,
   349  		leaf_index, proof, tree_size)
   350  	if err != nil {
   351  		return err
   352  	}
   353  	if calculated_root_hash != root_hash {
   354  		return errors.New(fmt.Sprintf("Constructed root hash differs from provided root hash. Constructed: %x, Expected: %x",
   355  			calculated_root_hash, root_hash))
   356  	}
   357  
   358  	return nil
   359  }
   360  
   361  /*
   362     Verify a Merkle Audit PATH.
   363  
   364     leaf: The leaf for which the proof is provided
   365     leaf_index: Index of the leaf in the tree.
   366     proof: A list of SHA-256 hashes representing the  Merkle audit path.
   367     tree_size: The size of the tree
   368     root_hash: The root hash of the tree
   369  
   370     Returns:
   371         nil when the proof is valid
   372  */
   373  func (self *MerkleVerifier) VerifyLeafInclusion(leaf []byte,
   374  	leaf_index uint64, proof []common.Hash, root_hash common.Hash, tree_size uint64) error {
   375  	leaf_hash := self.hasher.hash_leaf(leaf)
   376  	return self.VerifyLeafHashInclusion(leaf_hash, leaf_index, proof, root_hash, tree_size)
   377  }
   378  
   379  func (self *MerkleVerifier) calculate_root_hash_from_audit_path(leaf_hash common.Hash,
   380  	node_index uint64, audit_path []common.Hash, tree_size uint64) (common.Hash, error) {
   381  	calculated_hash := leaf_hash
   382  	last_node := tree_size - 1
   383  	pos := 0
   384  	path_len := len(audit_path)
   385  	for last_node > 0 {
   386  		if pos >= path_len {
   387  			return EMPTY_HASH, errors.New(fmt.Sprintf("Proof too short. expected %d, got %d",
   388  				audit_path_length(node_index, tree_size), path_len))
   389  		}
   390  
   391  		if node_index%2 == 1 {
   392  			calculated_hash = self.hasher.hash_children(audit_path[pos], calculated_hash)
   393  			pos += 1
   394  		} else if node_index < last_node {
   395  			calculated_hash = self.hasher.hash_children(calculated_hash, audit_path[pos])
   396  			pos += 1
   397  		}
   398  		node_index /= 2
   399  		last_node /= 2
   400  	}
   401  
   402  	if pos < path_len {
   403  		return EMPTY_HASH, errors.New("Proof too long")
   404  	}
   405  	return calculated_hash, nil
   406  }
   407  
   408  func audit_path_length(index, tree_size uint64) int {
   409  	length := 0
   410  	last_node := tree_size - 1
   411  	for last_node > 0 {
   412  		if index%2 == 1 || index < last_node {
   413  			length += 1
   414  		}
   415  		index /= 2
   416  		last_node /= 2
   417  	}
   418  	return length
   419  }
   420  
   421  /*
   422  Verify the consistency between two root hashes.
   423  
   424      old_tree_size must be <= new_tree_size.
   425  
   426      Args:
   427          old_tree_size: size of the older tree.
   428          new_tree_size: size of the newer_tree.
   429          old_root: the root hash of the older tree.
   430          new_root: the root hash of the newer tree.
   431          proof: the consistency proof.
   432  
   433      Returns:
   434          True. The return value is enforced by a decorator and need not be
   435              checked by the caller.
   436  
   437      Raises:
   438          ConsistencyError: the proof indicates an inconsistency
   439              (this is usually really serious!).
   440          ProofError: the proof is invalid.
   441          ValueError: supplied tree sizes are invalid.
   442  */
   443  func (self *MerkleVerifier) VerifyConsistency(old_tree_size,
   444  	new_tree_size uint64, old_root, new_root common.Hash, proof []common.Hash) error {
   445  	old_size := old_tree_size
   446  	new_size := new_tree_size
   447  
   448  	if old_size > new_size {
   449  		return errors.New(fmt.Sprintf("Older tree has bigger size %d vs %d", old_size, new_size))
   450  	}
   451  	if old_root == new_root {
   452  		return nil
   453  	}
   454  	if old_size == 0 {
   455  		return nil
   456  	}
   457  	//assert o < old_size < new_size
   458  	/*
   459  		A consistency proof is essentially an audit proof for the node with
   460  		index old_size - 1 in the newer tree. The sole difference is that
   461  		the path is already hashed together into a single hash up until the
   462  		first audit node that occurs in the newer tree only.
   463  	*/
   464  	node := old_size - 1
   465  	last_node := new_size - 1
   466  
   467  	// while we are the right child, everything is in both trees, so move one level up
   468  	for node%2 == 1 {
   469  		node /= 2
   470  		last_node /= 2
   471  	}
   472  
   473  	lenp := len(proof)
   474  	pos := 0
   475  	var new_hash, old_hash common.Hash
   476  
   477  	if pos >= lenp {
   478  		return errors.New("Wrong proof length")
   479  	}
   480  	if node != 0 {
   481  		// compute the two root hashes in parallel.
   482  		new_hash = proof[pos]
   483  		old_hash = proof[pos]
   484  		pos += 1
   485  	} else {
   486  		// The old tree was balanced (2^k nodes), so we already have the first root hash
   487  		new_hash = old_root
   488  		old_hash = old_root
   489  	}
   490  
   491  	for node != 0 {
   492  		if node%2 == 1 {
   493  			if pos >= lenp {
   494  				return errors.New("Wrong proof length")
   495  			}
   496  			// node is a right child: left sibling exists in both trees
   497  			next_node := proof[pos]
   498  			pos += 1
   499  			old_hash = self.hasher.hash_children(next_node, old_hash)
   500  			new_hash = self.hasher.hash_children(next_node, new_hash)
   501  		} else if node < last_node {
   502  			if pos >= lenp {
   503  				return errors.New("Wrong proof length")
   504  			}
   505  			// node is a left child: right sibling only exists inthe newer tree
   506  			next_node := proof[pos]
   507  			pos += 1
   508  			new_hash = self.hasher.hash_children(new_hash, next_node)
   509  		}
   510  		// else node == last_node: node is a left child with no sibling in either tree
   511  
   512  		node /= 2
   513  		last_node /= 2
   514  	}
   515  
   516  	// Now old_hash is the hash of the first subtree. If the two trees have different
   517  	// height, continue the path until the new root.
   518  	for last_node != 0 {
   519  		if pos >= lenp {
   520  			return errors.New("Wrong proof length")
   521  		}
   522  		next_node := proof[pos]
   523  		pos += 1
   524  		new_hash = self.hasher.hash_children(new_hash, next_node)
   525  		last_node /= 2
   526  	}
   527  
   528  	/* If the second hash does not match, the proof is invalid for the given pair
   529  	If, on the other hand, the newer hash matches but the older one does not, then
   530  	the proof (together with the signatures on the hashes) is proof of inconsistency.
   531  	*/
   532  	if new_hash != new_root {
   533  		return errors.New(fmt.Sprintf(`Bad Merkle proof: second root hash does not match. 
   534  			Expected hash:%x, computed hash: %x`, new_root, new_hash))
   535  	} else if old_hash != old_root {
   536  		return errors.New(fmt.Sprintf(`Inconsistency: first root hash does not match."
   537  			"Expected hash: %x, computed hash:%x`, old_root, old_hash))
   538  	}
   539  
   540  	if pos != lenp {
   541  		return errors.New("Proof too long")
   542  	}
   543  
   544  	return nil
   545  }