As I said before, version 1.0 of the anti-pool algorithm PoW described above has a substantial disadvantage. Miners can perform the first and the second cycles once and after that they can skip these cycles and find the block which meets the requirements, iterrating over the
sign_nonce digit of the ECDSA scheme based on the secp256k1 elliptic curve, using special equipment. Thus, some miners may obtain multiple superiority over miners who do not have ASIC. Therefore, I propose the following solution which avoids this disadvantage.
Anti-pool algorithm PoW - Version 2.0
The main problem with the implementation of version 1.0 is the inability to sign a hash (digit) equally and single-vary without loss of security and safety, because the
sign_nonce digit of the ECDSA secp256k1 scheme must be a random number unknown to a third party. Otherwise it is very easy to calculate the R digit and then the private key K from the S digit. That is why the primary task for solving the described problem is to discover such asymmetric cryptography which allows to sign a hash (digit) securely enough and gives the same and equal result.
To implement version 2.0 of the anti-pool algorithm PoW, I propose to use RSA (Rivest-Shamir-Adleman) asymmetric cryptography which is widely adopted, for example, in the well-known PGP (Pretty Good Privacy) application. In this cryptography, to enhance security, a digit (hash), which is the plain message M, is usually encapsualted into another (larger) digit using a Probabilistic Signature Scheme (PSS) before signing. In this scheme the so-called "salt" that is a random digit (in fact,
sign_nonce) is used by default, but this parameter may be omitted. Thus, the PSS scheme without the "salt" gives an equal result if the same hash (digit) is being signed. Of course, a signature without a "salt" is less secure but not significantly.
An example implementation of the algorithm
To test version 2.0 of the anti-pool algorithm PoW, you can use the well-known OpenSSL application. At present time, RSA cryptography typically uses a public exponent E, equal to 65537, and a public key N having a length of 2048 bits (256 bytes).
To generate an RSA key pair:1) Create a private key consisting of two primes P and Q, each of which has a length of 1024 bits (128 bytes):
openssl genrsa -out private_key.pem 2048
2) Calculate the public key N that has a length of 2048 bits (256 bytes). In fact, this is a multiplication of two primes P and Q.
openssl rsa -in private_key.pem -outform PEM -pubout -out public_key.pem
To sign the header hash using the RSA-PSS scheme:1) Calculate the block header hash through an ASIC-resistant algorithm and save the result which has a length of 256 bits (32 bytes) into a text file, for example, "block_header_hash.txt".
2) Sign the block header hash and save the RSA signature into the file "block_header_hash.txt.sig":
openssl dgst -sha256 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:0
-sign private_key.pem -out block_header_hash.txt.sig block_header_hash.txt
It should be noted that the
rsa_pss_saltlen parameter is equal to zero, therefore the result of executing this command is always the same and single-vary if the input data of the file "block_header_hash.txt" are not changed.
In version 2.0, the block header structure contains 7 fields:- 1) block_version (4 byte)
- 2) previous_block_header_hash (32 bytes)
- 3) block_timestamp (8 bytes)
- 4) transaction_count (4 bytes)
- 5) merkle_root (32 bytes)
- 6) required_leading_zero_bit_count_in_rsa_sign (1 byte)
- 7) block_nonce (8 bytes)
The signature
block_header_hash_rsa_sign_without_salt (256 bytes) is written further. The total size of the block header size with the RSA signature is 89 + 256 = 345 bytes.
To implement version 2.0 of the anti-pool algorithm PoW, transactions must simultaneously support addresses based on ECDSA and RSA cryptographies. Suppose Bitcoin as an example. In this case the new OP_CHECKSIGN_RSA should be introduced. This function verifies the last two values from the stack (signature S and public key N) using the PSS scheme (with "salt") and checks the validity of the transaction input script.
openssl dgst -sha256 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1
-sign private_key.pem -out transaction.txt.sig transaction.txt
In this command the
rsa_pss_saltlen parameter, which is -1, indicates that the length of "salt" is equal to the length of the SHA256 hash (that is, 32 bytes), so security and safety will be at high levels.
It is important that a valid COINBASE transaction should contain one output and send a reward for mining and all transactions fees included in the block to the address which is the RSA public key. Other miners will verify the signature of the block header hash using this key. The input script of the COINBASE transaction may be used, for example, for votings, annoucements and other marks.
The output script "scriptPubKey" of the COINBASE transaction must be in the PAY-TO-RSA-PUBKEY format:
OP_DUP OP_EQUALVERIFY OP_CHECKSIG_RSA
Accordingly, the signature S and the public key N must be defined in the input script of the futher transaction in order to spend this output in the future:
Conclusion
The presented version 2.0 of the anti-pool algorithm PoW avoids the substantial disadvantage of version 1.0 and also adds some features. The RSA-PSS scheme without "salt" will not allow miners to iterate over the
sign_nonce digit instead of the iterating over the
block_nonce digit as was possible in version 1.0 of the anti-pool algorithm PoW, so they will be forced to calculate the block header hash through an ASIC-resistant algorithm many times. In addition, administrators of botnets and websites are unlikely to install hidden JS-scripts, because the RSA private key (which is the P and Q digits) is required at each mining iteration.
The described algorithm can provide resistance to ASIC, decrease the centralization of mining and, as a result, reduce the possibility of transaction censorship by a small circle of people.