qortal/src/qora/block/GenesisBlock.java
catbref fe6cb4e366 Added Vote-on-poll transaction
* Added simple genesis block timestamp setting to help testing

* Fixed setting account's last reference

* Moved some Poll constants from CreatePollTransaction to Poll

* HSQLDB: added TYPE PollOptionIndex
* HSQLDB: added previous_option_index to VoteOnPollTransactions table to help orphaning
* HSQLDB: renamed "poll" to "poll_name" in same table
* HSQLDB: PollOptions now has additional option_index column

* Improved TransactionTests to allow for different genesis block timestamps.
* Also added VoteOnPollTransaction test
2018-06-29 10:29:18 +01:00

309 lines
16 KiB
Java

package qora.block;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import com.google.common.primitives.Bytes;
import com.google.common.primitives.Longs;
import data.block.BlockData;
import data.transaction.GenesisTransactionData;
import data.transaction.TransactionData;
import qora.account.GenesisAccount;
import qora.crypto.Crypto;
import qora.transaction.Transaction;
import repository.DataException;
import repository.Repository;
import settings.Settings;
public class GenesisBlock extends Block {
// Properties
private static final int GENESIS_BLOCK_VERSION = 1;
private static final byte[] GENESIS_REFERENCE = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1 }; // NOTE: Neither 64 nor 128 bytes!
private static final BigDecimal GENESIS_GENERATING_BALANCE = BigDecimal.valueOf(10_000_000L).setScale(8);
private static final byte[] GENESIS_GENERATOR_PUBLIC_KEY = GenesisAccount.PUBLIC_KEY; // NOTE: 8 bytes not 32 bytes!
public static final long GENESIS_TIMESTAMP = 1400247274336L; // QORA RELEASE: Fri May 16 13:34:34.336 2014 UTC
private static final byte[] GENESIS_GENERATOR_SIGNATURE = calcSignature();
private static final byte[] GENESIS_TRANSACTIONS_SIGNATURE = calcSignature();
// Constructors
public GenesisBlock(Repository repository) throws DataException {
super(repository, new BlockData(GENESIS_BLOCK_VERSION, GENESIS_REFERENCE, 0, BigDecimal.ZERO.setScale(8), GENESIS_TRANSACTIONS_SIGNATURE, 1,
Settings.getInstance().getGenesisTimestamp(), GENESIS_GENERATING_BALANCE, GENESIS_GENERATOR_PUBLIC_KEY, GENESIS_GENERATOR_SIGNATURE, null, null));
this.transactions = new ArrayList<Transaction>();
// Genesis transactions
addGenesisTransaction("QUD9y7NZqTtNwvSAUfewd7zKUGoVivVnTW", "7032468.191");
addGenesisTransaction("QVafvKkE5bZTkq8PcXvdaxwuLNN2DGCwYk", "1716146.084");
addGenesisTransaction("QV42QQP7frYWqsVq536g7zSk97fUpf2ZSN", "5241707.06");
addGenesisTransaction("QgkLTm5GkepJpgr53nAgUyYRsvmyHpb2zT", "854964.0816");
addGenesisTransaction("Qc8kN338XQULMBuUa6mTqL5tipvELDhzeZ", "769467.6734");
addGenesisTransaction("QQ81BA75jZcpjQBLZE1qcHrXV8ARC1DEec", "85496408.16");
addGenesisTransaction("QeoSe4DscWX4AFkNBCdm4WS1V7QkUFSQLP", "854968.3564");
addGenesisTransaction("Qdfu3Eh21ZVHNDY1xyNaFqTTEYscSmfSsm", "85496408.16");
addGenesisTransaction("QeDSr4abXKRg9j5hTN3TK9UGuH3umThZ42", "4445813.224");
addGenesisTransaction("QQKDuo1txYB9E2xim79YVR6SQ1ZbJtJtFX", "47023024.49");
addGenesisTransaction("QLeaeGr4CDA95FmeMtFh8okJRMLoq8Cge5", "170992816.3");
addGenesisTransaction("QSwN5oa8ZHWJmc6FeAJ8Xr1SHaEuSahw1J", "3419856.326");
addGenesisTransaction("QWnoGd4a7iXqQmNEpUtCb1x7nWgcya8QbE", "17056533.43");
addGenesisTransaction("QbJqhsJjcy3vkzsJ1kHvgn26pQF3sZEypc", "42705455.87");
addGenesisTransaction("QiBhBcseKzaDnHKyqEJs8z1Xx2rSb9XhBr", "141069073.5");
addGenesisTransaction("QTwYwxBhzivFEWY5yfzyz1pqhJ8XCroKwv", "85496408.16");
addGenesisTransaction("QfikxUU15Dy1oxbcDNEcLeU5cHvbrceq3A", "17099281.63");
addGenesisTransaction("QhdqBmKZeQ3Hg1XUuR5nKtAkw47tuoRi2q", "12824461.22");
addGenesisTransaction("QaVNyTqsTHA6JWMcqntcJf1u9c3qid76xH", "128244612.2");
addGenesisTransaction("QYaDa7bmgo5L9qkcfJKjhPPrQkvGjEoc7y", "85496408.16");
addGenesisTransaction("QQPddvWaYf4pbCyVHEVoyfC72EiaAv4JhT", "25648922.45");
addGenesisTransaction("QSQpTNtTZMwaDuNq56Jz73KHWXaey9JrT1", "26341443.35");
addGenesisTransaction("QVjcFWE6TnGePGJEtbNc1thwD2sgHBLvUV", "42940528.25");
addGenesisTransaction("Qga93mWNqTuJYx6o33vjUpFH7Cn4sxLyoG", "2564892.245");
addGenesisTransaction("QXyHKyQPJnb4ejyTkvS26x9sjWnhTTJ1Uc", "10259568.98");
addGenesisTransaction("QLurSSgJvW7WXHDFSobgfakgqXxjoZzwUH", "85496408.16");
addGenesisTransaction("QadxfiARcsmwzE93wqq82yXFi3ykM2qdtS", "79118376.11");
addGenesisTransaction("QRHhhtz3Cv9RPKB1QBBfkRmRfpXx8vkRa5", "22435418.54");
addGenesisTransaction("Qh8UnEs55n8jcnBaBwVtrTGkFFFBDyrMqH", "128757590.7");
addGenesisTransaction("QhF7Fu3f54CTYA7zBQ223NQEssi2yAbAcx", "258481290.8");
addGenesisTransaction("QPk9VB6tigoifrUYQrw4arBNk7i8HEgsDD", "128244612.2");
addGenesisTransaction("QXWJnEPsdtaLQAEutJFR4ySiMUJCWDzZJX", "85496408.16");
addGenesisTransaction("QVFs42gM4Cixf4Y5vDFvKKxRAamUPMCAVq", "85496408.16");
addGenesisTransaction("Qec5ueWc4rcBrty47GZfFSqvLymxvcycFm", "129091026.7");
addGenesisTransaction("QfYiztbDz1Nb9EMhgHidLycvuPN8HEcHEj", "128244612.2");
addGenesisTransaction("QPdWsZtaZcAKqk2HWVhEVbws4qG5KUTXmg", "179285967.9");
addGenesisTransaction("QVkNs5NcwQpsrCXpWzuMXkMehJr5mkvLVy", "8558190.456");
addGenesisTransaction("Qg19DzyEfyZANx6JLy4GrSGF5LuZ2MLqyZ", "42748204.08");
addGenesisTransaction("Qf3A8L5WJNHt1xZxmayrTp2d5owzdkcxM6", "50519827.58");
addGenesisTransaction("QeKR4W6qkFJGF7Hmu7rSUzTSQiqJzZLXdt", "10216820.77");
addGenesisTransaction("QWg7T5i3uBY3xeBLFTLYYruR15Ln11vwo4", "170992816.3");
addGenesisTransaction("QUYdM5fHECPZxKQQAmoxoQa2aWg8TZYfPw", "85496408.16");
addGenesisTransaction("QjhfEZCgrjUbnLRnWqWxzyYqKQpjjxkuA8", "86665653.61");
addGenesisTransaction("QMA53u3wrzDoxC57CWUJePNdR8FoqinqUS", "85496408.16");
addGenesisTransaction("QSuCp6mB5zNNeJKD62aq2hR9h84ks1WhHf", "161588211.4");
addGenesisTransaction("QS2tCUk7GQefg4zGewwrumxSPmN6fgA7Xc", "170992816.3");
addGenesisTransaction("Qcn6FZRxAgp3japtvjgUkBY6KPfbPZMZtM", "170992816.3");
addGenesisTransaction("QZrmXZkRmjV2GwMt72Rr1ZqHJjv8raDk5J", "17099281.63");
addGenesisTransaction("QeZzwGDfAHa132jb6r4rQHbgJstLuT8QJ3", "255875360.3");
addGenesisTransaction("Qj3L139sMMuFvvjKQDwRnoSgKUnoMhDQs5", "76946767.34");
addGenesisTransaction("QWJvpvbFRZHu7LRbY5MjzvrMBgzJNFYjCX", "178251461.4");
addGenesisTransaction("QRyECqW54ywKVt4kZTEXyRY17aaFUaxzc4", "8772355.539");
addGenesisTransaction("QgpH3K3ArkQTg15xjKqGq3BRgE3aNH9Q2P", "46766535.26");
addGenesisTransaction("QVZ6pxi8e3K3S44zLbnrLSLwSoYT8CWbwV", "233172022.2");
addGenesisTransaction("QNbA69dbnmwqJHLQeS9v63hSLZXXGkmtC6", "46626632.05");
addGenesisTransaction("QgzudSKbcLUeQUhFngotVswDSkbU42dSMr", "83786479.99");
addGenesisTransaction("QfkQ2UzKMBGPwj8Sm31SArjtXoka1ubU3i", "116345066.7");
addGenesisTransaction("QgxHHNwawZeTmQ3i5d9enchi4T9VmzNZ5k", "155448014.8");
addGenesisTransaction("QMNugJWNsLuV4Qmbzdf8r8RMEdXk5PNM69", "155448014.8");
addGenesisTransaction("QVhWuJkCjStNMV4U8PtNM9Qz4PvLAEtVSj", "101041209.6");
addGenesisTransaction("QXjNcckFG9gTr9YbiA3RrRhn3mPJ9zyR4G", "3108960.297");
addGenesisTransaction("QThnuBadmExtxk81vhFKimSzbPaPcuPAdm", "155448014.8");
addGenesisTransaction("QRc6sQthLHjfkmm2BUhu74g33XtkDoB7JP", "77773983.95");
addGenesisTransaction("QcDLhirHkSbR4TLYeShLzHw61B8UGTFusk", "23317202.22");
addGenesisTransaction("QXRnsXE6srHEf2abGh4eogs2mRsmNiuw6V", "5440680.519");
addGenesisTransaction("QRJmEswbDw4x1kwsLyxtMS9533fv5cDvQV", "3886200.371");
addGenesisTransaction("Qg43mCzWmFVwhVfx34g6shXnSU7U7amJNx", "6217920.593");
addGenesisTransaction("QQ9PveFTW64yUcXEE6AxhokWCwhmn8F2TD", "8549640.816");
addGenesisTransaction("QQaxJuTkW5XXn4DhhRekXpdXaWcsxEfCNG", "3886200.371");
addGenesisTransaction("QifWFqW8XWL5mcNxtdr5z1LVC7XUu9tNSK", "3116732.697");
addGenesisTransaction("QavhBKRN4vuyzHNNqcWxjcohRAJNTdTmh4", "154670774.8");
addGenesisTransaction("QMQyR3Hybof8WpQsXPxh19AZFCj4Z4mmke", "77724007.42");
addGenesisTransaction("QbT3GGjp1esTXtowVk2XCtBsKoRB8mkP61", "77724007.42");
addGenesisTransaction("QT13tVMZEtbrgJEsBBcTtnyqGveC7mtqAb", "23317202.22");
addGenesisTransaction("QegT2Ws5YjLQzEZ9YMzWsAZMBE8cAygHZN", "12606834");
addGenesisTransaction("QXoKRBJiJGKwvdA3jkmoUhkM7y6vuMp2pn", "65117173.41");
addGenesisTransaction("QY6SpdBzUev9ziqkmyaxESZSbdKwqGdedn", "89382608.53");
addGenesisTransaction("QeMxyt1nEE7tbFbioc87xhiKb4szx5DsjY", "15544801.48");
addGenesisTransaction("QcTp3THGZvJ42f2mWsQrawGvgBoSHgHZyk", "39639243.78");
addGenesisTransaction("QjSH91mTDN6TeV1naAcfwPhmRogufV4n1u", "23317202.22");
addGenesisTransaction("QiFLELeLm2TFWsnknzje51wMdt3Srkjz8g", "1554480.148");
addGenesisTransaction("QhxtJ3vvhsvVU9x2j5n2R3TXzutfLMUvBR", "23317202.22");
addGenesisTransaction("QUtUSNQfqexZZkaZ2s9LcpqjnTezPTnuAx", "15544801.48");
addGenesisTransaction("Qg6sPLxNMYxjEDGLLaFkkWx6ip3py5fLEt", "777240.0742");
addGenesisTransaction("QeLixskYbdkiAHmhBVMa2Pdi85YPFqw3Ed", "38862003.71");
addGenesisTransaction("Qary17o9qvZ2fifiVC8tF5zoBJm79n18zA", "3893972.772");
addGenesisTransaction("QLvCWDGwzwpR29XgiThMGDX2vxyFW5rFHB", "8790585.239");
addGenesisTransaction("Qgc77fSoAoUSVJfq62GxxTin6dBtU7Y6Hb", "194310018.5");
addGenesisTransaction("QPmPKjwPLCuRei6abuhMtMocxAEeSuLVcv", "23317202.22");
addGenesisTransaction("QcGfZePUN7JHs9WEEkJhXGzALy4JybiS3N", "194224522.1");
addGenesisTransaction("QSeXGwk7eQjR8j7bndJST19qWtM2qnqL1u", "38862003.71");
addGenesisTransaction("QU9i68h71nKTg4gwc5yJHzNRQdQEswP7Kn", "139592317.3");
addGenesisTransaction("QdKrZGCkwXSSeXJhVA1idDXsA4VFtrjPHN", "15544801.48");
addGenesisTransaction("QiYJ2B797xFpWYFu4XWivhGhyPXLU7S5Mr", "77724007.42");
addGenesisTransaction("QWxqtsNXUWSjYns2wdngh4WBSWQzLoQHvx", "232613963.9");
addGenesisTransaction("QTAGfu4FpTZ1bnvnd17YPtB3zabxfWKNeM", "101041209.6");
addGenesisTransaction("QPtRxchgRdwdnoZRwhiAoa77AvVPNSRcQk", "114254290.9");
addGenesisTransaction("QMcfoVc9Jat2pMFLHcuPEPnY6p6uBK6Dk7", "77724007.42");
addGenesisTransaction("Qi84KosdwSWHZX3qz4WcMgqYGutBmj14dd", "15544801.48");
addGenesisTransaction("QjAtcHsgig2tvdGr5tR4oGmRarhuojrAK1", "2883560.675");
addGenesisTransaction("QPJPNLP2NMHu5athB7ydezdTA6zviCV378", "6373368.608");
addGenesisTransaction("QfVLpmLbuUnA1JEe9FmeUAzihoBvqYDp8B", "15544801.48");
addGenesisTransaction("QVVFdy6VLFqAFCb6XSBJLLZybiKgfgDDZV", "10725913.02");
addGenesisTransaction("QVFXyeG1xpAR8Xg3u7oAmW8unueGAfeaKi", "31221733.78");
addGenesisTransaction("QdtQtrM1h3TLtwAGCNyoTrW5HyiPRLhrPq", "138426457.2");
addGenesisTransaction("QMukUMr84Mi2niz6rdhEJMkKJBve7uuRfe", "116586011.1");
addGenesisTransaction("QZR8c7dmfwqGPujebFH1miQToJZ4JQfU1X", "217938116.8");
addGenesisTransaction("QVV5Uu8eCxufTrBtquDKA96d7Kk8S4V7yX", "40091961.25");
addGenesisTransaction("QY9YdgfTEUFvQ2UJszGS63qkwdENkW1PQ5", "154670774.8");
addGenesisTransaction("QNgiswyhVyNJG4UMzvoSf29wDvGZqqs7WG", "11658601.11");
addGenesisTransaction("QabjgFiY34oihNkUcy9hpFjQdCaypCShMe", "54406805.19");
addGenesisTransaction("QionidPRekdshCTRL3c7idWWRAqGYcKaFN", "7772400.742");
addGenesisTransaction("QcJdBJiVgiNBNg6ZwZAiEfYDMi5ZTQaYAa", "81386689.86");
addGenesisTransaction("QNc8XMpPwM1HESwB7kqw8HoQ5sK2miZ2un", "190423818.2");
addGenesisTransaction("QUP1SeaNw7CvCnmDp5ai3onWYwThS4GEpu", "3886200.371");
addGenesisTransaction("QinToqEztNN1TsLdQEuzTHh7vUrEo6JTU2", "102440241.8");
addGenesisTransaction("QcLJYLV4RD4GmPcoNnh7dQrWeYgiiPiqFQ", "32644083.11");
addGenesisTransaction("QdYdYGYfgmMX4jQNWMZqLr81R3HdnuiKkv", "76169527.27");
addGenesisTransaction("Qi62mUW5zfJhgRL8FRmCpjSCCnSKtf76S6", "76169527.27");
addGenesisTransaction("QgFkxqQGkLW6CD95N2zTnT1PPqb9nxWp6b", "76169527.27");
addGenesisTransaction("QfNUBudYsrrq27YqiHGLUg6BtG52W1W1ci", "15544801.48");
addGenesisTransaction("QPSFoexnGoMH7EPdg72dM7SvqA7d4M2cu7", "37307523.56");
addGenesisTransaction("QQxt5WMvoJ2TNScAzcoxHXPnLTeQ43nQ7N", "21995894.1");
addGenesisTransaction("QicpACxck2oDYpzP8iWRQYD4oirCtvjok9", "93268808.9");
addGenesisTransaction("QVTJkdQkTGgqEED9kAsp4BZbYNJqWfhgGw", "153909079.5");
addGenesisTransaction("QQL5vCkhpXnP9F4wqNiBQsNaCocmRcDSUY", "15512934.64");
addGenesisTransaction("QSvEex3p2LaZCVBaCyL8MpYsEpHLwed17r", "155448014.8");
addGenesisTransaction("Qb3Xv96GucQpBG8n96QVFgcs2xXsEWW4CE", "38862003.71");
addGenesisTransaction("QdRua9MqXufALpQFDeYiQDYk3EBGdwGXSx", "230303229.1");
addGenesisTransaction("Qh16Umei91JqiHEVWV8AC6ED9aBqbDYuph", "231073474");
addGenesisTransaction("QMu6HXfZCnwaNmyFjjhWTYAUW7k1x7PoVr", "231073474");
addGenesisTransaction("QgcphUTiVHHfHg8e1LVgg5jujVES7ZDUTr", "115031531");
addGenesisTransaction("QbQk9s4j4EAxAguBhmqA8mdtTct3qGnsrx", "138348733.2");
addGenesisTransaction("QT79PhvBwE6vFzfZ4oh5wdKVsEazZuVJFy", "6360421.343");
}
// More information
public static boolean isGenesisBlock(BlockData blockData) {
if (blockData.getHeight() != 1)
return false;
// Validate block signature
if (!Arrays.equals(GENESIS_GENERATOR_SIGNATURE, blockData.getGeneratorSignature()))
return false;
// Validate transactions signature
if (!Arrays.equals(GENESIS_TRANSACTIONS_SIGNATURE, blockData.getTransactionsSignature()))
return false;
return true;
}
// Processing
@Override
public boolean addTransaction(TransactionData transactionData) {
// The genesis block has a fixed set of transactions so always refuse.
return false;
}
private void addGenesisTransaction(String recipient, String amount) {
this.transactions.add(Transaction.fromData(this.repository,
new GenesisTransactionData(recipient, new BigDecimal(amount).setScale(8), this.getBlockData().getTimestamp())));
this.blockData.setTransactionCount(this.blockData.getTransactionCount() + 1);
}
/**
* Refuse to calculate genesis block's generator signature!
* <p>
* This is not possible as there is no private key for the genesis account and so no way to sign data.
* <p>
* <b>Always throws IllegalStateException.</b>
*
* @throws IllegalStateException
*/
@Override
public void calcGeneratorSignature() {
throw new IllegalStateException("There is no private key for genesis account");
}
/**
* Refuse to calculate genesis block's transactions signature!
* <p>
* This is not possible as there is no private key for the genesis account and so no way to sign data.
* <p>
* <b>Always throws IllegalStateException.</b>
*
* @throws IllegalStateException
*/
@Override
public void calcTransactionsSignature() {
throw new IllegalStateException("There is no private key for genesis account");
}
/**
* Generate genesis block generator/transactions signature.
* <p>
* This is handled differently as there is no private key for the genesis account and so no way to sign data.
* <p>
* Instead we return the SHA-256 digest of the block, duplicated so that the returned byte[] is the same length as normal block signatures.
*
* @return byte[]
*/
private static byte[] calcSignature() {
byte[] digest = Crypto.digest(getBytesForSignature());
return Bytes.concat(digest, digest);
}
private static byte[] getBytesForSignature() {
try {
// Passing expected size to ByteArrayOutputStream avoids reallocation when adding more bytes than default 32.
// See below for explanation of some of the values used to calculated expected size.
ByteArrayOutputStream bytes = new ByteArrayOutputStream(8 + 64 + 8 + 32);
/*
* NOTE: Historic code had genesis block using Longs.toByteArray() compared to standard block's Ints.toByteArray. The subsequent
* Bytes.ensureCapacity(versionBytes, 0, 4) did not truncate versionBytes back to 4 bytes either. This means 8 bytes were used even though
* VERSION_LENGTH is set to 4. Correcting this historic bug will break genesis block signatures!
*/
bytes.write(Longs.toByteArray(GENESIS_BLOCK_VERSION));
/*
* NOTE: Historic code had the reference expanded to only 64 bytes whereas standard block references are 128 bytes. Correcting this historic bug
* will break genesis block signatures!
*/
bytes.write(Bytes.ensureCapacity(GENESIS_REFERENCE, 64, 0));
bytes.write(Longs.toByteArray(GENESIS_GENERATING_BALANCE.longValue()));
// NOTE: Genesis account's public key is only 8 bytes, not the usual 32, so we have to pad.
bytes.write(Bytes.ensureCapacity(GENESIS_GENERATOR_PUBLIC_KEY, 32, 0));
return bytes.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public boolean isSignatureValid() {
// Validate block signature
if (!Arrays.equals(GENESIS_GENERATOR_SIGNATURE, this.getBlockData().getGeneratorSignature()))
return false;
// Validate transactions signature
if (!Arrays.equals(GENESIS_TRANSACTIONS_SIGNATURE, this.getBlockData().getTransactionsSignature()))
return false;
return true;
}
@Override
public ValidationResult isValid() throws DataException {
// Check there is no other block in DB
if (this.repository.getBlockRepository().getBlockchainHeight() != 0)
return ValidationResult.BLOCKCHAIN_NOT_EMPTY;
// Validate transactions
for (Transaction transaction : this.getTransactions())
if (transaction.isValid() != Transaction.ValidationResult.OK)
return ValidationResult.TRANSACTION_INVALID;
return ValidationResult.OK;
}
}