Search in sources :

Example 1 with TxInput

use of bisq.core.dao.state.blockchain.TxInput in project bisq-core by bisq-network.

the class VoteResultConsensus method getConnectedBlindVoteStakeOutput.

public static TxOutput getConnectedBlindVoteStakeOutput(Tx voteRevealTx, BsqStateService bsqStateService) throws VoteResultException {
    try {
        // We use the stake output of the blind vote tx as first input
        final TxInput stakeTxInput = voteRevealTx.getTxInputs().get(0);
        Optional<TxOutput> optionalBlindVoteStakeOutput = bsqStateService.getConnectedTxOutput(stakeTxInput);
        checkArgument(optionalBlindVoteStakeOutput.isPresent(), "blindVoteStakeOutput must be present");
        final TxOutput blindVoteStakeOutput = optionalBlindVoteStakeOutput.get();
        checkArgument(blindVoteStakeOutput.getTxOutputType() == TxOutputType.BLIND_VOTE_LOCK_STAKE_OUTPUT, "blindVoteStakeOutput must be of type BLIND_VOTE_LOCK_STAKE_OUTPUT");
        return blindVoteStakeOutput;
    } catch (Throwable t) {
        throw new VoteResultException(t);
    }
}
Also used : TxOutput(bisq.core.dao.state.blockchain.TxOutput) TxInput(bisq.core.dao.state.blockchain.TxInput)

Example 2 with TxInput

use of bisq.core.dao.state.blockchain.TxInput in project bisq-core by bisq-network.

the class RpcService method getTxFromRawTransaction.

