var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { checkDigestSignature } from "../encryption/encryption";
import { gtvHash } from "../gtv";
import { getDigestToSign, rawGtvToGtx } from "../gtx/gtx";
import { decodeValue } from "../gtx/serialization";
import { CanNotFindTxException, DifferentNumberOfSignersException, MissingTransactionProof, ProofRidException, SignatureException, SystemChainException, } from "./error";
export function getClusterOfBlockchain(client, blockchainRID) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            const queryObject = {
                name: "cm_get_blockchain_cluster",
                args: { brid: blockchainRID },
            };
            const clusterName = yield client.query(queryObject);
            return clusterName;
        }
        catch (error) {
            throw new SystemChainException(error.message);
        }
    });
}
export function getClusterInfo(client, name) {
    return __awaiter(this, void 0, void 0, function* () {
        const queryObject = {
            name: "cm_get_cluster_info",
            args: { name },
        };
        try {
            const clusterInfo = yield client.query(queryObject);
            return clusterInfo;
        }
        catch (error) {
            throw new SystemChainException(error.message);
        }
    });
}
export function getAnchoringTransactionForBlockRid(client, blockchainRid, blockRid) {
    return __awaiter(this, void 0, void 0, function* () {
        const queryObject = {
            name: "get_anchoring_transaction_for_block_rid",
            args: { blockchain_rid: blockchainRid, block_rid: blockRid },
        };
        try {
            const anchoringTxForBlockRid = yield client.query(queryObject);
            return anchoringTxForBlockRid;
        }
        catch (error) {
            throw new SystemChainException(error.message);
        }
    });
}
export function calculateBlockRID(decodedTxProof) {
    const sourceBlockHeader = decodedTxProof.blockHeader;
    if (!sourceBlockHeader) {
        throw new Error("Failed to get blockHeader from confirmation proof");
    }
    const decodeSourceBlockRid = decodeValue(sourceBlockHeader);
    return gtvHash(decodeSourceBlockRid);
}
// fetch tx from txRID and verifies with secp256k1.ecdsaVerify that txRID and signer creates signatures that are on the blockchain transaction
export function fetchAndVerifyTransaction(sourceClient, txToProveRID, proofHash, txToProveSigners) {
    return __awaiter(this, void 0, void 0, function* () {
        const rawTx = yield sourceClient.getTransaction(txToProveRID);
        if (rawTx === null) {
            throw new CanNotFindTxException();
        }
        const txGtv = decodeValue(rawTx);
        const fetchedTxHash = gtvHash(txGtv);
        if (Buffer.compare(fetchedTxHash, proofHash)) {
            // We received another hash for tx RID than what was included in proof
            // Possibly rouge or faulty node(s). Anyway, we need to give up.
            throw new MissingTransactionProof(proofHash, fetchedTxHash);
        }
        const fetchedTx = rawGtvToGtx(txGtv);
        if (txToProveSigners.length != fetchedTx.signatures.length) {
            throw new DifferentNumberOfSignersException(fetchedTx.signatures.length, txToProveSigners.length);
        }
        const txRID = getDigestToSign(fetchedTx);
        if (Buffer.compare(txRID, txToProveRID)) {
            throw new ProofRidException();
        }
        for (const signer of txToProveSigners) {
            let hasSignature = false;
            for (const signature of fetchedTx.signatures) {
                // verify that txRID (hash of gtxBody) signed by signers equals the signatures from network
                if (checkDigestSignature(txRID, signer, signature)) {
                    hasSignature = true;
                    break;
                }
            }
            if (!hasSignature)
                throw new SignatureException(signer);
        }
        return { verifiedTx: fetchedTx, verifiedTxHash: fetchedTxHash };
    });
}
//# sourceMappingURL=utils.js.map