Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Confidential Transactions #325

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
208 changes: 208 additions & 0 deletions Sources/zkp/Surjection.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
//
// Surjection.swift
// GigaBitcoin/secp256k1.swift
//
// Copyright (c) 2023 GigaBitcoin LLC
// Distributed under the MIT software license
//
// See the accompanying file LICENSE for information
//

import Foundation
import zkp_bindings

// MARK: - secp256k1 + SurjectionProof

public extension secp256k1 {
enum Surjection {
struct Proof {
let length = Int(32 * (1 + SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS))
/// Total number of input asset tags
public let nInputs: Int
/// Bitmap of which input tags are used in the surjection proof
public let usedInputs: Data
/// Borromean signature: e0, scalars
public let rawRepresentation: Data
/// The index of the actual input that is secretly mapped to the output
public let inputIndex: Int
/// The ephemeral asset tag of the output
public let ephemeralOutputTag: Data
/// the blinding key of the output
public let blindingKey: [UInt8]

/// Surjection proof initialization and generation functions
@usableFromInline init(
fixedInputTags: [secp256k1_fixed_asset_tag],
ephemeralInputTags: [secp256k1_generator],
inputBlindingKey: [UInt8]
) throws {
var outSurjectionProof = secp256k1_surjectionproof()
var ephemeralOutputTag = secp256k1_generator()
var outputBlindingKey = [UInt8](repeating: 0, count: 64)
var outInputIndex = 0
var fixedOutputTag = secp256k1_fixed_asset_tag()
var randomSeed: Int8 = 3
var proofData = [UInt8](repeating: 0, count: length)

guard secp256k1_surjectionproof_initialize(
secp256k1.Context.raw,
&outSurjectionProof,
&outInputIndex,
fixedInputTags,
fixedInputTags.count,
fixedInputTags.count,
&fixedOutputTag,
100,
&randomSeed
).boolValue,
secp256k1_surjectionproof_generate(
secp256k1.Context.raw,
&outSurjectionProof,
ephemeralInputTags,
ephemeralInputTags.count,
&ephemeralOutputTag,
outInputIndex,
inputBlindingKey,
&outputBlindingKey
).boolValue else {
throw secp256k1Error.underlyingCryptoError
}

secp256k1_swift_surjection_proof_parse(&proofData, outSurjectionProof)

self.blindingKey = outputBlindingKey
self.nInputs = outSurjectionProof.n_inputs
self.inputIndex = outInputIndex
self.usedInputs = Data(outSurjectionProof.used_inputs)
self.rawRepresentation = Data(proofData)
self.ephemeralOutputTag = Data(ephemeralOutputTag.data)
}

static func verify(
proof: inout secp256k1_surjectionproof,
ephemeralInputTags: [secp256k1_generator],
ephemeralOutputTag: inout secp256k1_generator
) -> Bool {
secp256k1_surjectionproof_verify(
secp256k1.Context.raw,
&proof,
ephemeralInputTags,
ephemeralInputTags.count,
&ephemeralOutputTag
).boolValue
}
}
}
}

internal extension Data {
init(_ usedInputs: UsedInputsType) {
self = Data(Swift.withUnsafeBytes(of: usedInputs) { [UInt8]($0) })
}

init(_ ephemeralTag: EphemeralTagType) {
self = Data(Swift.withUnsafeBytes(of: ephemeralTag) { [UInt8]($0) })
}
}

typealias UsedInputsType = (
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8
)

typealias EphemeralTagType = (
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8,
UInt8
)
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Utility.h
// secp256k1_swift.h
// GigaBitcoin/secp256k1.swift
//
// Copyright (c) 2021 GigaBitcoin LLC
Expand All @@ -9,6 +9,7 @@
//

#include "./secp256k1.h"
#include "./secp256k1_surjectionproof.h"

/// Exposes secp256k1 memczero implementation to the bindings target
/// @param s pointer to an array to be zero'd by the function
Expand All @@ -21,3 +22,13 @@ void secp256k1_swift_memczero(void *s, size_t len, int flag);
/// @param input a pointer to the data to be hashed
/// @param len the length of the data to be hashed
void secp256k1_swift_sha256(unsigned char *output, const unsigned char *input, size_t len);

/// Parse a surjection proof
/// @param data Borromean signature: e0, scalars
/// @param proof data structure that holds a parsed surjection proof
void secp256k1_swift_surjection_proof_parse(const unsigned char *data, secp256k1_surjectionproof proof);

/// Serialize a surjection proof
/// @param proof data structure that holds a parsed surjection proof
/// @param data Borromean signature: e0, scalars
void secp256k1_swift_surjection_proof_serialize(secp256k1_surjectionproof proof, const unsigned char *data);
31 changes: 0 additions & 31 deletions Sources/zkp_bindings/src/Utility.c

This file was deleted.

45 changes: 45 additions & 0 deletions Sources/zkp_bindings/src/secp256k1_swift.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// secp256k1_swift.c
// GigaBitcoin/secp256k1.swift
//
// Copyright (c) 2021 GigaBitcoin LLC
// Distributed under the MIT software license
//
// See the accompanying file LICENSE for information
//

#include "../include/secp256k1_swift.h"
#include "../src/hash_impl.h"

/// Exposes secp256k1 memczero implementation to the bindings target
/// @param s pointer to an array to be zero'd by the function
/// @param len the length of the data to be zero'd
/// @param flag zero memory if flag == 1. Flag must be 0 or 1. Constant time.
void secp256k1_swift_memczero(void *s, size_t len, int flag) {
secp256k1_memczero(s, len, flag);
}

/// Exposes secp256k1 SHA256 implementation to the bindings target
/// @param output pointer to an array to be filled by the function
/// @param input a pointer to the data to be hashed
/// @param len the length of the data to be hashed
void secp256k1_swift_sha256(unsigned char *output, const unsigned char *input, size_t len) {
secp256k1_sha256 hasher;
secp256k1_sha256_initialize(&hasher);
secp256k1_sha256_write(&hasher, input, len);
secp256k1_sha256_finalize(&hasher, output);
}

/// Parse a surjection proof
/// @param data Borromean signature: e0, scalars
/// @param proof data structure that holds a parsed surjection proof
void secp256k1_swift_surjection_proof_parse(const unsigned char *data, secp256k1_surjectionproof proof) {
data = proof.data;
}

/// Serialize a surjection proof
/// @param proof data structure that holds a parsed surjection proof
/// @param data Borromean signature: e0, scalars
void secp256k1_swift_surjection_proof_serialize(secp256k1_surjectionproof proof, const unsigned char *data) {
memcpy(proof.data, &data, sizeof data);
}