Search in sources :

Example 1 with RedeemScriptParser

use of co.rsk.bitcoinj.script.RedeemScriptParser in project rskj by rsksmart.

the class BridgeUtils method countMissingSignatures.

/**
 * Return the amount of missing signatures for a tx.
 * @param btcContext Btc context
 * @param btcTx The btc tx to check
 * @return 0 if was signed by the required number of federators, amount of missing signatures otherwise
 */
public static int countMissingSignatures(Context btcContext, BtcTransaction btcTx) {
    // Check missing signatures for only one input as it is not
    // possible for a federator to leave unsigned inputs in a tx
    Context.propagate(btcContext);
    int unsigned = 0;
    TransactionInput input = btcTx.getInput(0);
    Script scriptSig = input.getScriptSig();
    List<ScriptChunk> chunks = scriptSig.getChunks();
    Script redeemScript = new Script(chunks.get(chunks.size() - 1).data);
    RedeemScriptParser parser = RedeemScriptParserFactory.get(redeemScript.getChunks());
    MultiSigType multiSigType;
    int lastChunk;
    multiSigType = parser.getMultiSigType();
    if (multiSigType == MultiSigType.STANDARD_MULTISIG || multiSigType == MultiSigType.FAST_BRIDGE_MULTISIG) {
        lastChunk = chunks.size() - 1;
    } else {
        lastChunk = chunks.size() - 2;
    }
    for (int i = 1; i < lastChunk; i++) {
        ScriptChunk chunk = chunks.get(i);
        if (!chunk.isOpCode() && chunk.data.length == 0) {
            unsigned++;
        }
    }
    return unsigned;
}
Also used : Script(co.rsk.bitcoinj.script.Script) MultiSigType(co.rsk.bitcoinj.script.RedeemScriptParser.MultiSigType) ScriptChunk(co.rsk.bitcoinj.script.ScriptChunk) RedeemScriptParser(co.rsk.bitcoinj.script.RedeemScriptParser)

Example 2 with RedeemScriptParser

use of co.rsk.bitcoinj.script.RedeemScriptParser in project rskj by rsksmart.

the class BridgeUtils method isValidPegInTx.

/**
 * It checks if the tx doesn't spend any of the federations' funds and if it sends more than
 * the minimum ({@see BridgeConstants::getMinimumLockTxValue}) to any of the federations
 * @param tx the BTC transaction to check
 * @param activeFederations the active federations
 * @param retiredFederationP2SHScript the retired federation P2SHScript. Could be {@code null}.
 * @param btcContext the BTC Context
 * @param bridgeConstants the Bridge constants
 * @param activations the network HF activations configuration
 * @return true if this is a valid peg-in transaction
 */
public static boolean isValidPegInTx(BtcTransaction tx, List<Federation> activeFederations, Script retiredFederationP2SHScript, Context btcContext, BridgeConstants bridgeConstants, ActivationConfig.ForBlock activations) {
    // optionally sending some change to any of the federation addresses)
    for (int i = 0; i < tx.getInputs().size(); i++) {
        final int index = i;
        if (activeFederations.stream().anyMatch(federation -> scriptCorrectlySpendsTx(tx, index, federation.getP2SHScript()))) {
            return false;
        }
        if (retiredFederationP2SHScript != null && scriptCorrectlySpendsTx(tx, index, retiredFederationP2SHScript)) {
            return false;
        }
        // erp federation, or even a retired fast bridge or erp federation
        if (activations.isActive(ConsensusRule.RSKIP201)) {
            RedeemScriptParser redeemScriptParser = RedeemScriptParserFactory.get(tx.getInput(index).getScriptSig().getChunks());
            try {
                Script inputStandardRedeemScript = redeemScriptParser.extractStandardRedeemScript();
                if (activeFederations.stream().anyMatch(federation -> federation.getStandardRedeemScript().equals(inputStandardRedeemScript))) {
                    return false;
                }
                Script outputScript = ScriptBuilder.createP2SHOutputScript(inputStandardRedeemScript);
                if (outputScript.equals(retiredFederationP2SHScript)) {
                    return false;
                }
            } catch (ScriptException e) {
            // There is no redeem script, could be a peg-in from a P2PKH address
            }
        }
    }
    Wallet federationsWallet = BridgeUtils.getFederationsNoSpendWallet(btcContext, activeFederations, false, null);
    Coin valueSentToMe = tx.getValueSentToMe(federationsWallet);
    Coin minimumPegInTxValue = activations.isActive(ConsensusRule.RSKIP219) ? bridgeConstants.getMinimumPeginTxValueInSatoshis() : bridgeConstants.getLegacyMinimumPeginTxValueInSatoshis();
    if (valueSentToMe.isLessThan(minimumPegInTxValue)) {
        logger.warn("[btctx:{}] Someone sent to the federation less than {} satoshis", tx.getHash(), minimumPegInTxValue);
    }
    return valueSentToMe.isPositive() && !valueSentToMe.isLessThan(minimumPegInTxValue);
}
Also used : Script(co.rsk.bitcoinj.script.Script) Wallet(co.rsk.bitcoinj.wallet.Wallet) RedeemScriptParser(co.rsk.bitcoinj.script.RedeemScriptParser)

