Search in sources :

Example 1 with TempTxOutput

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

the class TxParser method getTxTypeForOpReturn.

private static TxType getTxTypeForOpReturn(TempTx tx, OpReturnType opReturnType) {
    switch(opReturnType) {
        case COMPENSATION_REQUEST:
            boolean hasCorrectNumOutputs = tx.getTempTxOutputs().size() >= 3;
            if (!hasCorrectNumOutputs) {
                log.warn("Compensation request tx need to have at least 3 outputs");
                return TxType.INVALID;
            }
            TempTxOutput issuanceTxOutput = tx.getTempTxOutputs().get(1);
            boolean hasIssuanceOutput = issuanceTxOutput.getTxOutputType() == TxOutputType.ISSUANCE_CANDIDATE_OUTPUT;
            if (!hasIssuanceOutput) {
                log.warn("Compensation request txOutput type of output at index 1 need to be ISSUANCE_CANDIDATE_OUTPUT. " + "TxOutputType={}", issuanceTxOutput.getTxOutputType());
                return TxType.INVALID;
            }
            return TxType.COMPENSATION_REQUEST;
        case PROPOSAL:
            return TxType.PROPOSAL;
        case BLIND_VOTE:
            return TxType.BLIND_VOTE;
        case VOTE_REVEAL:
            return TxType.VOTE_REVEAL;
        case LOCKUP:
            return TxType.LOCKUP;
        default:
            log.warn("We got a BSQ tx with fee and unknown OP_RETURN. tx={}", tx);
            return TxType.INVALID;
    }
}
Also used : TempTxOutput(bisq.core.dao.state.blockchain.TempTxOutput)

Example 2 with TempTxOutput

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

the class TxParser method findGenesisTx.

/**
 * Parse and return the genesis transaction for bisq, if applicable.
 *
 * @param genesisTxId         The transaction id of the bisq genesis transaction.
 * @param genesisBlockHeight  The block height of the bisq genesis transaction.
 * @param genesisTotalSupply  The total supply of the genesis issuance for bisq.
 * @param rawTx               The candidate transaction.
 * @return The genesis transaction if applicable, or Optional.empty() otherwise.
 */
public static Optional<TempTx> findGenesisTx(String genesisTxId, int genesisBlockHeight, Coin genesisTotalSupply, RawTx rawTx) {
    boolean isGenesis = rawTx.getBlockHeight() == genesisBlockHeight && rawTx.getId().equals(genesisTxId);
    if (!isGenesis)
        return Optional.empty();
    TempTx tempTx = TempTx.fromRawTx(rawTx);
    tempTx.setTxType(TxType.GENESIS);
    long remainingInputValue = genesisTotalSupply.getValue();
    for (int i = 0; i < tempTx.getTempTxOutputs().size(); ++i) {
        TempTxOutput txOutput = tempTx.getTempTxOutputs().get(i);
        long value = txOutput.getValue();
        boolean isValid = value <= remainingInputValue;
        if (!isValid)
            throw new InvalidGenesisTxException("Genesis tx is invalid; using more than available inputs. " + "Remaining input value is " + remainingInputValue + " sat; tx info: " + tempTx.toString());
        remainingInputValue -= value;
        txOutput.setTxOutputType(TxOutputType.GENESIS_OUTPUT);
    }
    if (remainingInputValue > 0) {
        throw new InvalidGenesisTxException("Genesis tx is invalid; not using all available inputs. " + "Remaining input value is " + remainingInputValue + " sat, tx info: " + tempTx.toString());
    }
    return Optional.of(tempTx);
}
Also used : TempTx(bisq.core.dao.state.blockchain.TempTx) InvalidGenesisTxException(bisq.core.dao.node.parser.exceptions.InvalidGenesisTxException) TempTxOutput(bisq.core.dao.state.blockchain.TempTxOutput)

Example 3 with TempTxOutput

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

the class TxOutputParser method processGenesisTxOutput.

public void processGenesisTxOutput(TempTx genesisTx) {
    for (int i = 0; i < genesisTx.getTempTxOutputs().size(); ++i) {
        TempTxOutput tempTxOutput = genesisTx.getTempTxOutputs().get(i);
        bsqStateService.addUnspentTxOutput(TxOutput.fromTempOutput(tempTxOutput));
    }
}
Also used : TempTxOutput(bisq.core.dao.state.blockchain.TempTxOutput)

