Re-license bitcoin-serai to MIT

It's pretty basic code, yet would still be quite pleasant to the larger
community.

Also adds documentation.
This commit is contained in:
Luke Parker 2023-01-31 09:28:03 -05:00
parent 86ad947261
commit df75782e54
No known key found for this signature in database
5 changed files with 52 additions and 20 deletions

View file

@ -2,11 +2,10 @@
name = "bitcoin-serai"
version = "0.1.0"
description = "A Bitcoin library for FROST-signing transactions"
license = "AGPL-3.0-only"
license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/coins/bitcoin"
authors = ["Luke Parker <lukeparker5132@gmail.com>", "Vrx <vrx00@proton.me>"]
edition = "2021"
publish = false
[dependencies]
lazy_static = "1"
@ -21,9 +20,12 @@ bitcoin = { version = "0.29", features = ["serde"] }
k256 = { version = "0.11", features = ["arithmetic"] }
transcript = { package = "flexible-transcript", path = "../../crypto/transcript", version = "0.2", features = ["recommended"] }
frost = { version = "0.5", package = "modular-frost", path = "../../crypto/frost", features = ["secp256k1", "tests"] }
frost = { version = "0.5", package = "modular-frost", path = "../../crypto/frost", features = ["secp256k1"] }
hex = "0.4"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
reqwest = { version = "0.11", features = ["json"] }
[dev-dependencies]
frost = { version = "0.5", package = "modular-frost", path = "../../crypto/frost", features = ["tests"] }

View file

@ -1,15 +1,21 @@
AGPL-3.0-only license
MIT License
Copyright (c) 2022-2023 Luke Parker
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License Version 3 as
published by the Free Software Foundation.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -14,17 +14,19 @@ use bitcoin::XOnlyPublicKey;
use frost::{algorithm::Hram, curve::Secp256k1};
/// Get the x coordinate of a non-infinity, even point.
/// Get the x coordinate of a non-infinity, even point. Panics on invalid input.
pub fn x(key: &ProjectivePoint) -> [u8; 32] {
let encoded = key.to_encoded_point(true);
assert_eq!(encoded.tag(), Tag::CompressedEvenY);
(*encoded.x().expect("point at infinity")).into()
}
/// Convert a non-infinite even point to a XOnlyPublicKey. Panics on invalid input.
pub fn x_only(key: &ProjectivePoint) -> XOnlyPublicKey {
XOnlyPublicKey::from_slice(&x(key)).unwrap()
}
/// Make a point even, returning the even version and the offset required for it to be even.
pub fn make_even(mut key: ProjectivePoint) -> (ProjectivePoint, u64) {
let mut c = 0;
while key.to_encoded_point(true).tag() == Tag::CompressedOddY {
@ -34,7 +36,8 @@ pub fn make_even(mut key: ProjectivePoint) -> (ProjectivePoint, u64) {
(key, c)
}
#[derive(Clone)]
/// A BIP-340 compatible HRAm for use with the modular-frost Schnorr Algorithm.
#[derive(Clone, Copy, Debug)]
pub struct BitcoinHram {}
lazy_static! {

View file

@ -1,5 +1,8 @@
/// Cryptographic helpers.
pub mod crypto;
/// Wallet functionality to create transactions.
pub mod wallet;
/// A minimal async RPC.
pub mod rpc;
#[cfg(test)]

View file

@ -1,5 +1,5 @@
use std::{
io::{self, Read},
io::{self, Read, Write},
collections::HashMap,
};
@ -17,25 +17,32 @@ use frost::{
use bitcoin::{
hashes::Hash,
consensus::encode::{Encodable, Decodable, serialize},
consensus::encode::{Decodable, serialize},
util::sighash::{SchnorrSighashType, SighashCache, Prevouts},
OutPoint, Script, Sequence, Witness, TxIn, TxOut, PackedLockTime, Transaction, Address,
};
use crate::crypto::{BitcoinHram, make_even};
/// A spendable output.
#[derive(Clone, Debug)]
pub struct SpendableOutput {
/// The scalar offset to obtain the key usable to spend this output.
/// Enables HDKD systems.
pub offset: Scalar,
/// The output to spend.
pub output: TxOut,
/// The TX ID and vout of the output to spend.
pub outpoint: OutPoint,
}
impl SpendableOutput {
/// Obtain a unique ID for this output.
pub fn id(&self) -> [u8; 36] {
serialize(&self.outpoint).try_into().unwrap()
}
/// Read a SpendableOutput from a generic satisfying Read.
pub fn read<R: Read>(r: &mut R) -> io::Result<SpendableOutput> {
Ok(SpendableOutput {
offset: Secp256k1::read_F(r)?,
@ -46,14 +53,22 @@ impl SpendableOutput {
})
}
/// Write a SpendableOutput to a generic satisfying Write.
pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
w.write_all(&self.offset.to_bytes())?;
w.write_all(&serialize(&self.output))?;
w.write_all(&serialize(&self.outpoint))
}
/// Serialize a SpendableOutput to a Vec<u8>.
pub fn serialize(&self) -> Vec<u8> {
let mut res = self.offset.to_bytes().to_vec();
self.output.consensus_encode(&mut res).unwrap();
self.outpoint.consensus_encode(&mut res).unwrap();
let mut res = vec![];
self.write(&mut res).unwrap();
res
}
}
/// A signable transaction, clone-able across attempts.
#[derive(Clone, Debug)]
pub struct SignableTransaction(Transaction, Vec<Scalar>, Vec<TxOut>);
@ -82,6 +97,7 @@ impl SignableTransaction {
u64::try_from(tx.weight()).unwrap()
}
/// Create a new signable-transaction.
pub fn new(
mut inputs: Vec<SpendableOutput>,
payments: &[(Address, u64)],
@ -130,6 +146,7 @@ impl SignableTransaction {
))
}
/// Create a multisig machine for this transaction.
pub async fn multisig(
self,
keys: ThresholdKeys<Secp256k1>,
@ -165,6 +182,7 @@ impl SignableTransaction {
}
}
/// A FROST signing machine to produce a Bitcoin transaction.
pub struct TransactionMachine {
tx: SignableTransaction,
transcript: RecommendedTranscript,