Esempio n. 1
0
  @Test
  public void validateGenesisBlock() {
    // CREATE EMPTY DATABASE
    DBSet databaseSet = DBSet.createEmptyDatabaseSet();

    // CREATE GENESIS BLOCK
    Block genesisBlock = new GenesisBlock();

    // CHECK IF VALID
    assertEquals(true, genesisBlock.isValid(databaseSet));

    // ADD INVALID GENESIS TRANSACTION
    Transaction transaction =
        new GenesisTransaction(
            new Account("XUi2oga2pnGNcZ9es6pBqxydtRZKWdkL2g"),
            BigDecimal.valueOf(-1000).setScale(8),
            NTP.getTime());
    genesisBlock.addTransaction(transaction);

    // CHECK IF INVALID
    assertEquals(false, genesisBlock.isValid(databaseSet));

    // CREATE NEW BLOCK
    genesisBlock = new GenesisBlock();

    // CHECK IF VALID
    assertEquals(true, genesisBlock.isValid(databaseSet));

    // PROCESS
    genesisBlock.process(databaseSet);

    // CHECK IF INVALID
    assertEquals(false, genesisBlock.isValid(databaseSet));
  }
Esempio n. 2
0
  public void orphan(DBSet db) {
    // ORPHAN AT TRANSACTIONS
    LinkedHashMap<Tuple2<Integer, Integer>, AT_Transaction> atTxs =
        DBSet.getInstance().getATTransactionMap().getATTransactions(this.getHeight(db));

    Iterator<AT_Transaction> iter = atTxs.values().iterator();

    while (iter.hasNext()) {
      AT_Transaction key = iter.next();
      Long amount = key.getAmount();
      if (key.getRecipientId() != null
          && !Arrays.equals(key.getRecipientId(), new byte[AT_Constants.AT_ID_SIZE])
          && !key.getRecipient().equalsIgnoreCase("1")) {
        Account recipient = new Account(key.getRecipient());
        recipient.setConfirmedBalance(
            recipient.getConfirmedBalance(db).subtract(BigDecimal.valueOf(amount, 8)), db);
        if (Arrays.equals(recipient.getLastReference(db), new byte[64])) {
          recipient.removeReference(db);
        }
      }
      Account sender = new Account(key.getSender());
      sender.setConfirmedBalance(
          sender.getConfirmedBalance(db).add(BigDecimal.valueOf(amount, 8)), db);
    }

    // ORPHAN TRANSACTIONS
    this.orphanTransactions(this.getTransactions(), db);

    // REMOVE FEE
    BigDecimal blockFee = this.getTotalFee();
    if (blockFee.compareTo(BigDecimal.ZERO) == 1) {
      // UPDATE GENERATOR BALANCE WITH FEE
      this.generator.setConfirmedBalance(
          this.generator.getConfirmedBalance(db).subtract(blockFee), db);
    }

    // DELETE AT TRANSACTIONS FROM DB
    db.getATTransactionMap().delete(this.getHeight(db));

    // DELETE TRANSACTIONS FROM FINAL MAP
    db.getTransactionFinalMap().delete(this.getHeight(db));

    // DELETE BLOCK FROM DB
    db.getBlockMap().delete(this);

    // SET PARENT AS LAST BLOCK
    db.getBlockMap().setLastBlock(this.getParent(db));

    for (Transaction transaction : this.getTransactions()) {
      // ADD ORPHANED TRANASCTIONS BACK TO DATABASE
      db.getTransactionMap().add(transaction);

      // DELETE ORPHANED TRANASCTIONS FROM PARENT DATABASE
      db.getTransactionParentMap().delete(transaction.getSignature());
    }
  }
