Search in sources :

Example 26 with BtcBlock

use of co.rsk.bitcoinj.core.BtcBlock in project rskj by rsksmart.

the class RepositoryBtcBlockStoreWithCacheTest method getStoredBlockAtMainChainHeight_postIris_heightLowerThanMaxDepth_limitInChainHeadMinusMaxDepthToSearch.

@Test(expected = BlockStoreException.class)
public void getStoredBlockAtMainChainHeight_postIris_heightLowerThanMaxDepth_limitInChainHeadMinusMaxDepthToSearch() throws BlockStoreException {
    Repository repository = createRepository();
    BtcBlockStoreWithCache.Factory btcBlockStoreFactory = new RepositoryBtcBlockStoreWithCache.Factory(bridgeConstants.getBtcParams());
    BridgeStorageProvider provider = mock(BridgeStorageProvider.class);
    ActivationConfig.ForBlock activations = mock(ActivationConfig.ForBlock.class);
    when(activations.isActive(ConsensusRule.RSKIP199)).thenReturn(true);
    BtcBlockStoreWithCache btcBlockStore = btcBlockStoreFactory.newInstance(repository, bridgeConstants, provider, activations);
    BtcBlock genesis = networkParameters.getGenesisBlock();
    int btcHeightWhenBlockIndexActivates = bridgeConstants.getBtcHeightWhenBlockIndexActivates();
    int maxDepthToSearchBlocksBelowIndexActivation = bridgeConstants.getMaxDepthToSearchBlocksBelowIndexActivation();
    int blockHeight = btcHeightWhenBlockIndexActivates + maxDepthToSearchBlocksBelowIndexActivation - 1;
    StoredBlock storedBlock1 = createStoredBlock(genesis, blockHeight, 0);
    btcBlockStore.put(storedBlock1);
    btcBlockStore.setChainHead(storedBlock1);
    assertEquals(storedBlock1, btcBlockStore.getChainHead());
    // Search for a block in a height lower than the max depth, should fail
    // Since the chain height is below btcHeightWhenBlockIndexActivates + maxDepthToSearchBlocksBelowIndexActivation
    int maxDepth = blockHeight - maxDepthToSearchBlocksBelowIndexActivation;
    btcBlockStore.getStoredBlockAtMainChainHeight(maxDepth - 1);
}
Also used : Repository(org.ethereum.core.Repository) MutableRepository(org.ethereum.db.MutableRepository) StoredBlock(co.rsk.bitcoinj.core.StoredBlock) BtcBlock(co.rsk.bitcoinj.core.BtcBlock) ActivationConfig(org.ethereum.config.blockchain.upgrades.ActivationConfig) Test(org.junit.Test)

Example 27 with BtcBlock

use of co.rsk.bitcoinj.core.BtcBlock in project rskj by rsksmart.

the class RepositoryBtcBlockStoreWithCacheTest method checkDifferentInstancesWithSameRepoHaveSameContentTest.