Example 3 with RedeemScriptParser

use of co.rsk.bitcoinj.script.RedeemScriptParser in project rskj by rsksmart.

the class FastBridgeCompatibleBtcWallet method findRedeemDataFromScriptHash.

@Nullable
@Override
public RedeemData findRedeemDataFromScriptHash(byte[] payToScriptHash) {
    Optional<FastBridgeFederationInformation> fastBridgeFederationInformation = this.getFastBridgeFederationInformation(payToScriptHash);
    if (fastBridgeFederationInformation.isPresent()) {
        FastBridgeFederationInformation fastBridgeFederationInformationInstance = fastBridgeFederationInformation.get();
        Optional<Federation> destinationFederation = getDestinationFederation(fastBridgeFederationInformationInstance.getFederationRedeemScriptHash());
        if (!destinationFederation.isPresent()) {
            return null;
        }
        Federation destinationFederationInstance = destinationFederation.get();
        Script fedRedeemScript = destinationFederationInstance.getRedeemScript();
        RedeemScriptParser parser = RedeemScriptParserFactory.get(fedRedeemScript.getChunks());
        Script fastBridgeRedeemScript;
        if (parser.getMultiSigType() == MultiSigType.ERP_FED) {
            fastBridgeRedeemScript = FastBridgeErpRedeemScriptParser.createFastBridgeErpRedeemScript(fedRedeemScript, Sha256Hash.wrap(fastBridgeFederationInformationInstance.getDerivationHash().getBytes()));
        } else {
            fastBridgeRedeemScript = FastBridgeRedeemScriptParser.createMultiSigFastBridgeRedeemScript(fedRedeemScript, Sha256Hash.wrap(fastBridgeFederationInformationInstance.getDerivationHash().getBytes()));
        }
        return RedeemData.of(destinationFederationInstance.getBtcPublicKeys(), fastBridgeRedeemScript);
    }
    return super.findRedeemDataFromScriptHash(payToScriptHash);
}
Also used : Script(co.rsk.bitcoinj.script.Script) FastBridgeRedeemScriptParser(co.rsk.bitcoinj.script.FastBridgeRedeemScriptParser) RedeemScriptParser(co.rsk.bitcoinj.script.RedeemScriptParser) FastBridgeErpRedeemScriptParser(co.rsk.bitcoinj.script.FastBridgeErpRedeemScriptParser) FastBridgeFederationInformation(co.rsk.peg.fastbridge.FastBridgeFederationInformation) Nullable(javax.annotation.Nullable)

Example 4 with RedeemScriptParser

use of co.rsk.bitcoinj.script.RedeemScriptParser in project rskj by rsksmart.

the class BridgeUtils method hasEnoughSignatures.

/**
 * Checks whether a btc tx has been signed by the required number of federators.
 * @param btcContext Btc context
 * @param btcTx The btc tx to check
 * @return True if was signed by the required number of federators, false otherwise
 */