Esempio n. 3
0
  @Test
  public void orphanBlock() {
    // CREATE EMPTY MEMORY DATABASE
    DBSet databaseSet = DBSet.createEmptyDatabaseSet();

    // PROCESS GENESISBLOCK
    GenesisBlock genesisBlock = new GenesisBlock();
    genesisBlock.process(databaseSet);

    // CREATE KNOWN ACCOUNT
    byte[] seed = Crypto.getInstance().digest("test".getBytes());
    byte[] privateKey = Crypto.getInstance().createKeyPair(seed).getA();
    PrivateKeyAccount generator = new PrivateKeyAccount(privateKey);

    // PROCESS GENESIS TRANSACTION TO MAKE SURE GENERATOR HAS FUNDS
    Transaction transaction =
        new GenesisTransaction(generator, BigDecimal.valueOf(1000).setScale(8), NTP.getTime());
    transaction.process(databaseSet);

    // GENERATE NEXT BLOCK
    BlockGenerator blockGenerator = new BlockGenerator();
    Block block = blockGenerator.generateNextBlock(databaseSet, generator, genesisBlock);

    // FORK
    DBSet fork = databaseSet.fork();

    // GENERATE PAYMENT 1
    Account recipient = new Account("XUi2oga2pnGNcZ9es6pBqxydtRZKWdkL2g");
    long timestamp = block.getTimestamp();
    byte[] signature =
        PaymentTransaction.generateSignature(
            databaseSet,
            generator,
            recipient,
            BigDecimal.valueOf(100).setScale(8),
            BigDecimal.valueOf(1).setScale(8),
            timestamp);
    Transaction payment1 =
        new PaymentTransaction(
            generator,
            recipient,
            BigDecimal.valueOf(100).setScale(8),
            BigDecimal.valueOf(1).setScale(8),
            timestamp,
            generator.getLastReference(databaseSet),
            signature);
    payment1.process(fork);
    block.addTransaction(payment1);

    // GENERATE PAYMENT 2
    Account recipient2 = new Account("XLPYYfxKEiDcybCkFA7jXcxSdePMMoyZLt");
    signature =
        PaymentTransaction.generateSignature(
            fork,
            generator,
            recipient2,
            BigDecimal.valueOf(100).setScale(8),
            BigDecimal.valueOf(1).setScale(8),
            timestamp);
    Transaction payment2 =
        new PaymentTransaction(
            generator,
            recipient2,
            BigDecimal.valueOf(100).setScale(8),
            BigDecimal.valueOf(1).setScale(8),
            timestamp,
            generator.getLastReference(fork),
            signature);
    block.addTransaction(payment2);

    // ADD TRANSACTION SIGNATURE
    byte[] transactionsSignature = blockGenerator.calculateTransactionsSignature(block, generator);
    block.setTransactionsSignature(transactionsSignature);

    // CHECK VALID
    assertEquals(true, block.isSignatureValid());
    assertEquals(true, block.isValid(databaseSet));

    // PROCESS BLOCK
    block.process(databaseSet);

    // ORPHAN BLOCK
    block.orphan(databaseSet);

    // CHECK BALANCE GENERATOR
    assertEquals(
        true, generator.getConfirmedBalance(databaseSet).compareTo(BigDecimal.valueOf(1000)) == 0);

    // CHECK LAST REFERENCE GENERATOR
    assertEquals(
        true, Arrays.equals(generator.getLastReference(databaseSet), transaction.getSignature()));

    // CHECK BALANCE RECIPIENT
    assertEquals(
        true, recipient.getConfirmedBalance(databaseSet).compareTo(BigDecimal.valueOf(1000)) == 0);

    // CHECK LAST REFERENCE RECIPIENT
    assertEquals(
        false, Arrays.equals(recipient.getLastReference(databaseSet), payment1.getSignature()));

    // CHECK BALANCE RECIPIENT2
    assertEquals(
        true, recipient2.getConfirmedBalance(databaseSet).compareTo(BigDecimal.valueOf(0)) == 0);

    // CHECK LAST REFERENCE RECIPIENT
    assertEquals(true, Arrays.equals(recipient2.getLastReference(databaseSet), new byte[0]));

    // CHECK LAST BLOCK
    assertEquals(
        true,
        Arrays.equals(
            genesisBlock.getSignature(), databaseSet.getBlockMap().getLastBlock().getSignature()));
  }
