Skip to content

Commit

Permalink
Merge branch 'master' of github.com:ordinals/ord into emilcondrea/master
Browse files Browse the repository at this point in the history
  • Loading branch information
raphjaph committed Jan 27, 2025
2 parents e7f71f6 + 6041457 commit 17ef2e2
Show file tree
Hide file tree
Showing 20 changed files with 913 additions and 86 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ rss = "2.0.1"
rust-embed = "8.0.0"
rustls = { version = "0.23.20", features = ["ring"] }
rustls-acme = { version = "0.12.1", features = ["axum"] }
secp256k1 = { version = "*", features = ["global-context"] }
serde-hex = "0.1.0"
serde.workspace = true
serde_json.workspace = true
Expand Down
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Summary
- [Examples](inscriptions/examples.md)
- [Runes](runes.md)
- [Specification](runes/specification.md)
- [Satscard](satscard.md)
- [FAQ](faq.md)
- [Contributing](contributing.md)
- [Donate](donate.md)
Expand Down
65 changes: 65 additions & 0 deletions docs/src/satscard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
Satscard
========

[Satscards](https://satscard.com/) are cards which can be used to store
bitcoin, inscriptions, and runes.

Slots
-----

Each satscard has ten slots containing private keys with corresponding bitcoin
addresses.

Initially, all slots are sealed and the private keys are stored only the
satscard.

Slots can be unsealed, which allows the corresponding private key to be
extracted.

Unsealing is permanent. If a satscard is sealed, you can have some confidence
that private key is not known to anyone. That taking physical ownership of a
satscard makes you the sole owner of assets in any sealed slots.

Lifespan
--------

Satscards are expected to have a usable lifetime of ten years. Do not use
satscards for long-term storage of valuable assets.


Viewing
-------

When placed on a smartphone, the satscard transmits a URL, beginning with
`https://satscard.com/start` or `https://getsatscard.com/start`, depending on
when it was manufactured.

This URL contains a signature which can be used to recover the address of the
current slot. This signature is made over a random nonce, so it changes every
time the satscard is tapped, and provides some confidence that the satscard
contains the private key.

`ord` supports viewing the contents of a satscard by entering the full URL into
the `ord` explorer search bar, or the input field on the `/satscard` page.

For `ordinals.com`, this is
[ordinals.com/satscard](https://ordinals.com/satscard).

Unsealing
---------

Satscard slots can be unsealed and the private keys extracted using the `cktap`
binary, available in the
[coinkite-tap-proto](https://github.com/coinkite/coinkite-tap-proto)
repository.

Sweeping
--------

After a satscard slot is unsealed, all assets should be swept from that slot to
another wallet, as the private key can now be read via NFC.

`ord` does not yet support sweeping assets from other wallets, so assets will
need to be transferred manually.

Be careful, and good luck!
116 changes: 80 additions & 36 deletions install.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
#!/usr/bin/env bash
#!/usr/bin/env sh

set -euo pipefail
set -eu

if [ ! -z ${GITHUB_ACTIONS-} ]; then
if [ -n "${GITHUB_ACTIONS-}" ]; then
set -x
fi

# Check pipefail support in a subshell, ignore if unsupported
# shellcheck disable=SC3040
(set -o pipefail 2> /dev/null) && set -o pipefail

help() {
cat <<'EOF'
Install a binary release of ord hosted on GitHub
Expand All @@ -18,7 +22,7 @@ FLAGS:
-f, --force Force overwriting an existing binary
OPTIONS:
--tag TAG Tag (version) of the crate to install, defaults to latest release
--tag TAG Tag (version) to install, defaults to latest release
--to LOCATION Where to install the binary [default: ~/bin]
--target TARGET
EOF
Expand All @@ -29,24 +33,35 @@ url=https://github.com/ordinals/ord
releases=$url/releases

say() {
echo "install.sh: $*" >&2
echo "install: $*" >&2
}

err() {
if [ ! -z ${tempdir-} ]; then
rm -rf $tempdir
if [ -n "${td-}" ]; then
rm -rf "$td"
fi

say "error: $*"
exit 1
}

need() {
if ! command -v $1 > /dev/null 2>&1; then
if ! command -v "$1" > /dev/null 2>&1; then
err "need $1 (command not found)"
fi
}

download() {
url="$1"
output="$2"

if command -v curl > /dev/null; then
curl --proto =https --tlsv1.2 -sSfL "$url" "-o$output"
else
wget --https-only --secure-protocol=TLSv1_2 --quiet "$url" "-O$output"
fi
}

force=false
while test $# -gt 0; do
case $1 in
Expand All @@ -70,46 +85,74 @@ while test $# -gt 0; do
shift
;;
*)
say "error: unrecognized argument '$1'. Usage:"
help
exit 1
;;
esac
shift
done

# Dependencies
need curl
need install
command -v curl > /dev/null 2>&1 ||
command -v wget > /dev/null 2>&1 ||
err "need wget or curl (command not found)"

need mkdir
need mktemp
need tar

dest=${dest-"$HOME/bin"}
if [ -z "${tag-}" ]; then
need grep
need cut
fi

if [ -z ${tag-} ]; then
if [ -z "${target-}" ]; then
need cut
fi

tag=$(curl --proto =https --tlsv1.2 -sSf https://api.github.com/repos/ordinals/ord/releases/latest |
if [ -z "${dest-}" ]; then
dest="$HOME/bin"
fi

if [ -z "${tag-}" ]; then
tag=$(
download https://api.github.com/repos/ordinals/ord/releases/latest - |
grep tag_name |
cut -d'"' -f4
)
fi

if [ -z ${target-} ]; then
uname_target=`uname -m`-`uname -s`
if [ -z "${target-}" ]; then
# bash compiled with MINGW (e.g. git-bash, used in github windows runners),
# unhelpfully includes a version suffix in `uname -s` output, so handle that.
# e.g. MINGW64_NT-10-0.19044
kernel=$(uname -s | cut -d- -f1)
uname_target="$(uname -m)-$kernel"

case $uname_target in
arm64-Darwin) target=aarch64-apple-darwin;;
x86_64-Darwin) target=x86_64-apple-darwin;;
x86_64-Linux) target=x86_64-unknown-linux-gnu;;
x86_64-MINGW64_NT) target=x86_64-pc-windows-msvc;;
x86_64-Windows_NT) target=x86_64-pc-windows-msvc;;
*)
say 'Could not determine target from output of `uname -m`-`uname -s`, please use `--target`:' $uname_target
say 'Target architecture is not supported by this install script.'
say 'Consider opening an issue or building from source: https://github.com/ordinals/ord'
exit 1
# shellcheck disable=SC2016
err 'Could not determine target from output of `uname -m`-`uname -s`, please use `--target`:' "$uname_target"
;;
esac
fi

