Search in sources :

Example 16 with BlockStoreException

use of co.rsk.bitcoinj.store.BlockStoreException in project rskj by rsksmart.

the class BridgeSupport method validationsForRegisterBtcTransaction.

@VisibleForTesting
protected boolean validationsForRegisterBtcTransaction(Sha256Hash btcTxHash, int height, byte[] pmtSerialized, byte[] btcTxSerialized) throws BlockStoreException, VerificationException.EmptyInputsOrOutputs, BridgeIllegalArgumentException {
    // Validates height and confirmations for tx
    try {
        int acceptableConfirmationsAmount = bridgeConstants.getBtc2RskMinimumAcceptableConfirmations();
        if (!BridgeUtils.validateHeightAndConfirmations(height, getBtcBlockchainBestChainHeight(), acceptableConfirmationsAmount, btcTxHash)) {
            return false;
        }
    } catch (Exception e) {
        String panicMessage = String.format("Btc Tx %s Supplied Height is %d but should be greater than 0", btcTxHash, height);
        logger.warn(panicMessage);
        panicProcessor.panic("btclock", panicMessage);
        return false;
    }
    // Validates pmt size
    if (!PartialMerkleTreeFormatUtils.hasExpectedSize(pmtSerialized)) {
        throw new BridgeIllegalArgumentException("PartialMerkleTree doesn't have expected size");
    }
    // Calculates merkleRoot
    Sha256Hash merkleRoot;
    try {
        NetworkParameters networkParameters = bridgeConstants.getBtcParams();
        merkleRoot = BridgeUtils.calculateMerkleRoot(networkParameters, pmtSerialized, btcTxHash);
        if (merkleRoot == null) {
            return false;
        }
    } catch (VerificationException e) {
        throw new BridgeIllegalArgumentException(e.getMessage(), e);
    }
    // Validates inputs count
    logger.info("Going to validate inputs for btc tx {}", btcTxHash);
    BridgeUtils.validateInputsCount(btcTxSerialized, activations.isActive(ConsensusRule.RSKIP143));
    // Check the the merkle root equals merkle root of btc block at specified height in the btc best chain
    // BTC blockstore is available since we've already queried the best chain height
    logger.trace("Getting btc block at height: {}", height);
    BtcBlock blockHeader = btcBlockStore.getStoredBlockAtMainChainHeight(height).getHeader();
    logger.trace("Validating block merkle root at height: {}", height);
    if (!isBlockMerkleRootValid(merkleRoot, blockHeader)) {
        String panicMessage = String.format("Btc Tx %s Supplied merkle root %s does not match block's merkle root %s", btcTxHash.toString(), merkleRoot, blockHeader.getMerkleRoot());
        logger.warn(panicMessage);
        panicProcessor.panic("btclock", panicMessage);
        return false;
    }
    return true;
}
Also used : NetworkParameters(co.rsk.bitcoinj.core.NetworkParameters) Sha256Hash(co.rsk.bitcoinj.core.Sha256Hash) VerificationException(co.rsk.bitcoinj.core.VerificationException) BtcBlock(co.rsk.bitcoinj.core.BtcBlock) VMException(org.ethereum.vm.exception.VMException) UTXOProviderException(co.rsk.bitcoinj.core.UTXOProviderException) VerificationException(co.rsk.bitcoinj.core.VerificationException) InsufficientMoneyException(co.rsk.bitcoinj.core.InsufficientMoneyException) AddressFormatException(co.rsk.bitcoinj.core.AddressFormatException) IOException(java.io.IOException) BlockStoreException(co.rsk.bitcoinj.store.BlockStoreException) PeginInstructionsException(co.rsk.peg.pegininstructions.PeginInstructionsException) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 17 with BlockStoreException

use of co.rsk.bitcoinj.store.BlockStoreException in project rskj by rsksmart.

the class BridgeSupport method receiveHeader.

