github.com/mavryk-network/mvgo@v1.19.9/mavryk/blinded.go (about)

     1  // Copyright (c) 2020-2021 Blockwatch Data Inc.
     2  // Author: alex@blockwatch.cc
     3  
     4  package mavryk
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  
    10  	"github.com/mavryk-network/mvgo/base58"
    11  	"golang.org/x/crypto/blake2b"
    12  )
    13  
    14  // blinded pks
    15  // def genesis_commitments(wallets, blind):
    16  //     commitments = []
    17  //     for pkh_b58, amount in wallets.iteritems():
    18  //         # Public key hash corresponding to this Tezos address.
    19  //         pkh = bitcoin.b58check_to_bin(pkh_b58)[2:]
    20  //         # The redemption code is unique to the public key hash and deterministically
    21  //         # constructed using a secret blinding value.
    22  //         secret = secret_code(pkh, blind)
    23  //         # The redemption code is used to blind the pkh
    24  //         blinded_pkh = blake2b(pkh, 20, key=secret).digest()
    25  //         commitment = {
    26  //             'blinded_pkh': bitcoin.bin_to_b58check(blinded_pkh, magicbyte=16921055),
    27  //             'amount': amount
    28  //         }
    29  //         commitments.append(commitment)
    30  //     return commitments
    31  
    32  func BlindHash(hash, secret []byte) ([]byte, error) {
    33  	h, err := blake2b.New(20, secret)
    34  	if err != nil {
    35  		return nil, err
    36  	}
    37  	h.Write(hash)
    38  	return h.Sum(nil), nil
    39  }
    40  
    41  func BlindAddress(a Address, secret []byte) (Address, error) {
    42  	bh, err := BlindHash(a[1:], secret)
    43  	if err != nil {
    44  		return Address{}, err
    45  	}
    46  	return NewAddress(AddressTypeBlinded, bh), nil
    47  }
    48  
    49  // Checks if address a when blinded with secret equals blinded address b.
    50  func MatchBlindedAddress(a, b Address, secret []byte) bool {
    51  	bh, _ := BlindHash(a[1:], secret)
    52  	return bytes.Equal(bh, b[1:])
    53  }
    54  
    55  func DecodeBlindedAddress(addr string) (a Address, err error) {
    56  	ibuf := bufPool32.Get()
    57  	dec, ver, err2 := base58.CheckDecode(addr, 4, ibuf.([]byte))
    58  	if err2 != nil {
    59  		if err == base58.ErrChecksum {
    60  			err = ErrChecksumMismatch
    61  			return
    62  		}
    63  		err = fmt.Errorf("tezos: decoded address is of unknown format: %w", err2)
    64  		return
    65  	}
    66  	if len(dec) != 20 {
    67  		err = fmt.Errorf("tezos: decoded address hash has invalid length %d", len(dec))
    68  		return
    69  	}
    70  	if !bytes.Equal(ver, BLINDED_PUBLIC_KEY_HASH_ID) {
    71  		err = fmt.Errorf("tezos: decoded address %s is of unknown type %x", addr, ver)
    72  		return
    73  	}
    74  	a[0] = byte(AddressTypeBlinded)
    75  	copy(a[1:], dec)
    76  	bufPool32.Put(ibuf)
    77  	return
    78  }
    79  
    80  func EncodeBlindedAddress(hash, secret []byte) (string, error) {
    81  	bh, err := BlindHash(hash, secret)
    82  	if err != nil {
    83  		return "", err
    84  	}
    85  	return EncodeAddress(AddressTypeBlinded, bh), nil
    86  }