archive="$releases/download/$tag/$crate-$tag-$target.tar.gz"
case $target in
x86_64-pc-windows-msvc)
extension=zip
need unzip
;;
*)
extension=tar.gz
need tar
;;
esac

archive="$releases/download/$tag/$crate-$tag-$target.$extension"

say "Repository: $url"
say "Crate: $crate"
Expand All @@ -118,20 +161,21 @@ say "Target: $target"
say "Destination: $dest"
say "Archive: $archive"

tempdir=`mktemp -d || mktemp -d -t tmp`
td=$(mktemp -d || mktemp -d -t tmp)

curl --proto =https --tlsv1.2 -sSfL $archive | tar --directory $tempdir --strip-components 1 -xz

for name in `ls $tempdir`; do
file="$tempdir/$name"
test -x $file || continue
if [ "$extension" = "zip" ]; then
download "$archive" "$td/ord.zip"
unzip -jd "$td" "$td/ord.zip"
else
download "$archive" - | tar --directory "$td" --strip-components 1 -xz
fi

if [ -e "$dest/$name" ] && [ $force = false ]; then
err "$name already exists in $dest"
else
mkdir -p $dest
install -m 755 $file $dest
fi
done
if [ -e "$dest/ord" ] && [ "$force" = false ]; then
err "\`$dest/ord\` already exists"
else
mkdir -p "$dest"
cp "$td/ord" "$dest/ord"
chmod 755 "$dest/ord"
fi

rm -rf $tempdir
rm -rf "$td"
8 changes: 8 additions & 0 deletions src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ impl Chain {
self.into()
}

pub(crate) fn bech32_hrp(self) -> KnownHrp {
match self {
Self::Mainnet => KnownHrp::Mainnet,
Self::Regtest => KnownHrp::Regtest,
Self::Signet | Self::Testnet | Self::Testnet4 => KnownHrp::Testnets,
}
}

pub(crate) fn default_rpc_port(self) -> u16 {
match self {
Self::Mainnet => 8332,
Expand Down
1 change: 1 addition & 0 deletions src/deserialize_from_str.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::*;

#[derive(Debug)]
pub struct DeserializeFromStr<T: FromStr>(pub T);

impl<'de, T: FromStr> Deserialize<'de> for DeserializeFromStr<T>
Expand Down
2 changes: 1 addition & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl From<Error> for SnafuError {
/// We currently use `anyhow` for error handling but are migrating to typed
/// errors using `snafu`. This trait exists to provide access to
/// `snafu::ResultExt::{context, with_context}`, which are otherwise shadowed
/// by `anhow::Context::{context, with_context}`. Once the migration is
/// by `anyhow::Context::{context, with_context}`. Once the migration is
/// complete, this trait can be deleted, and `snafu::ResultExt` used directly.
pub(crate) trait ResultExt<T, E>: Sized {
fn snafu_context<C, E2>(self, context: C) -> Result<T, E2>
Expand Down
5 changes: 5 additions & 0 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,11 @@ impl Index {
})
}

#[cfg(test)]
pub(crate) fn chain(&self) -> Chain {
self.settings.chain()
}

pub fn have_full_utxo_index(&self) -> bool {
self.first_index_height == 0
}
Expand Down
10 changes: 7 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ use {
teleburn, ParsedEnvelope,
},
into_usize::IntoUsize,
option_ext::OptionExt,
outgoing::Outgoing,
representation::Representation,
satscard::Satscard,
settings::Settings,
signer::Signer,
subcommand::{OutputFormat, Subcommand, SubcommandResult},
Expand All @@ -43,10 +45,10 @@ use {
hash_types::{BlockHash, TxMerkleNode},
hashes::Hash,
policy::MAX_STANDARD_TX_WEIGHT,
script,
script, secp256k1,
transaction::Version,
Amount, Block, Network, OutPoint, Script, ScriptBuf, Sequence, SignedAmount, Transaction, TxIn,
TxOut, Txid, Witness,
Amount, Block, KnownHrp, Network, OutPoint, Script, ScriptBuf, Sequence, SignedAmount,
Transaction, TxIn, TxOut, Txid, Witness,
},
bitcoincore_rpc::{Client, RpcApi},
chrono::{DateTime, TimeZone, Utc},
Expand Down Expand Up @@ -119,11 +121,13 @@ mod inscriptions;
mod into_usize;
mod macros;
mod object;
mod option_ext;
pub mod options;
pub mod outgoing;
mod re;
mod representation;
pub mod runes;
mod satscard;
pub mod settings;
mod signer;
pub mod subcommand;
Expand Down
Loading

0 comments on commit 17ef2e2

Please sign in to comment.