public static boolean hasEnoughSignatures(Context btcContext, BtcTransaction btcTx) {
    // When the tx is constructed OP_0 are placed where signature should go.
    // Check all OP_0 have been replaced with actual signatures in all inputs
    Context.propagate(btcContext);
    Script scriptSig;
    List<ScriptChunk> chunks;
    Script redeemScript;
    RedeemScriptParser parser;
    MultiSigType multiSigType;
    int lastChunk;
    for (TransactionInput input : btcTx.getInputs()) {
        scriptSig = input.getScriptSig();
        chunks = scriptSig.getChunks();
        redeemScript = new Script(chunks.get(chunks.size() - 1).data);
        parser = RedeemScriptParserFactory.get(redeemScript.getChunks());
        multiSigType = parser.getMultiSigType();
        if (multiSigType == MultiSigType.STANDARD_MULTISIG || multiSigType == MultiSigType.FAST_BRIDGE_MULTISIG) {
            lastChunk = chunks.size() - 1;
        } else {
            lastChunk = chunks.size() - 2;
        }
        for (int i = 1; i < lastChunk; i++) {
            ScriptChunk chunk = chunks.get(i);
            if (!chunk.isOpCode() && chunk.data.length == 0) {
                return false;
            }
        }
    }
    return true;
}
Also used : Script(co.rsk.bitcoinj.script.Script) MultiSigType(co.rsk.bitcoinj.script.RedeemScriptParser.MultiSigType) ScriptChunk(co.rsk.bitcoinj.script.ScriptChunk) RedeemScriptParser(co.rsk.bitcoinj.script.RedeemScriptParser)

Example 5 with RedeemScriptParser

use of co.rsk.bitcoinj.script.RedeemScriptParser in project rskj by rsksmart.

the class BridgeUtils method isPegOutTx.

public static boolean isPegOutTx(BtcTransaction tx, ActivationConfig.ForBlock activations, Script... p2shScript) {
    int inputsSize = tx.getInputs().size();
    for (int i = 0; i < inputsSize; i++) {
        TransactionInput txInput = tx.getInput(i);
        Optional<Script> redeemScriptOptional = extractRedeemScriptFromInput(tx.getInput(i));
        if (!redeemScriptOptional.isPresent()) {
            continue;
        }
        Script redeemScript = redeemScriptOptional.get();
        if (activations.isActive(ConsensusRule.RSKIP201)) {
            // Extract standard redeem script since the registered utxo could be from a fast bridge or erp federation
            RedeemScriptParser redeemScriptParser = RedeemScriptParserFactory.get(txInput.getScriptSig().getChunks());
            try {
                redeemScript = redeemScriptParser.extractStandardRedeemScript();
            } catch (ScriptException e) {
                // There is no redeem script
                continue;
            }
        }
        Script outputScript = ScriptBuilder.createP2SHOutputScript(redeemScript);
        if (Stream.of(p2shScript).anyMatch(federationPayScript -> federationPayScript.equals(outputScript))) {
            return true;
        }
    }
    return false;
}
Also used : Script(co.rsk.bitcoinj.script.Script) RedeemScriptParser(co.rsk.bitcoinj.script.RedeemScriptParser)

Aggregations

RedeemScriptParser (co.rsk.bitcoinj.script.RedeemScriptParser)5 Script (co.rsk.bitcoinj.script.Script)5 MultiSigType (co.rsk.bitcoinj.script.RedeemScriptParser.MultiSigType)2 ScriptChunk (co.rsk.bitcoinj.script.ScriptChunk)2 FastBridgeErpRedeemScriptParser (co.rsk.bitcoinj.script.FastBridgeErpRedeemScriptParser)1 FastBridgeRedeemScriptParser (co.rsk.bitcoinj.script.FastBridgeRedeemScriptParser)1 Wallet (co.rsk.bitcoinj.wallet.Wallet)1 FastBridgeFederationInformation (co.rsk.peg.fastbridge.FastBridgeFederationInformation)1 Nullable (javax.annotation.Nullable)1