// /////////////////////////////////////////////////////////////////////////////////////////
// Private
// /////////////////////////////////////////////////////////////////////////////////////////
private RawTx getTxFromRawTransaction(RawTransaction rawBtcTx, com.neemre.btcdcli4j.core.domain.RawBlock rawBtcBlock) {
    String txId = rawBtcTx.getTxId();
    // We convert block time from sec to ms
    long blockTime = rawBtcBlock.getTime() * 1000;
    int blockHeight = rawBtcBlock.getHeight();
    String blockHash = rawBtcBlock.getHash();
    final List<TxInput> txInputs = rawBtcTx.getVIn().stream().filter(rawInput -> rawInput != null && rawInput.getVOut() != null && rawInput.getTxId() != null).map(rawInput -> {
        // We don't support segWit inputs yet as well as no pay to pubkey txs...
        String[] split = rawInput.getScriptSig().getAsm().split("\\[ALL\\] ");
        String pubKeyAsHex;
        if (split.length == 2) {
            pubKeyAsHex = rawInput.getScriptSig().getAsm().split("\\[ALL\\] ")[1];
        } else {
            // If we receive a pay to pubkey tx the pubKey is not included as
            // it is in the output already.
            // Bitcoin Core creates payToPubKey tx when spending mined coins (regtest)...
            pubKeyAsHex = null;
            log.debug("pubKeyAsHex is not set as we received a not supported sigScript " + "(segWit or payToPubKey tx). txId={}, asm={}", rawBtcTx.getTxId(), rawInput.getScriptSig().getAsm());
        }
        return new TxInput(rawInput.getTxId(), rawInput.getVOut(), pubKeyAsHex);
    }).collect(Collectors.toList());
    final List<RawTxOutput> txOutputs = rawBtcTx.getVOut().stream().filter(e -> e != null && e.getN() != null && e.getValue() != null && e.getScriptPubKey() != null).map(rawBtcTxOutput -> {
        byte[] opReturnData = null;
        com.neemre.btcdcli4j.core.domain.PubKeyScript scriptPubKey = rawBtcTxOutput.getScriptPubKey();
        if (ScriptTypes.NULL_DATA.equals(scriptPubKey.getType()) && scriptPubKey.getAsm() != null) {
            String[] chunks = scriptPubKey.getAsm().split(" ");
            // We get on testnet a lot of "OP_RETURN 0" data, so we filter those away
            if (chunks.length == 2 && "OP_RETURN".equals(chunks[0]) && !"0".equals(chunks[1])) {
                try {
                    opReturnData = Utils.HEX.decode(chunks[1]);
                } catch (Throwable t) {
                    // We get sometimes exceptions, seems BitcoinJ
                    // cannot handle all existing OP_RETURN data, but we ignore them
                    // anyway as our OP_RETURN data is valid in BitcoinJ
                    log.warn("Error at Utils.HEX.decode(chunks[1]): " + t.toString() + " / chunks[1]=" + chunks[1]);
                }
            }
        }
        // We don't support raw MS which are the only case where scriptPubKey.getAddresses()>1
        String address = scriptPubKey.getAddresses() != null && scriptPubKey.getAddresses().size() == 1 ? scriptPubKey.getAddresses().get(0) : null;
        PubKeyScript pubKeyScript = dumpBlockchainData ? new PubKeyScript(scriptPubKey) : null;
        return new RawTxOutput(rawBtcTxOutput.getN(), rawBtcTxOutput.getValue().movePointRight(8).longValue(), rawBtcTx.getTxId(), pubKeyScript, address, opReturnData, blockHeight);
    }).collect(Collectors.toList());
    return new RawTx(txId, blockHeight, blockHash, blockTime, ImmutableList.copyOf(txInputs), ImmutableList.copyOf(txOutputs));
}
Also used : BtcdClientImpl(com.neemre.btcdcli4j.core.client.BtcdClientImpl) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) Utilities(bisq.common.util.Utilities) Inject(com.google.inject.Inject) DaoOptionKeys(bisq.core.dao.DaoOptionKeys) RawTransaction(com.neemre.btcdcli4j.core.domain.RawTransaction) BtcdDaemonImpl(com.neemre.btcdcli4j.daemon.BtcdDaemonImpl) RawTxOutput(bisq.core.dao.state.blockchain.RawTxOutput) ImmutableList(com.google.common.collect.ImmutableList) PoolingHttpClientConnectionManager(org.apache.http.impl.conn.PoolingHttpClientConnectionManager) BitcoindException(com.neemre.btcdcli4j.core.BitcoindException) Named(javax.inject.Named) TxInput(bisq.core.dao.state.blockchain.TxInput) CloseableHttpClient(org.apache.http.impl.client.CloseableHttpClient) Properties(java.util.Properties) RawBlock(bisq.core.dao.state.blockchain.RawBlock) RawTx(bisq.core.dao.state.blockchain.RawTx) Utils(org.bitcoinj.core.Utils) ResultHandler(bisq.common.handlers.ResultHandler) CommunicationException(com.neemre.btcdcli4j.core.CommunicationException) ScriptTypes(com.neemre.btcdcli4j.core.domain.enums.ScriptTypes) BtcdClient(com.neemre.btcdcli4j.core.client.BtcdClient) Collectors(java.util.stream.Collectors) FutureCallback(com.google.common.util.concurrent.FutureCallback) PubKeyScript(bisq.core.dao.state.blockchain.PubKeyScript) BlockListener(com.neemre.btcdcli4j.daemon.event.BlockListener) Consumer(java.util.function.Consumer) Futures(com.google.common.util.concurrent.Futures) List(java.util.List) Slf4j(lombok.extern.slf4j.Slf4j) UserThread(bisq.common.UserThread) BtcdDaemon(com.neemre.btcdcli4j.daemon.BtcdDaemon) NotNull(org.jetbrains.annotations.NotNull) HttpClients(org.apache.http.impl.client.HttpClients) ListeningExecutorService(com.google.common.util.concurrent.ListeningExecutorService) RawTxOutput(bisq.core.dao.state.blockchain.RawTxOutput) PubKeyScript(bisq.core.dao.state.blockchain.PubKeyScript) TxInput(bisq.core.dao.state.blockchain.TxInput) RawTx(bisq.core.dao.state.blockchain.RawTx)

Example 3 with TxInput

use of bisq.core.dao.state.blockchain.TxInput in project bisq-core by bisq-network.

the class TxParserTest method testGetBisqTxType.