@Test
public void checkDifferentInstancesWithSameRepoHaveSameContentTest() throws Exception {
    // This Is how I produced RepositoryBlockStore_data.ser. I had a bitcoind in regtest with 613 blocks + genesis block
    // NetworkParameters params = RegTestParams.get();
    // Context context = new Context(params);
    // Wallet wallet = new Wallet(context);
    // BlockStore store = new SPVBlockStore(params, new File("spvBlockstore"));
    // AbstractBlockChain chain = new BlockChain(context, wallet, store);
    // PeerGroup peerGroup = new PeerGroup(context, chain);
    // peerGroup.start();
    // final DownloadProgressTracker listener = new DownloadProgressTracker();
    // peerGroup.startBlockChainDownload(listener);
    // listener.await();
    // peerGroup.stop();
    // StoredBlock storedBlock = chain.getChainHead();
    // FileOutputStream fos = new FileOutputStream("RepositoryBlockStore_data.ser");
    // ObjectOutputStream oos = new ObjectOutputStream(fos);
    // for (int i = 0; i < 614; i++) {
    // Triple<byte[], BigInteger , Integer> tripleStoredBlock = new ImmutableTriple<>(storedBlock.getHeader().bitcoinSerialize(), storedBlock.getChainWork(), storedBlock.getHeight());
    // oos.writeObject(tripleStoredBlock);
    // storedBlock = store.get(storedBlock.getHeader().getPrevBlockHash());
    // }
    // oos.close();
    // Read original store
    InputStream fileInputStream = ClassLoader.getSystemResourceAsStream("peg/RepositoryBlockStore_data.ser");
    ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
    Repository repository = createRepository();
    BtcBlockStoreWithCache.Factory btcBlockStoreFactory = new RepositoryBtcBlockStoreWithCache.Factory(bridgeConstants.getBtcParams());
    BtcBlockStoreWithCache store = btcBlockStoreFactory.newInstance(repository, bridgeConstants, mock(BridgeStorageProvider.class), mock(ActivationConfig.ForBlock.class));
    for (int i = 0; i < 614; i++) {
        Triple<byte[], BigInteger, Integer> tripleStoredBlock = (Triple<byte[], BigInteger, Integer>) objectInputStream.readObject();
        BtcBlock header = RegTestParams.get().getDefaultSerializer().makeBlock(tripleStoredBlock.getLeft());
        StoredBlock storedBlock = new StoredBlock(header, tripleStoredBlock.getMiddle(), tripleStoredBlock.getRight());
        if (i == 0) {
            store.setChainHead(storedBlock);
        }
        store.put(storedBlock);
    }
    // Create a new instance of the store
    BtcBlockStoreWithCache store2 = btcBlockStoreFactory.newInstance(repository, bridgeConstants, mock(BridgeStorageProvider.class), mock(ActivationConfig.ForBlock.class));
    // Check a specific block that used to fail when we had a bug
    assertEquals(store.get(Sha256Hash.wrap("373941fe83961cf70e181e468abc5f9f7cc440c711c3d06948fa66f3912ed27a")), store2.get(Sha256Hash.wrap("373941fe83961cf70e181e468abc5f9f7cc440c711c3d06948fa66f3912ed27a")));
    // Check new instance content is identical to the original one
    StoredBlock storedBlock = store.getChainHead();
    StoredBlock storedBlock2 = store2.getChainHead();
    int headHeight = storedBlock.getHeight();
    for (int i = 0; i < headHeight; i++) {
        assertNotNull(storedBlock);
        assertEquals(storedBlock, storedBlock2);
        Sha256Hash prevBlockHash = storedBlock.getHeader().getPrevBlockHash();
        storedBlock = store.get(prevBlockHash);
        storedBlock2 = store2.get(prevBlockHash);
    }
}
Also used : StoredBlock(co.rsk.bitcoinj.core.StoredBlock) ObjectInputStream(java.io.ObjectInputStream) InputStream(java.io.InputStream) Sha256Hash(co.rsk.bitcoinj.core.Sha256Hash) BigInteger(java.math.BigInteger) Triple(org.apache.commons.lang3.tuple.Triple) Repository(org.ethereum.core.Repository) MutableRepository(org.ethereum.db.MutableRepository) BigInteger(java.math.BigInteger) BtcBlock(co.rsk.bitcoinj.core.BtcBlock) ObjectInputStream(java.io.ObjectInputStream) Test(org.junit.Test)

Example 28 with BtcBlock

use of co.rsk.bitcoinj.core.BtcBlock in project rskj by rsksmart.

the class RepositoryBtcBlockStoreWithCacheTest method getStoredBlockAtMainChainHeight_postIris_heightLowerThanMaxDepth_limitInBtcHeightWhenBlockIndexActivates.

