mergeTxInput :: [Tx] -> Tx -> (ScriptOutput, Int) -> Either String Tx
mergeTxInput txs tx (so, i) = do
    -- Ignore transactions with empty inputs
    let ins = map (scriptInput . (!! i) . txIn) txs
    sigRes <- mapM extractSigs $ filter (not . BS.null) ins
    let rdm = snd $ head sigRes
    unless (all (== rdm) $ map snd sigRes) $
        Left "Redeem scripts do not match"
    si <- encodeInputBS <$> go (nub $ concat $ map fst sigRes) so rdm
    return tx{ txIn = updateIndex i (txIn tx) (\ti -> ti{ scriptInput = si }) }
  where
    go allSigs out rdmM = case out of
        PayMulSig msPubs r ->
            let sigs = take r $ catMaybes $ matchTemplate allSigs msPubs $ f out
            in return $ RegularInput $ SpendMulSig sigs
        PayScriptHash _ -> case rdmM of
            Just rdm -> do
                si <- go allSigs rdm Nothing
                return $ ScriptHashInput (getRegularInput si) rdm
            _ -> Left "Invalid output script type"
        _ -> Left "Invalid output script type"
    extractSigs si = case decodeInputBS si of
        Right (RegularInput (SpendMulSig sigs)) -> Right (sigs, Nothing)
        Right (ScriptHashInput (SpendMulSig sigs) rdm) -> Right (sigs, Just rdm)
        _ -> Left "Invalid script input type"
    f out (TxSignature x sh) p =
        verifySig (txSigHash tx (encodeOutput out) i sh) x p

{- Tx verification -}

-- | Verify if a transaction is valid and all of its inputs are standard.
mergeTxInput :: [Tx] -> Tx -> (ScriptOutput, Int) -> Either String Tx
mergeTxInput txs tx (so, i) = do
    -- Ignore transactions with empty inputs
    let ins = map (scriptInput . (!! i) . txIn) txs
    sigRes <- mapM extractSigs $ filter (not . BS.null) ins
    let rdm = snd $ head sigRes
    unless (all (== rdm) $ map snd sigRes) $
        Left "Redeem scripts do not match"
    si <- encodeInputBS <$> go (nub $ concat $ map fst sigRes) so rdm
    return tx{ txIn = updateIndex i (txIn tx) (\ti -> ti{ scriptInput = si }) }
  where
    go allSigs out rdmM = case out of
        PayMulSig msPubs r ->
            let sigs = take r $ catMaybes $ matchTemplate allSigs msPubs $ f out
            in return $ RegularInput $ SpendMulSig sigs
        PayScriptHash _ -> case rdmM of
            Just rdm -> do
                si <- go allSigs rdm Nothing
                return $ ScriptHashInput (getRegularInput si) rdm
            _ -> Left "Invalid output script type"
        _ -> Left "Invalid output script type"
    extractSigs si = case decodeInputBS si of
        Right (RegularInput (SpendMulSig sigs)) -> Right (sigs, Nothing)
        Right (ScriptHashInput (SpendMulSig sigs) rdm) -> Right (sigs, Just rdm)
        _ -> Left "Invalid script input type"
    f out (TxSignature x sh) p =
        verifySig (txSigHash tx (encodeOutput out) i sh) x p

{- Tx verification -}

-- | Verify if a transaction is valid and all of its inputs are standard.
mergeTxInput txs tx (so, i) = do
    -- Ignore transactions with empty inputs
    let ins = map (scriptInput . (!! i) . txIn) txs
    sigRes <- mapM extractSigs $ filter (not . BS.null) ins
    let rdm = snd $ head sigRes
    unless (all (== rdm) $ map snd sigRes) $
        Left "Redeem scripts do not match"
    si <- encodeInputBS <$> go (nub $ concat $ map fst sigRes) so rdm
    return tx{ txIn = updateIndex i (txIn tx) (\ti -> ti{ scriptInput = si }) }
  where
    go allSigs out rdmM = case out of
        PayMulSig msPubs r ->
            let sigs = take r $ catMaybes $ matchTemplate allSigs msPubs $ f out
            in return $ RegularInput $ SpendMulSig sigs
        PayScriptHash _ -> case rdmM of
            Just rdm -> do
                si <- go allSigs rdm Nothing
                return $ ScriptHashInput (getRegularInput si) rdm
            _ -> Left "Invalid output script type"
        _ -> Left "Invalid output script type"
    extractSigs si = case decodeInputBS si of
        Right (RegularInput (SpendMulSig sigs)) -> Right (sigs, Nothing)
        Right (ScriptHashInput (SpendMulSig sigs) rdm) -> Right (sigs, Just rdm)
        _ -> Left "Invalid script input type"
    f out (TxSignature x sh) p =
        verifySig (txSigHash tx (encodeOutput out) i sh) x p

{- Tx verification -}

-- | Verify if a transaction is valid and all of its inputs are standard.