/**
 * Receives only one header of serialized Bitcoin block headers and adds them to the internal BlockChain structure.
 * @param header The bitcoin headers
 */
public Integer receiveHeader(BtcBlock header) throws IOException, BlockStoreException {
    Context.propagate(btcContext);
    this.ensureBtcBlockChain();
    if (btcBlockStore.get(header.getHash()) != null) {
        return RECEIVE_HEADER_BLOCK_PREVIOUSLY_SAVED;
    }
    long diffTimeStamp = bridgeConstants.getMinSecondsBetweenCallsToReceiveHeader();
    // in seconds
    long currentTimeStamp = rskExecutionBlock.getTimestamp();
    Optional<Long> optionalLastTimeStamp = provider.getReceiveHeadersLastTimestamp();
    if (optionalLastTimeStamp.isPresent() && (currentTimeStamp - optionalLastTimeStamp.get() < diffTimeStamp)) {
        logger.warn("Receive header last TimeStamp less than {} milliseconds", diffTimeStamp);
        return RECEIVE_HEADER_CALLED_TOO_SOON;
    }
    // Depth
    StoredBlock previousBlock = btcBlockStore.get(header.getPrevBlockHash());
    if (previousBlock == null) {
        return RECEIVE_HEADER_CANT_FOUND_PREVIOUS_BLOCK;
    }
    // height of best chain - height of current header block greater than maximum depth accepted
    if ((getBtcBlockchainBestChainHeight() - (previousBlock.getHeight() + 1)) > bridgeConstants.getMaxDepthBlockchainAccepted()) {
        return RECEIVE_HEADER_BLOCK_TOO_OLD;
    }
    try {
        btcBlockChain.add(header);
    } catch (Exception e) {
        // If we tray to add an orphan header bitcoinj throws an exception
        // This catches that case and any other exception that may be thrown
        logger.warn("Exception adding btc header {}", header.getHash(), e);
        return RECEIVE_HEADER_UNEXPECTED_EXCEPTION;
    }
    provider.setReceiveHeadersLastTimestamp(currentTimeStamp);
    return 0;
}
Also used : StoredBlock(co.rsk.bitcoinj.core.StoredBlock) VMException(org.ethereum.vm.exception.VMException) UTXOProviderException(co.rsk.bitcoinj.core.UTXOProviderException) VerificationException(co.rsk.bitcoinj.core.VerificationException) InsufficientMoneyException(co.rsk.bitcoinj.core.InsufficientMoneyException) AddressFormatException(co.rsk.bitcoinj.core.AddressFormatException) IOException(java.io.IOException) BlockStoreException(co.rsk.bitcoinj.store.BlockStoreException) PeginInstructionsException(co.rsk.peg.pegininstructions.PeginInstructionsException)

Example 18 with BlockStoreException

use of co.rsk.bitcoinj.store.BlockStoreException in project rskj by rsksmart.

the class BridgeSupport method registerBtcCoinbaseTransaction.