Esempio n. 4
0
  @Test
  public void parseBlock() {
    // CREATE EMPTY MEMORY DATABASE
    DBSet databaseSet = DBSet.createEmptyDatabaseSet();

    // PROCESS GENESISBLOCK
    GenesisBlock genesisBlock = new GenesisBlock();
    genesisBlock.process(databaseSet);

    // CREATE KNOWN ACCOUNT
    byte[] seed = Crypto.getInstance().digest("test".getBytes());
    byte[] privateKey = Crypto.getInstance().createKeyPair(seed).getA();
    PrivateKeyAccount generator = new PrivateKeyAccount(privateKey);

    // PROCESS GENESIS TRANSACTION TO MAKE SURE GENERATOR HAS FUNDS
    Transaction transaction =
        new GenesisTransaction(generator, BigDecimal.valueOf(1000).setScale(8), NTP.getTime());
    transaction.process(databaseSet);

    // GENERATE NEXT BLOCK
    BlockGenerator blockGenerator = new BlockGenerator();
    Block block = blockGenerator.generateNextBlock(databaseSet, generator, genesisBlock);

    // FORK
    DBSet fork = databaseSet.fork();

    // GENERATE PAYMENT 1
    Account recipient = new Account("XUi2oga2pnGNcZ9es6pBqxydtRZKWdkL2g");
    long timestamp = block.getTimestamp();
    byte[] signature =
        PaymentTransaction.generateSignature(
            databaseSet,
            generator,
            recipient,
            BigDecimal.valueOf(100).setScale(8),
            BigDecimal.valueOf(1).setScale(8),
            timestamp);
    Transaction payment1 =
        new PaymentTransaction(
            generator,
            recipient,
            BigDecimal.valueOf(100).setScale(8),
            BigDecimal.valueOf(1).setScale(8),
            timestamp,
            generator.getLastReference(databaseSet),
            signature);
    payment1.process(fork);
    block.addTransaction(payment1);

    // GENERATE PAYMENT 2
    Account recipient2 = new Account("XLPYYfxKEiDcybCkFA7jXcxSdePMMoyZLt");
    signature =
        PaymentTransaction.generateSignature(
            fork,
            generator,
            recipient2,
            BigDecimal.valueOf(100).setScale(8),
            BigDecimal.valueOf(1).setScale(8),
            timestamp);
    Transaction payment2 =
        new PaymentTransaction(
            generator,
            recipient2,
            BigDecimal.valueOf(100).setScale(8),
            BigDecimal.valueOf(1).setScale(8),
            timestamp,
            generator.getLastReference(fork),
            signature);
    block.addTransaction(payment2);

    // ADD TRANSACTION SIGNATURE
    byte[] transactionsSignature =
        Crypto.getInstance().sign(generator, block.getGeneratorSignature());
    block.setTransactionsSignature(transactionsSignature);

    // CONVERT TO BYTES
    byte[] rawBlock = block.toBytes();

    try {
      // PARSE FROM BYTES
      Block parsedBlock = BlockFactory.getInstance().parse(rawBlock);

      // CHECK INSTANCE
      assertEquals(false, parsedBlock instanceof GenesisBlock);

      // CHECK SIGNATURE
      assertEquals(true, Arrays.equals(block.getSignature(), parsedBlock.getSignature()));

      // CHECK GENERATOR
      assertEquals(block.getGenerator().getAddress(), parsedBlock.getGenerator().getAddress());

      // CHECK BASE TARGET
      assertEquals(block.getGeneratingBalance(), parsedBlock.getGeneratingBalance());

      // CHECK FEE
      assertEquals(block.getTotalFee(), parsedBlock.getTotalFee());

      // CHECK REFERENCE
      assertEquals(true, Arrays.equals(block.getReference(), parsedBlock.getReference()));

      // CHECK TIMESTAMP
      assertEquals(block.getTimestamp(), parsedBlock.getTimestamp());

      // CHECK TRANSACTIONS COUNT
      assertEquals(block.getTransactionCount(), parsedBlock.getTransactionCount());
    } catch (Exception e) {
      fail("Exception while parsing transaction.");
    }

    // PARSE TRANSACTION FROM WRONG BYTES
    rawBlock = new byte[50];

    try {
      // PARSE FROM BYTES
      BlockFactory.getInstance().parse(rawBlock);

      // FAIL
      fail("this should throw an exception");
    } catch (Exception e) {
      // EXCEPTION IS THROWN OKE
    }
  }
