Bitcoinolog - Reason about Bitcoin addresses with Prolog



Elliptic Curves


An elliptic curve over the finite field Fp is a set of points (x,y) that satisfy the equation:
y2 = x3 + ax + b    mod p
Such a curve is defined by the parameters a, b, p. In addition, a generator point G is given.

An elliptic curve is an Abelian variety: There is an operation called addition of points, which forms a group, and multiplication of points by a scalar. The maximum number of different points that can be obtained by multiplying the generator by a scalar is called the order of the curve.

Elliptic curves can be used for encryption and signing. The signature algorithm based on elliptic curves is called ECDSA.

A Prolog library for rudimentary reasoning about elliptic curves is available: ecclog.pl

Note the use of declarative integer arithmetic to allow declarative debugging.

Bitcoin

Bitcoin is a cryptocurrency. It uses ECDSA for signing transactions.

A Prolog library for reasoning about Bitcoin addresses is available: bitcoinolog.pl

You need SWI-Prolog 7.5.10 or later to run it.

Bitcoinolog uses library(crypto) to compute various hashes, and to reason about the named curve secp256k1, which is used by Bitcoin.

Alternatively, you can also use ecclog.pl for the required operations over elliptic curves.

Use cases of Bitcoinolog

Here are a few use cases of bitcoinolog.pl:
  1. Offline Bitcoin wallet creation
    To generate a public/private key pair, you can use the Prolog predicates new_private_key/1 and private_key_to_public_key/2:
    ?- new_private_key(PrivateKey),
       private_key_to_public_key(PrivateKey, PublicKey).
    PrivateKey = 87443244391001342896527975361878627920717378785443876955045552084285386647786,
    PublicKey = '020766fd4ffbbfa2086a96b335ba6eff24b58e4819936f8dc9d4002dabc9b11405'.
            
    Note that in ECDSA, a private key is an integer, and the corresponding public key is a point on the curve. In the above, the so-called compressed encoding of the public key is used, which is recommended for Bitcoin as of version 0.6.
  2. Convert public keys to Bitcoin addresses
    As transaction targets, Bitcoin uses addresses that are derived from public keys. You can use the Prolog predicate public_key_to_address/2 to convert a public key as shown above to its corresponding address:
    ?- public_key_to_address('020766fd4ffbbfa2086a96b335ba6eff24b58e4819936f8dc9d4002dabc9b11405', Address).
    Address = '1FVRX63gUDxkQ25C7ivMa27C9nT1DUafmD'.
            
  3. Export private keys to Wallet Import Format (WIF)
    To use those keys that you generate with Bitcoinolog also with other programs, you can export private keys to Wallet Import Format (WIF) via the Prolog predicate private_key_to_wif/2. For example:
    ?- private_key_to_wif(87443244391001342896527975361878627920717378785443876955045552084285386647786, WIF).
    WIF = 'L3hWTxRVjB9qzgdWQwcgWtSJZMzNnNvnWvajHstPuSPwzx2H4sbp'.
            
Here is a Prolog query that indefinitely generates private keys and corresponding Bitcoin addresses:
?- repeat,
    new_private_key(PrivateKey),
    private_key_to_wif(PrivateKey, WIF),
    private_key_to_public_key(PrivateKey, PublicKey),
    public_key_to_address(PublicKey, Address),
    portray_clause((address_key(A, K) :- A=Address, K=WIF)),
    false.
    
It yields output like:
address_key(A, B) :-
        A='1Fo9WojzYwhfjqQKQDWQyehxWyMJVhySBA',
        B='Ky91qbBbHnrozFkJRFBA6KQG8hzctWPRKGWd3kRxX1ajVKEzmrSp'.
address_key(A, B) :-
        A='1HQXkmyUPnhXdzk1gacXzCLx3mV6843ncN',
        B='L3yC2Bf2Ko3nLW61vkhqJia18QkTJb3KGxQJ6fWSNa4o7x71JNXU'.
address_key(A, B) :-
        A='1FMuyjrVi7DUDFrThZNcNkBG8bq1YNfqiG',
        B='Kxmburb4FiNQHnaWf6e8mTDJUnCaUzuXaHM5TeeKiTjpT2bPCNBR'.
address_key(A, B) :-
        A='1FeQG4oBfWA3HCaiEKyeaGWQRLazwzmaUy',
        B='L4EresJ9xiC7JzbXV3gU7SpUsenqq12ZxonYFYHr6c9GSt3RKyVA'.
etc.
    
The source code of Bitcoinolog is also available from a public git repository: github.com/triska/bitcoinolog


More about Prolog: The Power of Prolog


Main page