@Test
public void testGetBisqTxType() {
    // Thu Jun 20 14:04:25 CEST 2013
    long time = 1371729865;
    final List<TxInput> inputs = Arrays.asList(new TxInput("tx0", 0, null), new TxInput("tx1", 1, null));
    RawTxOutput output = new RawTxOutput(0, 123, null, null, null, null, 100);
    RawTx rawTx = new RawTx("faketx0", 100, "fakeblock0", time, ImmutableList.copyOf(inputs), ImmutableList.copyOf(Arrays.asList(output)));
    TempTx tempTx = TempTx.fromRawTx(rawTx);
    boolean hasOpReturnCandidate = true;
    long remainingInputValue = 0;
    Optional<OpReturnType> optionalOpReturnType = Optional.empty();
    TxType result = TxParser.getBisqTxType(tempTx, hasOpReturnCandidate, remainingInputValue, optionalOpReturnType);
    TxType want = TxType.INVALID;
    Assert.assertEquals("With an OP_RETURN candidate but no optional OP_RETURN type, this tx should be invalid.", want, result);
    hasOpReturnCandidate = false;
    result = TxParser.getBisqTxType(tempTx, hasOpReturnCandidate, remainingInputValue, optionalOpReturnType);
    want = TxType.TRANSFER_BSQ;
    Assert.assertEquals("With no OP_RETURN candidate and no optional OP_RETURN type, this should be a BSQ transfer tx.", want, result);
    // todo(chirhonul): this is very likely incorrect, we should see the tx as INVALID if
    // !hasOpReturnCandidate but optionalOpReturnType.
    hasOpReturnCandidate = false;
    optionalOpReturnType = Optional.of(OpReturnType.LOCKUP);
    result = TxParser.getBisqTxType(tempTx, hasOpReturnCandidate, remainingInputValue, optionalOpReturnType);
    want = TxType.LOCKUP;
    Assert.assertEquals("With no OP_RETURN candidate and optional OP_RETURN type of LOCKUP, this should be a LOCKUP tx.", want, result);
    hasOpReturnCandidate = true;
    optionalOpReturnType = Optional.of(OpReturnType.BLIND_VOTE);
    result = TxParser.getBisqTxType(tempTx, hasOpReturnCandidate, remainingInputValue, optionalOpReturnType);
    want = TxType.BLIND_VOTE;
    Assert.assertEquals("With OP_RETURN candidate and optional OP_RETURN type of BLIND_VOTE, this should be a BLIND_VOTE tx.", want, result);
    hasOpReturnCandidate = true;
    optionalOpReturnType = Optional.of(OpReturnType.VOTE_REVEAL);
    result = TxParser.getBisqTxType(tempTx, hasOpReturnCandidate, remainingInputValue, optionalOpReturnType);
    want = TxType.VOTE_REVEAL;
    Assert.assertEquals("With OP_RETURN candidate and optional OP_RETURN type of VOTE_REVEAL, this should be a VOTE_REVEAL tx.", want, result);
    hasOpReturnCandidate = true;
    optionalOpReturnType = Optional.of(OpReturnType.PROPOSAL);
    result = TxParser.getBisqTxType(tempTx, hasOpReturnCandidate, remainingInputValue, optionalOpReturnType);
    want = TxType.PROPOSAL;
    Assert.assertEquals("With OP_RETURN candidate and optional OP_RETURN type of PROPOSAL, this should be a PROPOSAL tx.", want, result);
    hasOpReturnCandidate = true;
    optionalOpReturnType = Optional.of(OpReturnType.COMPENSATION_REQUEST);
    result = TxParser.getBisqTxType(tempTx, hasOpReturnCandidate, remainingInputValue, optionalOpReturnType);
    want = TxType.INVALID;
    Assert.assertEquals("COMPENSATION_REQUEST has fewer than three outputs, this should be a INVALID tx.", want, result);
    RawTxOutput output1 = new RawTxOutput(0, 123, null, null, null, null, 100);
    RawTxOutput output2 = new RawTxOutput(0, 456, null, null, null, null, 100);
    RawTxOutput output3 = new RawTxOutput(0, 678, null, null, null, null, 100);
    rawTx = new RawTx("faketx1", 200, "fakeblock1", time, ImmutableList.copyOf(inputs), ImmutableList.copyOf(Arrays.asList(output1, output2, output3)));
    tempTx = TempTx.fromRawTx(rawTx);
    hasOpReturnCandidate = true;
    optionalOpReturnType = Optional.of(OpReturnType.COMPENSATION_REQUEST);
    result = TxParser.getBisqTxType(tempTx, hasOpReturnCandidate, remainingInputValue, optionalOpReturnType);
    want = TxType.INVALID;
    Assert.assertEquals("Output 1 at COMPENSATION_REQUEST has to be a ISSUANCE_CANDIDATE_OUTPUT, this should be a INVALID tx.", want, result);
    hasOpReturnCandidate = true;
    optionalOpReturnType = Optional.of(OpReturnType.COMPENSATION_REQUEST);
    tempTx.getTempTxOutputs().get(1).setTxOutputType(TxOutputType.ISSUANCE_CANDIDATE_OUTPUT);
    result = TxParser.getBisqTxType(tempTx, hasOpReturnCandidate, remainingInputValue, optionalOpReturnType);
    want = TxType.COMPENSATION_REQUEST;
    Assert.assertEquals("With OP_RETURN candidate and optional OP_RETURN type of COMPENSATION_REQUEST, this should be a COMPENSATION_REQUEST tx.", want, result);
}
Also used : TempTx(bisq.core.dao.state.blockchain.TempTx) RawTxOutput(bisq.core.dao.state.blockchain.RawTxOutput) TxType(bisq.core.dao.state.blockchain.TxType) RawTx(bisq.core.dao.state.blockchain.RawTx) OpReturnType(bisq.core.dao.state.blockchain.OpReturnType) TxInput(bisq.core.dao.state.blockchain.TxInput) Test(org.junit.Test)