Esempio n. 5
0
  @Test
  public void validateBlock() {
    // CREATE EMPTY MEMORY DATABASE
    DBSet databaseSet = DBSet.createEmptyDatabaseSet();

    // PROCESS GENESISBLOCK
    GenesisBlock genesisBlock = new GenesisBlock();
    genesisBlock.process(databaseSet);

    // CREATE KNOWN ACCOUNT
    byte[] seed = Crypto.getInstance().digest("test".getBytes());
    byte[] privateKey = Crypto.getInstance().createKeyPair(seed).getA();
    PrivateKeyAccount generator = new PrivateKeyAccount(privateKey);

    // PROCESS GENESIS TRANSACTION TO MAKE SURE GENERATOR HAS FUNDS
    Transaction transaction =
        new GenesisTransaction(generator, BigDecimal.valueOf(1000).setScale(8), NTP.getTime());
    transaction.process(databaseSet);

    // GENERATE NEXT BLOCK
    BlockGenerator blockGenerator = new BlockGenerator();
    Block newBlock = blockGenerator.generateNextBlock(databaseSet, generator, genesisBlock);

    // ADD TRANSACTION SIGNATURE
    byte[] transactionsSignature =
        Crypto.getInstance().sign(generator, newBlock.getGeneratorSignature());
    newBlock.setTransactionsSignature(transactionsSignature);

    // CHECK IF VALID
    assertEquals(true, newBlock.isValid(databaseSet));

    // CHANGE REFERENCE
    Block invalidBlock =
        BlockFactory.getInstance()
            .create(
                newBlock.getVersion(),
                new byte[128],
                newBlock.getTimestamp(),
                newBlock.getGeneratingBalance(),
                newBlock.getGenerator(),
                newBlock.getGeneratorSignature());

    // CHECK IF INVALID
    assertEquals(false, invalidBlock.isValid(databaseSet));

    // CHANGE TIMESTAMP
    invalidBlock =
        BlockFactory.getInstance()
            .create(
                newBlock.getVersion(),
                newBlock.getReference(),
                1L,
                newBlock.getGeneratingBalance(),
                newBlock.getGenerator(),
                newBlock.getGeneratorSignature());

    // CHECK IF INVALID
    assertEquals(false, invalidBlock.isValid(databaseSet));

    // CHANGE BASETARGET
    invalidBlock =
        BlockFactory.getInstance()
            .create(
                newBlock.getVersion(),
                newBlock.getReference(),
                newBlock.getTimestamp(),
                1L,
                newBlock.getGenerator(),
                newBlock.getGeneratorSignature());

    // CHECK IF INVALID
    assertEquals(false, invalidBlock.isValid(databaseSet));

    // ADD INVALID TRANSACTION
    invalidBlock = blockGenerator.generateNextBlock(databaseSet, generator, genesisBlock);
    Account recipient = new Account("XUi2oga2pnGNcZ9es6pBqxydtRZKWdkL2g");
    long timestamp = newBlock.getTimestamp();
    byte[] signature =
        PaymentTransaction.generateSignature(
            databaseSet,
            generator,
            recipient,
            BigDecimal.valueOf(-100).setScale(8),
            BigDecimal.valueOf(1).setScale(8),
            timestamp);
    Transaction payment =
        new PaymentTransaction(
            generator,
            recipient,
            BigDecimal.valueOf(-100).setScale(8),
            BigDecimal.valueOf(1).setScale(8),
            timestamp,
            generator.getLastReference(databaseSet),
            signature);
    invalidBlock.addTransaction(payment);

    // CHECK IF INVALID
    assertEquals(false, invalidBlock.isValid(databaseSet));

    // ADD GENESIS TRANSACTION
    invalidBlock = blockGenerator.generateNextBlock(databaseSet, generator, genesisBlock);
    transaction =
        new GenesisTransaction(
            generator, BigDecimal.valueOf(1000).setScale(8), newBlock.getTimestamp());
    invalidBlock.addTransaction(transaction);

    // CHECK IF INVALID
    assertEquals(false, invalidBlock.isValid(databaseSet));
  }