@Test(expected = BlockStoreException.class)
public void getStoredBlockAtMainChainHeight_postIris_heightLowerThanMaxDepth_limitInBtcHeightWhenBlockIndexActivates() throws BlockStoreException {
    Repository repository = createRepository();
    BtcBlockStoreWithCache.Factory btcBlockStoreFactory = new RepositoryBtcBlockStoreWithCache.Factory(bridgeConstants.getBtcParams());
    BridgeStorageProvider provider = mock(BridgeStorageProvider.class);
    ActivationConfig.ForBlock activations = mock(ActivationConfig.ForBlock.class);
    when(activations.isActive(ConsensusRule.RSKIP199)).thenReturn(true);
    BtcBlockStoreWithCache btcBlockStore = btcBlockStoreFactory.newInstance(repository, bridgeConstants, provider, activations);
    BtcBlock genesis = networkParameters.getGenesisBlock();
    int btcHeightWhenBlockIndexActivates = bridgeConstants.getBtcHeightWhenBlockIndexActivates();
    int maxDepthToSearchBlocksBelowIndexActivation = bridgeConstants.getMaxDepthToSearchBlocksBelowIndexActivation();
    int blockHeight = btcHeightWhenBlockIndexActivates + maxDepthToSearchBlocksBelowIndexActivation + 1;
    StoredBlock storedBlock1 = createStoredBlock(genesis, blockHeight, 0);
    btcBlockStore.put(storedBlock1);
    btcBlockStore.setChainHead(storedBlock1);
    assertEquals(storedBlock1, btcBlockStore.getChainHead());
    // Search for a block in a height lower than the max depth, should fail
    // Since the chain height is above btcHeightWhenBlockIndexActivates + maxDepthToSearchBlocksBelowIndexActivation
    int maxDepth = btcHeightWhenBlockIndexActivates;
    btcBlockStore.getStoredBlockAtMainChainHeight(maxDepth - 1);
}
Also used : Repository(org.ethereum.core.Repository) MutableRepository(org.ethereum.db.MutableRepository) StoredBlock(co.rsk.bitcoinj.core.StoredBlock) BtcBlock(co.rsk.bitcoinj.core.BtcBlock) ActivationConfig(org.ethereum.config.blockchain.upgrades.ActivationConfig) Test(org.junit.Test)

Example 29 with BtcBlock

use of co.rsk.bitcoinj.core.BtcBlock in project rskj by rsksmart.

the class RepositoryBtcBlockStoreWithCacheTest method getStoredBlockAtMainChainDepth_Error.

@Test
public void getStoredBlockAtMainChainDepth_Error() throws BlockStoreException {
    BtcBlockStoreWithCache btcBlockStore = createBlockStore();
    BtcBlock parent = networkParameters.getGenesisBlock();
    BtcBlock blockHeader1 = new BtcBlock(networkParameters, 2L, parent.getHash(), Sha256Hash.ZERO_HASH, parent.getTimeSeconds() + 1, parent.getDifficultyTarget(), 0, new ArrayList<>());
    StoredBlock storedBlock1 = new StoredBlock(blockHeader1, new BigInteger("0"), 2);
    btcBlockStore.put(storedBlock1);
    parent = blockHeader1;
    BtcBlock blockHeader2 = new BtcBlock(networkParameters, 2L, parent.getHash(), Sha256Hash.ZERO_HASH, parent.getTimeSeconds() + 1, parent.getDifficultyTarget(), 0, new ArrayList<>());
    StoredBlock storedBlock2 = new StoredBlock(blockHeader2, new BigInteger("0"), 2);
    btcBlockStore.put(storedBlock2);
    btcBlockStore.setChainHead(storedBlock2);
    // getStoredBlockAtMainChainDepth should fail as the block is at a inconsistent height
    try {
        btcBlockStore.getStoredBlockAtMainChainDepth(1);
        fail();
    } catch (BlockStoreException e) {
        assertTrue(true);
    }
    // getStoredBlockAtMainChainHeight should fail as the block is at a inconsistent height
    try {
        btcBlockStore.getStoredBlockAtMainChainHeight(1);
        fail();
    } catch (BlockStoreException e) {
        assertTrue(true);
    }
}
Also used : StoredBlock(co.rsk.bitcoinj.core.StoredBlock) BlockStoreException(co.rsk.bitcoinj.store.BlockStoreException) BtcBlock(co.rsk.bitcoinj.core.BtcBlock) BigInteger(java.math.BigInteger) Test(org.junit.Test)

Example 30 with BtcBlock

use of co.rsk.bitcoinj.core.BtcBlock in project rskj by rsksmart.

the class ProofOfWorkRule method isValid.