public void registerBtcCoinbaseTransaction(byte[] btcTxSerialized, Sha256Hash blockHash, byte[] pmtSerialized, Sha256Hash witnessMerkleRoot, byte[] witnessReservedValue) throws VMException {
    Context.propagate(btcContext);
    try {
        this.ensureBtcBlockStore();
    } catch (BlockStoreException | IOException e) {
        logger.warn("Exception in registerBtcCoinbaseTransaction", e);
        throw new VMException("Exception in registerBtcCoinbaseTransaction", e);
    }
    Sha256Hash btcTxHash = BtcTransactionFormatUtils.calculateBtcTxHash(btcTxSerialized);
    if (witnessReservedValue.length != 32) {
        logger.warn("[btcTx:{}] WitnessResevedValue length can't be different than 32 bytes", btcTxHash);
        throw new BridgeIllegalArgumentException("WitnessResevedValue length can't be different than 32 bytes");
    }
    if (!PartialMerkleTreeFormatUtils.hasExpectedSize(pmtSerialized)) {
        logger.warn("[btcTx:{}] PartialMerkleTree doesn't have expected size", btcTxHash);
        throw new BridgeIllegalArgumentException("PartialMerkleTree doesn't have expected size");
    }
    Sha256Hash merkleRoot;
    try {
        PartialMerkleTree pmt = new PartialMerkleTree(bridgeConstants.getBtcParams(), pmtSerialized, 0);
        List<Sha256Hash> hashesInPmt = new ArrayList<>();
        merkleRoot = pmt.getTxnHashAndMerkleRoot(hashesInPmt);
        if (!hashesInPmt.contains(btcTxHash)) {
            logger.warn("Supplied Btc Tx {} is not in the supplied partial merkle tree", btcTxHash);
            return;
        }
    } catch (VerificationException e) {
        logger.warn("[btcTx:{}] PartialMerkleTree could not be parsed", btcTxHash);
        throw new BridgeIllegalArgumentException(String.format("PartialMerkleTree could not be parsed %s", ByteUtil.toHexString(pmtSerialized)), e);
    }
    // Check merkle root equals btc block merkle root at the specified height in the btc best chain
    // Btc blockstore is available since we've already queried the best chain height
    StoredBlock storedBlock = btcBlockStore.getFromCache(blockHash);
    if (storedBlock == null) {
        logger.warn("[btcTx:{}] Block not registered", btcTxHash);
        throw new BridgeIllegalArgumentException(String.format("Block not registered %s", blockHash.toString()));
    }
    BtcBlock blockHeader = storedBlock.getHeader();
    if (!blockHeader.getMerkleRoot().equals(merkleRoot)) {
        String panicMessage = String.format("Btc Tx %s Supplied merkle root %s does not match block's merkle root %s", btcTxHash.toString(), merkleRoot, blockHeader.getMerkleRoot());
        logger.warn(panicMessage);
        panicProcessor.panic("btclock", panicMessage);
        return;
    }
    BtcTransaction btcTx = new BtcTransaction(bridgeConstants.getBtcParams(), btcTxSerialized);
    btcTx.verify();
    Sha256Hash witnessCommitment = Sha256Hash.twiceOf(witnessMerkleRoot.getReversedBytes(), witnessReservedValue);
    if (!witnessCommitment.equals(btcTx.findWitnessCommitment())) {
        logger.warn("[btcTx:{}] WitnessCommitment does not match", btcTxHash);
        throw new BridgeIllegalArgumentException("WitnessCommitment does not match");
    }
    CoinbaseInformation coinbaseInformation = new CoinbaseInformation(witnessMerkleRoot);
    provider.setCoinbaseInformation(blockHeader.getHash(), coinbaseInformation);
    logger.warn("[btcTx:{}] Registered coinbase information", btcTxHash);
}
Also used : BlockStoreException(co.rsk.bitcoinj.store.BlockStoreException) StoredBlock(co.rsk.bitcoinj.core.StoredBlock) CoinbaseInformation(co.rsk.peg.bitcoin.CoinbaseInformation) Sha256Hash(co.rsk.bitcoinj.core.Sha256Hash) BtcTransaction(co.rsk.bitcoinj.core.BtcTransaction) ArrayList(java.util.ArrayList) IOException(java.io.IOException) VMException(org.ethereum.vm.exception.VMException) PartialMerkleTree(co.rsk.bitcoinj.core.PartialMerkleTree) VerificationException(co.rsk.bitcoinj.core.VerificationException) BtcBlock(co.rsk.bitcoinj.core.BtcBlock)

Example 19 with BlockStoreException

use of co.rsk.bitcoinj.store.BlockStoreException in project rskj by rsksmart.

the class BridgeSupport method getBtcTransactionConfirmations.