Esempio n. 6
0
  public void process(DBSet db) {
    // PROCESS TRANSACTIONS
    for (Transaction transaction : this.getTransactions()) {
      // PROCESS
      transaction.process(db);

      // SET PARENT
      db.getTransactionParentMap().set(transaction, this);

      // REMOVE FROM UNCONFIRMED DATABASE
      db.getTransactionMap().delete(transaction);
    }

    // DELETE CONFIRMED TRANSACTIONS FROM UNCONFIRMED TRANSACTIONS LIST
    List<Transaction> unconfirmedTransactions =
        new ArrayList<Transaction>(db.getTransactionMap().getValues());
    for (Transaction transaction : unconfirmedTransactions) {
      if (db.getTransactionParentMap().contains(transaction.getSignature())) {
        db.getTransactionMap().delete(transaction);
      }
    }

    // PROCESS FEE
    BigDecimal blockFee = this.getTotalFee();
    if (blockFee.compareTo(BigDecimal.ZERO) == 1) {
      // UPDATE GENERATOR BALANCE WITH FEE
      this.generator.setConfirmedBalance(this.generator.getConfirmedBalance(db).add(blockFee), db);
    }

    Block parent = this.getParent(db);
    int height = 1;
    if (parent != null) {
      // SET AS CHILD OF PARENT
      db.getChildMap().set(parent, this);

      // SET BLOCK HEIGHT
      height = parent.getHeight(db) + 1;
      db.getHeightMap().set(this, height);
    } else {
      // IF NO PARENT HEIGHT IS 1
      db.getHeightMap().set(this, 1);
    }

    // PROCESS TRANSACTIONS
    int seq = 1;
    for (Transaction transaction : this.getTransactions()) {
      db.getTransactionFinalMap().add(height, seq, transaction);
      seq++;
    }

    // ADD TO DB
    db.getBlockMap().add(this);

    // UPDATE LAST BLOCK
    db.getBlockMap().setLastBlock(this);
  }
Esempio n. 7
0
 public void orphan() {
   this.orphan(DBSet.getInstance());
 }
