/// Gathers commitments and sum them. public static Commitment sum_commitments(this ICommitted committed, Secp256K1 secp) { // first, verify each range proof foreach (var output in committed.outputs_committed()) { output.Verify_proof(secp); } // then gather the commitments var inputCommits = new List <Commitment>(); foreach (var input in committed.inputs_commited()) { inputCommits.Add(input.Commitment); } var outputCommits = new List <Commitment>(); foreach (var output in committed.outputs_committed()) { outputCommits.Add(output.Commit); } // add the overage as output commitment if positive, as an input commitment if // negative if (committed.Overage() != 0) { var overCommit = secp.commit_value((ulong)Math.Abs(committed.Overage())); if (committed.Overage() < 0) { inputCommits.Add(overCommit); } else { outputCommits.Add(overCommit); } } // sum all that stuff return(secp.commit_sum(outputCommits.ToArray(), inputCommits.ToArray())); }
/// Verifies the sum of input/output commitments match the sum in kernels /// and that all kernel signatures are valid. /// TODO - when would we skip_sig? Is this needed or used anywhere? public void verify_kernels(Secp256K1 secp, bool skipSig) { foreach (var k in Kernels) { if ((k.Fee & 1) != 0) { //throw new BlockErrorException(BlockError.OddKernelFee); } if (k.LockHeight > Header.Height) { throw new BlockErrorException(BlockError.KernelLockHeight).Data("lock_height", k.LockHeight); } // sum all inputs and outs commitments var ioSum = this.sum_commitments(secp); // sum all kernels commitments var proofCommits = Kernels.Select(s => s.Excess).ToArray(); var proofSum = secp.commit_sum(proofCommits, new Commitment[] { }); // both should be the same if (proofSum.Hex != ioSum.Hex) { throw new BlockErrorException(BlockError.KernelSumMismatch); } // verify all signatures with the commitment as pk if (!skipSig) { foreach (var proof in Kernels) { proof.Verify(secp); } } } }