/**
 * @param btcTxHash The BTC transaction Hash
 * @param btcBlockHash The BTC block hash
 * @param merkleBranch The merkle branch
 * @throws BlockStoreException
 * @throws IOException
 */
public Integer getBtcTransactionConfirmations(Sha256Hash btcTxHash, Sha256Hash btcBlockHash, MerkleBranch merkleBranch) throws BlockStoreException, IOException {
    Context.propagate(btcContext);
    this.ensureBtcBlockChain();
    // Get the block using the given block hash
    StoredBlock block = btcBlockStore.getFromCache(btcBlockHash);
    if (block == null) {
        return BTC_TRANSACTION_CONFIRMATION_INEXISTENT_BLOCK_HASH_ERROR_CODE;
    }
    final int bestChainHeight = getBtcBlockchainBestChainHeight();
    // Prevent diving too deep in the blockchain to avoid high processing costs
    final int blockDepth = Math.max(0, bestChainHeight - block.getHeight());
    if (blockDepth > BTC_TRANSACTION_CONFIRMATION_MAX_DEPTH) {
        return BTC_TRANSACTION_CONFIRMATION_BLOCK_TOO_OLD_ERROR_CODE;
    }
    try {
        StoredBlock storedBlock = btcBlockStore.getStoredBlockAtMainChainHeight(block.getHeight());
        // Make sure it belongs to the best chain
        if (storedBlock == null || !storedBlock.equals(block)) {
            return BTC_TRANSACTION_CONFIRMATION_BLOCK_NOT_IN_BEST_CHAIN_ERROR_CODE;
        }
    } catch (BlockStoreException e) {
        logger.warn(String.format("Illegal state trying to get block with hash %s", btcBlockHash), e);
        return BTC_TRANSACTION_CONFIRMATION_INCONSISTENT_BLOCK_ERROR_CODE;
    }
    Sha256Hash merkleRoot = merkleBranch.reduceFrom(btcTxHash);
    if (!isBlockMerkleRootValid(merkleRoot, block.getHeader())) {
        return BTC_TRANSACTION_CONFIRMATION_INVALID_MERKLE_BRANCH_ERROR_CODE;
    }
    return bestChainHeight - block.getHeight() + 1;
}
Also used : StoredBlock(co.rsk.bitcoinj.core.StoredBlock) BlockStoreException(co.rsk.bitcoinj.store.BlockStoreException) Sha256Hash(co.rsk.bitcoinj.core.Sha256Hash)

Aggregations

BlockStoreException (co.rsk.bitcoinj.store.BlockStoreException)19 StoredBlock (co.rsk.bitcoinj.core.StoredBlock)9 Sha256Hash (co.rsk.bitcoinj.core.Sha256Hash)7 IOException (java.io.IOException)7 BigInteger (java.math.BigInteger)6 BtcBlockStore (co.rsk.bitcoinj.store.BtcBlockStore)5 BridgeStorageProvider (co.rsk.peg.BridgeStorageProvider)5 Repository (org.ethereum.core.Repository)5 VMException (org.ethereum.vm.exception.VMException)5 BtcBlock (co.rsk.bitcoinj.core.BtcBlock)4 VerificationException (co.rsk.bitcoinj.core.VerificationException)4 RskSystemProperties (co.rsk.config.RskSystemProperties)4 Test (org.junit.Test)4 AddressFormatException (co.rsk.bitcoinj.core.AddressFormatException)3 InsufficientMoneyException (co.rsk.bitcoinj.core.InsufficientMoneyException)3 UTXOProviderException (co.rsk.bitcoinj.core.UTXOProviderException)3 RepositoryBlockStore (co.rsk.peg.RepositoryBlockStore)3 PeginInstructionsException (co.rsk.peg.pegininstructions.PeginInstructionsException)3 ArrayList (java.util.ArrayList)3 BtcBlockChain (co.rsk.bitcoinj.core.BtcBlockChain)2