'Merkle Proof in python using Keccak256

I'm trying to create a whitelist for an NFT using a Merkle tree to save on gas costs. I saw a great implementation here, in javascript, but I would like to do it in Python. Doesn't seem like I'm able to create a merkle tree using keccak hashing, which I think it necessary to do for the etheruem blockchain. Open-zeppelin's MerkleProof.sol uses kaccack hashing to verify a leaf. I'm guessing I can just change this to use sha256 instead, but I don't like these quick fixes.

Here is what I tried below:

from pymerkle import MerkleTree
from Crypto.Hash import keccak
from scripts.helpful_scripts import get_account
from brownie import NFTCollectible, network, config


def hash(address):
    k = keccak.new(digest_bits=256)
    k.update(address.encode("utf_8"))
    return k.hexdigest()


def main():
    account = get_account()
    nft_collectible = NFTCollectible[-1]

    whitelistedAddresses = [
        "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
        "0x78D6CF3DEF45AF458442E787FE6E64A03750AB94",
        "0xA7B0E4CF55AF900F6E80D619AE1E00965044BC4E",
        "0x38C4278F42A26A588176017F5E4F6ED831835EA2",
        "0x9F9A0AA0507FE79CA1FF8F26A8D84BD8BB0EC9DF",
        "0xDABF258F5619942D19AD87C3472FABE893B26D7D",
        "0xD30ED9C457C7D32F3F7B949964191E4084C53F66",
    ]

    leafNodes = []
    for address in whitelistedAddresses:
        hashedAddress = hash(address)
        leafNodes.append(hashedAddress)

    merkleTree = MerkleTree()
    for leaf in leafNodes:
        merkleTree.update(leaf)

    print(merkleTree)

    root = merkleTree.rootHash.decode("utf-8")
    print(root)

It does return a Merkle tree, but hashed using sha256 as pymerkle doesn't have keccak hashing. (The keccak library above is used for hashing the wallets). Running this returns a different Merkle tree than the one in JS. I'm not even sure if the difference is because of the hashing.

This is how I would like to verify in solidity:

        // using merkle tree for whitelist
        bytes32 leaf = keccak256(abi.encodePacked(msg.sender)); // this will work good since the wallets are hashed by keccak
        require(
            MerkleProof.verify(merkleProof, whitelistedMerkleRoot, leaf), // this will fail
            "Not on the whitelist"
        );


Solution 1:[1]

Did you try overriding existing Pymerkle methods in order to be able to use a new encoding option ?

You would need to include type here https://github.com/fmerg/pymerkle/blob/6d4c9eb502fe7aa6117123e7f1ab8cf84a38e7b4/pymerkle/hashing/machine.py#L9

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Diego Iruretagoyena