@Override
public boolean isValid(BlockHeader header) {
    // TODO: Make ProofOfWorkRule one of the classes that inherits from AuthenticationRule.
    if (isFallbackMiningPossibleAndBlockSigned(header)) {
        boolean isValidFallbackSignature = validFallbackBlockSignature(constants, header, header.getBitcoinMergedMiningHeader());
        if (!isValidFallbackSignature) {
            logger.warn("Fallback signature failed. Header {}", header.getPrintableHash());
        }
        return isValidFallbackSignature;
    }
    co.rsk.bitcoinj.core.NetworkParameters bitcoinNetworkParameters = bridgeConstants.getBtcParams();
    MerkleProofValidator mpValidator;
    try {
        if (activationConfig.isActive(ConsensusRule.RSKIP92, header.getNumber())) {
            boolean isRskip180Enabled = activationConfig.isActive(ConsensusRule.RSKIP180, header.getNumber());
            mpValidator = new Rskip92MerkleProofValidator(header.getBitcoinMergedMiningMerkleProof(), isRskip180Enabled);
        } else {
            mpValidator = new GenesisMerkleProofValidator(bitcoinNetworkParameters, header.getBitcoinMergedMiningMerkleProof());
        }
    } catch (RuntimeException ex) {
        logger.warn("Merkle proof can't be validated. Header {}", header.getPrintableHash(), ex);
        return false;
    }
    byte[] bitcoinMergedMiningCoinbaseTransactionCompressed = header.getBitcoinMergedMiningCoinbaseTransaction();
    if (bitcoinMergedMiningCoinbaseTransactionCompressed == null) {
        logger.warn("Compressed coinbase transaction does not exist. Header {}", header.getPrintableHash());
        return false;
    }
    if (header.getBitcoinMergedMiningHeader() == null) {
        logger.warn("Bitcoin merged mining header does not exist. Header {}", header.getPrintableHash());
        return false;
    }
    BtcBlock bitcoinMergedMiningBlock = bitcoinNetworkParameters.getDefaultSerializer().makeBlock(header.getBitcoinMergedMiningHeader());
    BigInteger target = DifficultyUtils.difficultyToTarget(header.getDifficulty());
    BigInteger bitcoinMergedMiningBlockHashBI = bitcoinMergedMiningBlock.getHash().toBigInteger();
    if (bitcoinMergedMiningBlockHashBI.compareTo(target) > 0) {
        logger.warn("Hash {} is higher than target {}", bitcoinMergedMiningBlockHashBI.toString(16), target.toString(16));
        return false;
    }
    byte[] bitcoinMergedMiningCoinbaseTransactionMidstate = new byte[RskMiningConstants.MIDSTATE_SIZE];
    System.arraycopy(bitcoinMergedMiningCoinbaseTransactionCompressed, 0, bitcoinMergedMiningCoinbaseTransactionMidstate, 8, RskMiningConstants.MIDSTATE_SIZE_TRIMMED);
    byte[] bitcoinMergedMiningCoinbaseTransactionTail = new byte[bitcoinMergedMiningCoinbaseTransactionCompressed.length - RskMiningConstants.MIDSTATE_SIZE_TRIMMED];
    System.arraycopy(bitcoinMergedMiningCoinbaseTransactionCompressed, RskMiningConstants.MIDSTATE_SIZE_TRIMMED, bitcoinMergedMiningCoinbaseTransactionTail, 0, bitcoinMergedMiningCoinbaseTransactionTail.length);
    byte[] expectedCoinbaseMessageBytes = org.bouncycastle.util.Arrays.concatenate(RskMiningConstants.RSK_TAG, header.getHashForMergedMining());
    int rskTagPosition = ListArrayUtil.lastIndexOfSubList(bitcoinMergedMiningCoinbaseTransactionTail, expectedCoinbaseMessageBytes);
    if (rskTagPosition == -1) {
        logger.warn("bitcoin coinbase transaction tail message does not contain expected" + " RSKBLOCK:RskBlockHeaderHash. Expected: {} . Actual: {} .", Arrays.toString(expectedCoinbaseMessageBytes), Arrays.toString(bitcoinMergedMiningCoinbaseTransactionTail));
        return false;
    }
    /*
        * We check that the there is no other block before the rsk tag, to avoid a possible malleability attack:
        * If we have a mid state with 10 blocks, and the rsk tag, we can also have
        * another mid state with 9 blocks, 64bytes + the rsk tag, giving us two blocks with different hashes but the same spv proof.
        * */
    if (rskTagPosition >= 64) {
        logger.warn("bitcoin coinbase transaction tag position is bigger than expected 64. Actual: {}.", Integer.toString(rskTagPosition));
        return false;
    }
    int lastTag = ListArrayUtil.lastIndexOfSubList(bitcoinMergedMiningCoinbaseTransactionTail, RskMiningConstants.RSK_TAG);
    if (rskTagPosition != lastTag) {
        logger.warn("The valid RSK tag is not the last RSK tag. Tail: {}.", Arrays.toString(bitcoinMergedMiningCoinbaseTransactionTail));
        return false;
    }
    int remainingByteCount = bitcoinMergedMiningCoinbaseTransactionTail.length - rskTagPosition - RskMiningConstants.RSK_TAG.length - RskMiningConstants.BLOCK_HEADER_HASH_SIZE;
    if (remainingByteCount > RskMiningConstants.MAX_BYTES_AFTER_MERGED_MINING_HASH) {
        logger.warn("More than 128 bytes after RSK tag");
        return false;
    }
    // TODO test
    long byteCount = Pack.bigEndianToLong(bitcoinMergedMiningCoinbaseTransactionMidstate, 8);
    long coinbaseLength = bitcoinMergedMiningCoinbaseTransactionTail.length + byteCount;
    if (coinbaseLength <= 64) {
        logger.warn("Coinbase transaction must always be greater than 64-bytes long. But it was: {}", coinbaseLength);
        return false;
    }
    SHA256Digest digest = new SHA256Digest(bitcoinMergedMiningCoinbaseTransactionMidstate);
    digest.update(bitcoinMergedMiningCoinbaseTransactionTail, 0, bitcoinMergedMiningCoinbaseTransactionTail.length);
    byte[] bitcoinMergedMiningCoinbaseTransactionOneRoundOfHash = new byte[32];
    digest.doFinal(bitcoinMergedMiningCoinbaseTransactionOneRoundOfHash, 0);
    Sha256Hash bitcoinMergedMiningCoinbaseTransactionHash = Sha256Hash.wrapReversed(Sha256Hash.hash(bitcoinMergedMiningCoinbaseTransactionOneRoundOfHash));
    if (!mpValidator.isValid(bitcoinMergedMiningBlock.getMerkleRoot(), bitcoinMergedMiningCoinbaseTransactionHash)) {
        logger.warn("bitcoin merkle branch doesn't match coinbase and state root");
        return false;
    }
    return true;
}
Also used : Sha256Hash(co.rsk.bitcoinj.core.Sha256Hash) SHA256Digest(org.bouncycastle.crypto.digests.SHA256Digest) BtcBlock(co.rsk.bitcoinj.core.BtcBlock) BigInteger(java.math.BigInteger)