Example 4 with TempTxOutput

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

the class TxOutputParser method handleOpReturnOutput.

private void handleOpReturnOutput(TempTxOutput tempTxOutput, boolean isLastOutput) {
    TxOutputType txOutputType = OpReturnParser.getTxOutputType(tempTxOutput, isLastOutput);
    tempTxOutput.setTxOutputType(txOutputType);
    optionalVerifiedOpReturnType = getMappedOpReturnType(txOutputType);
    optionalVerifiedOpReturnType.filter(verifiedOpReturnType -> verifiedOpReturnType == OpReturnType.LOCKUP).ifPresent(verifiedOpReturnType -> {
        byte[] opReturnData = tempTxOutput.getOpReturnData();
        checkNotNull(opReturnData, "opReturnData must not be null");
        int lockTime = BondingConsensus.getLockTime(opReturnData);
        tempTxOutput.setLockTime(lockTime);
    });
}
Also used : TempTx(bisq.core.dao.state.blockchain.TempTx) Setter(lombok.Setter) TempTxOutput(bisq.core.dao.state.blockchain.TempTxOutput) Getter(lombok.Getter) TxOutput(bisq.core.dao.state.blockchain.TxOutput) Preconditions.checkNotNull(com.google.common.base.Preconditions.checkNotNull) BsqStateService(bisq.core.dao.state.BsqStateService) BondingConsensus(bisq.core.dao.bonding.BondingConsensus) TxOutputType(bisq.core.dao.state.blockchain.TxOutputType) OpReturnType(bisq.core.dao.state.blockchain.OpReturnType) Slf4j(lombok.extern.slf4j.Slf4j) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) Optional(java.util.Optional) VisibleForTesting(com.google.common.annotations.VisibleForTesting) TxOutputType(bisq.core.dao.state.blockchain.TxOutputType)

Example 5 with TempTxOutput

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

the class TxParser method processOpReturnType.