Esempio n. 8
0
  public boolean isValid(DBSet db) {
    // CHECK IF PARENT EXISTS
    if (this.reference == null || this.getParent(db) == null) {
      return false;
    }

    // CHECK IF TIMESTAMP IS VALID -500 MS ERROR MARGIN TIME
    if (this.timestamp - 500 > NTP.getTime() || this.timestamp < this.getParent(db).timestamp) {
      return false;
    }

    // CHECK IF TIMESTAMP REST SAME AS PARENT TIMESTAMP REST
    if (this.timestamp % 1000 != this.getParent(db).timestamp % 1000) {
      return false;
    }

    // CHECK IF GENERATING BALANCE IS CORRECT
    if (this.generatingBalance
        != BlockGenerator.getNextBlockGeneratingBalance(db, this.getParent(db))) {
      return false;
    }

    // CHECK IF VERSION IS CORRECT
    if (this.version != this.getParent(db).getNextBlockVersion(db)) {
      return false;
    }
    if (this.version < 2 && (this.atBytes.length > 0 || this.atFees != 0)) {
      return false;
    }

    // CREATE TARGET
    byte[] targetBytes = new byte[32];
    Arrays.fill(targetBytes, Byte.MAX_VALUE);
    BigInteger target = new BigInteger(1, targetBytes);

    // DIVIDE TARGET BY BASE TARGET
    BigInteger baseTarget =
        BigInteger.valueOf(BlockGenerator.getBaseTarget(this.generatingBalance));
    target = target.divide(baseTarget);

    // MULTIPLY TARGET BY USER BALANCE
    target = target.multiply(this.generator.getGeneratingBalance(db).toBigInteger());

    // MULTIPLE TARGET BY GUESSES
    long guesses = (this.timestamp - this.getParent(db).getTimestamp()) / 1000;
    BigInteger lowerTarget = target.multiply(BigInteger.valueOf(guesses - 1));
    target = target.multiply(BigInteger.valueOf(guesses));

    // CONVERT PROOF HASH TO BIGINT
    BigInteger hashValue = new BigInteger(1, getProofHash());

    // CHECK IF HASH LOWER THEN TARGET
    if (hashValue.compareTo(target) >= 0) {
      return false;
    }

    // CHECK IF FIRST BLOCK OF USER
    if (hashValue.compareTo(lowerTarget) < 0) {
      return false;
    }

    if (this.atBytes != null && this.atBytes.length > 0) {
      try {

        AT_Block atBlock =
            AT_Controller.validateATs(
                this.getBlockATs(), db.getBlockMap().getLastBlock().getHeight(db) + 1, db);
        this.atFees = atBlock.getTotalFees();
      } catch (NoSuchAlgorithmException | AT_Exception e) {
        e.printStackTrace();
        return false;
      }
    }

    // CHECK TRANSACTIONS
    DBSet fork = db.fork();
    for (Transaction transaction : this.getTransactions()) {
      // CHECK IF NOT GENESISTRANSACTION
      if (transaction instanceof GenesisTransaction) {
        return false;
      }

      Integer min = 0;
      if (db.getBlockMap().getParentList() != null) {
        min = AT_API_Platform_Impl.getForkHeight(db);
      }

      // CHECK IF VALID
      if (transaction instanceof DeployATTransaction) {
        DeployATTransaction atTx = (DeployATTransaction) transaction;
        if (atTx.isValid(fork, min) != Transaction.VALIDATE_OK) {
          return false;
        }
      } else if (transaction.isValid(fork) != Transaction.VALIDATE_OK) {
        return false;
      }

      // CHECK TIMESTAMP AND DEADLINE
      if (transaction.getTimestamp() > this.timestamp
          || transaction.getDeadline() <= this.timestamp) {
        return false;
      }

      // PROCESS TRANSACTION IN MEMORYDB TO MAKE SURE OTHER TRANSACTIONS VALIDATE PROPERLY
      transaction.process(fork);
    }

    // BLOCK IS VALID
    return true;
  }
Esempio n. 9
0
 public void process() {
   this.process(DBSet.getInstance());
 }
Esempio n. 10
0
 public int getHeight(DBSet db) {
   if (db.getHeightMap().contains(this.getSignature())) return db.getHeightMap().get(this);
   else return -1;
 }
Esempio n. 11
0
 public boolean isValid() {
   return this.isValid(DBSet.getInstance());
 }
Esempio n. 12
0
 public int getHeight() {
   return this.getHeight(DBSet.getInstance());
 }
Esempio n. 13
0
 public Block getChild(DBSet db) {
   return db.getChildMap().get(this);
 }
Esempio n. 14
0
 public Block getChild() {
   return this.getChild(DBSet.getInstance());
 }
Esempio n. 15
0
 public Block getParent(DBSet db) {
   return db.getBlockMap().get(this.reference);
 }
Esempio n. 16
0
 public Block getParent() {
   return this.getParent(DBSet.getInstance());
 }