Example 4 with TxInput

use of bisq.core.dao.state.blockchain.TxInput in project bisq-core by bisq-network.

the class BlockParserTest method testIsBsqTx.

// FIXME
@Test
public void testIsBsqTx() {
    // Setup a basic transaction with two inputs
    int height = 200;
    String hash = "abc123";
    long time = new Date().getTime();
    final List<TxInput> inputs = asList(new TxInput("tx1", 0, null), new TxInput("tx1", 1, null));
    final List<RawTxOutput> outputs = asList(new RawTxOutput(0, 101, "tx1", null, null, null, height));
    RawTx rawTx = new RawTx("vo", height, hash, time, ImmutableList.copyOf(inputs), ImmutableList.copyOf(outputs));
    // Return one spendable txoutputs with value, for three test cases
    // 1) - null, 0     -> not BSQ transaction
    // 2) - 100, null   -> BSQ transaction
    // 3) - 0, 100      -> BSQ transaction
    new Expectations(bsqStateService) {

        {
            // Expectations can be recorded on mocked instances, either with specific matching arguments or catch all
            // http://jmockit.github.io/tutorial/Mocking.html#results
            // Results are returned in the order they're recorded, so in this case for the first call to
            // getSpendableTxOutput("tx1", 0) the return value will be Optional.empty()
            // for the second call the return is Optional.of(new TxOutput(0,... and so on
            bsqStateService.getUnspentTxOutput(new TxOutputKey("tx1", 0));
            result = Optional.empty();
            result = Optional.of(new RawTxOutput(0, 100, "txout1", null, null, null, height));
            result = Optional.of(new RawTxOutput(0, 0, "txout1", null, null, null, height));
            bsqStateService.getUnspentTxOutput(new TxOutputKey("tx1", 1));
            result = Optional.of(new RawTxOutput(0, 0, "txout2", null, null, null, height));
            result = Optional.empty();
            result = Optional.of(new RawTxOutput(0, 100, "txout2", null, null, null, height));
        }
    };
    String genesisTxId = "genesisTxId";
    int blockHeight = 200;
    String blockHash = "abc123";
    Coin genesisTotalSupply = Coin.parseCoin("2.5");
    // First time there is no BSQ value to spend so it's not a bsq transaction
    assertFalse(txParser.findTx(rawTx, genesisTxId, blockHeight, genesisTotalSupply).isPresent());
    // Second time there is BSQ in the first txout
    assertTrue(txParser.findTx(rawTx, genesisTxId, blockHeight, genesisTotalSupply).isPresent());
    // Third time there is BSQ in the second txout
    assertTrue(txParser.findTx(rawTx, genesisTxId, blockHeight, genesisTotalSupply).isPresent());
}
Also used : Expectations(mockit.Expectations) Coin(org.bitcoinj.core.Coin) RawTxOutput(bisq.core.dao.state.blockchain.RawTxOutput) RawTx(bisq.core.dao.state.blockchain.RawTx) TxOutputKey(bisq.core.dao.state.blockchain.TxOutputKey) Date(java.util.Date) TxInput(bisq.core.dao.state.blockchain.TxInput) Test(org.junit.Test)