private void processOpReturnType(int blockHeight, TempTx tempTx) {
    // We might have a opReturn output
    OpReturnType verifiedOpReturnType = null;
    Optional<OpReturnType> optionalVerifiedOpReturnType = txOutputParser.getOptionalVerifiedOpReturnType();
    if (optionalVerifiedOpReturnType.isPresent()) {
        verifiedOpReturnType = optionalVerifiedOpReturnType.get();
        long bsqFee = remainingInputValue;
        boolean isFeeAndPhaseValid;
        switch(verifiedOpReturnType) {
            case PROPOSAL:
                isFeeAndPhaseValid = isFeeAndPhaseValid(blockHeight, bsqFee, DaoPhase.Phase.PROPOSAL, Param.PROPOSAL_FEE);
                if (!isFeeAndPhaseValid) {
                    tempTx.setTxType(TxType.INVALID);
                }
                break;
            case COMPENSATION_REQUEST:
                isFeeAndPhaseValid = isFeeAndPhaseValid(blockHeight, bsqFee, DaoPhase.Phase.PROPOSAL, Param.PROPOSAL_FEE);
                Optional<TempTxOutput> optionalIssuanceCandidate = txOutputParser.getOptionalIssuanceCandidate();
                if (isFeeAndPhaseValid) {
                    if (optionalIssuanceCandidate.isPresent()) {
                        // Now after we have validated the opReturn data we will apply the TxOutputType
                        optionalIssuanceCandidate.get().setTxOutputType(TxOutputType.ISSUANCE_CANDIDATE_OUTPUT);
                    } else {
                        log.warn("It can be that we have a opReturn which is correct from its structure but the whole tx " + "in not valid as the issuanceCandidate in not there. " + "As the BSQ fee is set it must be either a buggy tx or an manually crafted invalid tx.");
                    }
                } else {
                    tempTx.setTxType(TxType.INVALID);
                    optionalIssuanceCandidate.ifPresent(tempTxOutput -> tempTxOutput.setTxOutputType(TxOutputType.BTC_OUTPUT));
                // Empty Optional case is a possible valid case where a random tx matches our opReturn rules but it is not a
                // valid BSQ tx.
                }
                break;
            case BLIND_VOTE:
                isFeeAndPhaseValid = isFeeAndPhaseValid(blockHeight, bsqFee, DaoPhase.Phase.BLIND_VOTE, Param.BLIND_VOTE_FEE);
                if (!isFeeAndPhaseValid) {
                    tempTx.setTxType(TxType.INVALID);
                    Optional<TempTxOutput> optionalBlindVoteLockStakeOutput = txOutputParser.getOptionalBlindVoteLockStakeOutput();
                    optionalBlindVoteLockStakeOutput.ifPresent(tempTxOutput -> tempTxOutput.setTxOutputType(TxOutputType.BTC_OUTPUT));
                // Empty Optional case is a possible valid case where a random tx matches our opReturn rules but it is not a
                // valid BSQ tx.
                }
                break;
            case VOTE_REVEAL:
                boolean isPhaseValid = isPhaseValid(blockHeight, DaoPhase.Phase.VOTE_REVEAL);
                boolean isVoteRevealInputInValid = txInputParser.getVoteRevealInputState() != TxInputParser.VoteRevealInputState.VALID;
                if (!isPhaseValid) {
                    tempTx.setTxType(TxType.INVALID);
                }
                if (!isPhaseValid || isVoteRevealInputInValid) {
                    Optional<TempTxOutput> optionalVoteRevealUnlockStakeOutput = txOutputParser.getOptionalVoteRevealUnlockStakeOutput();
                    optionalVoteRevealUnlockStakeOutput.ifPresent(tempTxOutput -> tempTxOutput.setTxOutputType(TxOutputType.BTC_OUTPUT));
                // Empty Optional case is a possible valid case where a random tx matches our opReturn rules but it is not a
                // valid BSQ tx.
                }
                break;
            case LOCKUP:
                // do nothing
                break;
        }
    }
    // set the output to a BTC output. We must not use if else cases here!
    if (verifiedOpReturnType != OpReturnType.COMPENSATION_REQUEST) {
        txOutputParser.getOptionalIssuanceCandidate().ifPresent(tempTxOutput -> tempTxOutput.setTxOutputType(TxOutputType.BTC_OUTPUT));
    }
    if (verifiedOpReturnType != OpReturnType.BLIND_VOTE) {
        txOutputParser.getOptionalBlindVoteLockStakeOutput().ifPresent(tempTxOutput -> tempTxOutput.setTxOutputType(TxOutputType.BTC_OUTPUT));
    }
    if (verifiedOpReturnType != OpReturnType.VOTE_REVEAL) {
        txOutputParser.getOptionalVoteRevealUnlockStakeOutput().ifPresent(tempTxOutput -> tempTxOutput.setTxOutputType(TxOutputType.BTC_OUTPUT));
    }
    if (verifiedOpReturnType != OpReturnType.LOCKUP) {
        txOutputParser.getOptionalLockupOutput().ifPresent(tempTxOutput -> tempTxOutput.setTxOutputType(TxOutputType.BTC_OUTPUT));
    }
}
Also used : TempTxOutput(bisq.core.dao.state.blockchain.TempTxOutput) OpReturnType(bisq.core.dao.state.blockchain.OpReturnType)

Aggregations

TempTxOutput (bisq.core.dao.state.blockchain.TempTxOutput)6 TempTx (bisq.core.dao.state.blockchain.TempTx)3 OpReturnType (bisq.core.dao.state.blockchain.OpReturnType)2 BondingConsensus (bisq.core.dao.bonding.BondingConsensus)1 InvalidGenesisTxException (bisq.core.dao.node.parser.exceptions.InvalidGenesisTxException)1 BsqStateService (bisq.core.dao.state.BsqStateService)1 TxInput (bisq.core.dao.state.blockchain.TxInput)1 TxOutput (bisq.core.dao.state.blockchain.TxOutput)1 TxOutputKey (bisq.core.dao.state.blockchain.TxOutputKey)1 TxOutputType (bisq.core.dao.state.blockchain.TxOutputType)1 TxType (bisq.core.dao.state.blockchain.TxType)1 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1 Preconditions.checkArgument (com.google.common.base.Preconditions.checkArgument)1 Preconditions.checkNotNull (com.google.common.base.Preconditions.checkNotNull)1 Optional (java.util.Optional)1 Getter (lombok.Getter)1 Setter (lombok.Setter)1 Slf4j (lombok.extern.slf4j.Slf4j)1