Aggregations

BtcBlock (co.rsk.bitcoinj.core.BtcBlock)37 Test (org.junit.Test)17 StoredBlock (co.rsk.bitcoinj.core.StoredBlock)16 NetworkParameters (co.rsk.bitcoinj.core.NetworkParameters)11 BtcTransaction (co.rsk.bitcoinj.core.BtcTransaction)10 Sha256Hash (co.rsk.bitcoinj.core.Sha256Hash)9 Repository (org.ethereum.core.Repository)8 Context (co.rsk.bitcoinj.core.Context)7 BigInteger (java.math.BigInteger)7 MutableRepository (org.ethereum.db.MutableRepository)6 BlockStoreException (co.rsk.bitcoinj.store.BlockStoreException)4 BlockGenerator (co.rsk.blockchain.utils.BlockGenerator)3 SubmitBlockResult (co.rsk.mine.SubmitBlockResult)3 InputStream (java.io.InputStream)3 ActivationConfig (org.ethereum.config.blockchain.upgrades.ActivationConfig)3 MessageSerializer (co.rsk.bitcoinj.core.MessageSerializer)2 VerificationException (co.rsk.bitcoinj.core.VerificationException)2 BlockMiner (co.rsk.blockchain.utils.BlockMiner)2 RskSystemProperties (co.rsk.config.RskSystemProperties)2 Keccak256 (co.rsk.crypto.Keccak256)2