Example 5 with TxInput

use of bisq.core.dao.state.blockchain.TxInput in project bisq-core by bisq-network.

the class BlockParserTest method testParseBlocks.

@Test
public void testParseBlocks() throws BitcoindException, CommunicationException, BlockNotConnectingException, RpcException {
    // Setup blocks to test, starting before genesis
    // Only the transactions related to bsq are relevant, no checks are done on correctness of blocks or other txs
    // so hashes and most other data don't matter
    long time = new Date().getTime();
    int genesisHeight = 200;
    int startHeight = 199;
    int headHeight = 201;
    Coin issuance = Coin.parseCoin("2.5");
    RawTransaction genTx = new RawTransaction("gen block hash", 0, 0L, 0L, genesisTxId);
    // Blockhashes
    String bh199 = "blockhash199";
    String bh200 = "blockhash200";
    String bh201 = "blockhash201";
    // Block 199
    String cbId199 = "cbid199";
    RawTransaction tx199 = new RawTransaction(bh199, 0, 0L, 0L, cbId199);
    RawTx cbTx199 = new RawTx(cbId199, 199, bh199, time, ImmutableList.copyOf(new ArrayList<TxInput>()), ImmutableList.copyOf(asList(new RawTxOutput(0, 25, cbId199, null, null, null, 199))));
    RawBlock block199 = new RawBlock(bh199, 10, 10, 199, 2, "root", asList(tx199), time, Long.parseLong("1234"), "bits", BigDecimal.valueOf(1), "chainwork", "previousBlockHash", bh200);
    // Genesis Block
    String cbId200 = "cbid200";
    RawTransaction tx200 = new RawTransaction(bh200, 0, 0L, 0L, cbId200);
    RawTx cbTx200 = new RawTx(cbId200, 200, bh200, time, ImmutableList.copyOf(new ArrayList<TxInput>()), ImmutableList.copyOf(asList(new RawTxOutput(0, 25, cbId200, null, null, null, 200))));
    RawTx genesisTx = new RawTx(genesisTxId, 200, bh200, time, ImmutableList.copyOf(asList(new TxInput("someoldtx", 0, null))), ImmutableList.copyOf(asList(new RawTxOutput(0, issuance.getValue(), genesisTxId, null, null, null, 200))));
    RawBlock block200 = new RawBlock(bh200, 10, 10, 200, 2, "root", asList(tx200, genTx), time, Long.parseLong("1234"), "bits", BigDecimal.valueOf(1), "chainwork", bh199, bh201);
    // Block 201
    // Make a bsq transaction
    String cbId201 = "cbid201";
    String bsqTx1Id = "bsqtx1";
    RawTransaction tx201 = new RawTransaction(bh201, 0, 0L, 0L, cbId201);
    RawTransaction txbsqtx1 = new RawTransaction(bh201, 0, 0L, 0L, bsqTx1Id);
    long bsqTx1Value1 = Coin.parseCoin("2.4").getValue();
    long bsqTx1Value2 = Coin.parseCoin("0.04").getValue();
    RawTx cbTx201 = new RawTx(cbId201, 201, bh201, time, ImmutableList.copyOf(new ArrayList<TxInput>()), ImmutableList.copyOf(asList(new RawTxOutput(0, 25, cbId201, null, null, null, 201))));
    RawTx bsqTx1 = new RawTx(bsqTx1Id, 201, bh201, time, ImmutableList.copyOf(asList(new TxInput(genesisTxId, 0, null))), ImmutableList.copyOf(asList(new RawTxOutput(0, bsqTx1Value1, bsqTx1Id, null, null, null, 201), new RawTxOutput(1, bsqTx1Value2, bsqTx1Id, null, null, null, 201))));
    RawBlock block201 = new RawBlock(bh201, 10, 10, 201, 2, "root", asList(tx201, txbsqtx1), time, Long.parseLong("1234"), "bits", BigDecimal.valueOf(1), "chainwork", bh200, "nextBlockHash");
// TODO update test with new API
/*
        new Expectations(rpcService) {{
            rpcService.requestBlock(199);
            result = block199;
            rpcService.requestBlock(200);
            result = block200;
            rpcService.requestBlock(201);
            result = block201;

            rpcService.requestTx(cbId199, 199);
            result = cbTx199;
            rpcService.requestTx(cbId200, genesisHeight);
            result = cbTx200;
            rpcService.requestTx(genesisTxId, genesisHeight);
            result = genesisTx;
            rpcService.requestTx(cbId201, 201);
            result = cbTx201;
            rpcService.requestTx(bsqTx1Id, 201);
            result = bsqTx1;
        }};

        // Running parseBlocks to build the bsq blockchain
        fullNodeParser.parseBlocks(startHeight, headHeight, block -> {
        });
*/
// Verify that the genesis tx has been added to the bsq blockchain with the correct issuance amount
/*    assertTrue(bsqStateService.getGenesisTx().get() == genesisTx);
        assertTrue(bsqStateService.getGenesisTotalSupply().getValue() == issuance.getValue());

        // And that other txs are not added
        assertFalse(bsqStateService.containsTx(cbId199));
        assertFalse(bsqStateService.containsTx(cbId200));
        assertFalse(bsqStateService.containsTx(cbId201));

        // But bsq txs are added
        assertTrue(bsqStateService.containsTx(bsqTx1Id));
        TxOutput bsqOut1 = bsqStateService.getUnspentAndMatureTxOutput(bsqTx1Id, 0).get();
        assertTrue(bsqStateService.isUnspent(bsqOut1));
        assertTrue(bsqOut1.getValue() == bsqTx1Value1);
        TxOutput bsqOut2 = bsqStateService.getUnspentAndMatureTxOutput(bsqTx1Id, 1).get();
        assertTrue(bsqStateService.isUnspent(bsqOut2));
        assertTrue(bsqOut2.getValue() == bsqTx1Value2);
        assertFalse(bsqStateService.isTxOutputSpendable(genesisTxId, 0));
        assertTrue(bsqStateService.isTxOutputSpendable(bsqTx1Id, 0));
        assertTrue(bsqStateService.isTxOutputSpendable(bsqTx1Id, 1));*/
}
Also used : Coin(org.bitcoinj.core.Coin) RawTxOutput(bisq.core.dao.state.blockchain.RawTxOutput) RawBlock(com.neemre.btcdcli4j.core.domain.RawBlock) RawTransaction(com.neemre.btcdcli4j.core.domain.RawTransaction) ArrayList(java.util.ArrayList) RawTx(bisq.core.dao.state.blockchain.RawTx) Date(java.util.Date) TxInput(bisq.core.dao.state.blockchain.TxInput) Test(org.junit.Test)

Aggregations

TxInput (bisq.core.dao.state.blockchain.TxInput)8 RawTx (bisq.core.dao.state.blockchain.RawTx)5 RawTxOutput (bisq.core.dao.state.blockchain.RawTxOutput)5 Test (org.junit.Test)4 TempTx (bisq.core.dao.state.blockchain.TempTx)3 TxOutput (bisq.core.dao.state.blockchain.TxOutput)2 TxOutputKey (bisq.core.dao.state.blockchain.TxOutputKey)2 TxType (bisq.core.dao.state.blockchain.TxType)2 RawTransaction (com.neemre.btcdcli4j.core.domain.RawTransaction)2 Date (java.util.Date)2 Slf4j (lombok.extern.slf4j.Slf4j)2 Coin (org.bitcoinj.core.Coin)2 UserThread (bisq.common.UserThread)1 ResultHandler (bisq.common.handlers.ResultHandler)1 Utilities (bisq.common.util.Utilities)1 DaoOptionKeys (bisq.core.dao.DaoOptionKeys)1 CompensationProposal (bisq.core.dao.governance.proposal.compensation.CompensationProposal)1 InvalidGenesisTxException (bisq.core.dao.node.parser.exceptions.InvalidGenesisTxException)1 BsqStateService (bisq.core.dao.state.BsqStateService)1 OpReturnType (bisq.core.dao.state.blockchain.OpReturnType)1