Skip to content

Commit af7a096

Browse files
committed
Simplify space scripts
- Reduces on-chain cost by a few bytes - Simpler space label type `SLabel` replacing `SName` - Enforce alphanumeric rules - Cargo fmt
1 parent 3548e3d commit af7a096

File tree

18 files changed

+849
-1315
lines changed

18 files changed

+849
-1315
lines changed

Cargo.lock

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

node/src/bin/space-cli.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ use jsonrpsee::{
1111
use protocol::{
1212
bitcoin::{Amount, FeeRate, OutPoint, Txid},
1313
hasher::{KeyHasher, SpaceKey},
14-
opcodes::OP_SETALL,
15-
sname::{NameLike, SName},
14+
slabel::SLabel,
1615
Covenant, FullSpaceOut,
1716
};
1817
use serde::{Deserialize, Serialize};
@@ -372,8 +371,8 @@ async fn main() -> anyhow::Result<()> {
372371

373372
fn space_hash(spaceish: &str) -> anyhow::Result<String> {
374373
let space = normalize_space(&spaceish);
375-
let sname = SName::from_str(&space)?;
376-
let spacehash = SpaceKey::from(Sha256::hash(sname.to_bytes()));
374+
let sname = SLabel::from_str(&space)?;
375+
let spacehash = SpaceKey::from(Sha256::hash(sname.as_ref()));
377376
Ok(hex::encode(spacehash.as_slice()))
378377
}
379378

@@ -553,13 +552,13 @@ async fn handle_commands(
553552
)))
554553
}
555554
};
556-
let builder = protocol::script::ScriptBuilder::new()
557-
.push_slice(data.as_slice())
558-
.push_opcode(OP_SETALL.into());
555+
556+
let space_script = protocol::script::SpaceScript::create_set(data.as_slice());
557+
559558
cli.send_request(
560559
Some(RpcWalletRequest::Execute(ExecuteParams {
561560
context: vec![space],
562-
space_script: builder,
561+
space_script,
563562
})),
564563
None,
565564
fee_rate,

node/src/config.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ impl Args {
129129
let data_dir = match args.data_dir {
130130
None => default_dirs.data_dir().to_path_buf(),
131131
Some(data_dir) => data_dir,
132-
}.join(args.chain.to_string());
132+
}
133+
.join(args.chain.to_string());
133134

134135
let default_port = args.rpc_port.unwrap();
135136
let rpc_bind_addresses: Vec<SocketAddr> = args
@@ -145,7 +146,6 @@ impl Args {
145146
})
146147
.collect();
147148

148-
149149
let bitcoin_rpc_auth = if let Some(cookie) = args.bitcoin_rpc_cookie {
150150
let cookie = std::fs::read_to_string(cookie)?;
151151
BitcoinRpcAuth::Cookie(cookie)

node/src/node.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use protocol::{
1010
constants::{ChainAnchor, ROLLOUT_BATCH_SIZE, ROLLOUT_BLOCK_INTERVAL},
1111
hasher::{BidKey, KeyHasher, OutpointKey, SpaceKey},
1212
prepare::TxContext,
13-
sname::NameLike,
1413
validate::{TxChangeSet, UpdateKind, Validator},
1514
Covenant, FullSpaceOut, RevokeReason, SpaceOut,
1615
};
@@ -149,7 +148,7 @@ impl Node {
149148

150149
// Space => Outpoint
151150
if let Some(space) = create.space.as_ref() {
152-
let space_key = SpaceKey::from(Sha256::hash(space.name.to_bytes()));
151+
let space_key = SpaceKey::from(Sha256::hash(space.name.as_ref()));
153152
state.insert_space(space_key, outpoint.into());
154153
}
155154
// Outpoint => SpaceOut
@@ -168,7 +167,7 @@ impl Node {
168167
// Since these are caused by spends
169168
// Outpoint -> Spaceout mapping is already removed,
170169
let space = update.output.spaceout.space.unwrap();
171-
let base_hash = Sha256::hash(space.name.to_bytes());
170+
let base_hash = Sha256::hash(space.name.as_ref());
172171

173172
// Remove Space -> Outpoint
174173
let space_key = SpaceKey::from(base_hash);
@@ -209,7 +208,7 @@ impl Node {
209208
.as_ref()
210209
.expect("a space in rollout")
211210
.name
212-
.to_bytes(),
211+
.as_ref(),
213212
);
214213
let bid_key = BidKey::from_bid(rollout.priority, base_hash);
215214

@@ -229,7 +228,7 @@ impl Node {
229228
.as_ref()
230229
.expect("space")
231230
.name
232-
.to_bytes(),
231+
.as_ref(),
233232
);
234233

235234
let (bid_value, previous_bid) = unwrap_bid_value(&update.output.spaceout);

node/src/rpc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ pub struct SendCoinsParams {
225225
#[derive(Clone, Serialize, Deserialize)]
226226
pub struct ExecuteParams {
227227
pub context: Vec<String>,
228-
pub space_script: protocol::script::ScriptBuilder,
228+
pub space_script: Vec<u8>,
229229
}
230230

231231
#[derive(Clone, Serialize, Deserialize)]

node/src/sync.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ use std::{net::SocketAddr, path::PathBuf, time::Duration};
33
use anyhow::{anyhow, Context};
44
use log::info;
55
use protocol::{
6-
bitcoin::{Block, BlockHash},
6+
bitcoin::{hashes::Hash, Block, BlockHash},
77
constants::ChainAnchor,
88
hasher::BaseHash,
99
};
1010
use tokio::sync::broadcast;
11-
use protocol::bitcoin::hashes::Hash;
11+
1212
use crate::{
1313
config::ExtendedNetwork,
1414
node::{BlockMeta, BlockSource, Node},
@@ -190,8 +190,10 @@ impl Spaced {
190190
Ok(())
191191
}
192192

193-
pub async fn genesis(rpc : &BitcoinRpc, network: ExtendedNetwork) -> anyhow::Result<ChainAnchor> {
194-
193+
pub async fn genesis(
194+
rpc: &BitcoinRpc,
195+
network: ExtendedNetwork,
196+
) -> anyhow::Result<ChainAnchor> {
195197
let mut anchor = match network {
196198
ExtendedNetwork::Testnet => ChainAnchor::TESTNET(),
197199
ExtendedNetwork::Testnet4 => ChainAnchor::TESTNET4(),
@@ -204,11 +206,17 @@ impl Spaced {
204206
if anchor.hash == BlockHash::all_zeros() {
205207
let client = reqwest::Client::new();
206208

207-
anchor.hash = match rpc.send_json(&client, &rpc.get_block_hash(anchor.height)).await {
209+
anchor.hash = match rpc
210+
.send_json(&client, &rpc.get_block_hash(anchor.height))
211+
.await
212+
{
208213
Ok(hash) => hash,
209214
Err(e) => {
210-
return Err(anyhow!("Could not retrieve activation block at height {}: {}",
211-
anchor.height, e));
215+
return Err(anyhow!(
216+
"Could not retrieve activation block at height {}: {}",
217+
anchor.height,
218+
e
219+
));
212220
}
213221
}
214222
}

node/src/wallets.rs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ use protocol::{
99
constants::ChainAnchor,
1010
hasher::{KeyHasher, SpaceKey},
1111
prepare::DataSource,
12-
sname::{NameLike, SName},
12+
script::SpaceScript,
13+
slabel::SLabel,
1314
Space,
1415
};
1516
use serde::{Deserialize, Serialize};
@@ -154,8 +155,11 @@ impl RpcWallet {
154155
balance,
155156
dust: unspent
156157
.into_iter()
157-
.filter(|output| output.is_spaceout ||
158-
output.output.txout.value <= SpacesAwareCoinSelection::DUST_THRESHOLD)
158+
.filter(|output|
159+
(output.is_spaceout || output.output.txout.value <= SpacesAwareCoinSelection::DUST_THRESHOLD) &&
160+
// trusted pending only
161+
(output.output.confirmation_time.is_confirmed() || output.output.keychain == KeychainKind::Internal)
162+
)
159163
.map(|output| output.output.txout.value)
160164
.sum(),
161165
};
@@ -414,7 +418,7 @@ impl RpcWallet {
414418
return Ok(Some(space_address.0));
415419
}
416420

417-
let sname = match SName::from_str(to) {
421+
let sname = match SLabel::from_str(to) {
418422
Ok(sname) => sname,
419423
Err(_) => {
420424
return Err(anyhow!(
@@ -423,7 +427,7 @@ impl RpcWallet {
423427
}
424428
};
425429

426-
let spacehash = SpaceKey::from(Sha256::hash(sname.to_bytes()));
430+
let spacehash = SpaceKey::from(Sha256::hash(sname.as_ref()));
427431
let script_pubkey = match store.get_space_info(&spacehash)? {
428432
None => return Ok(None),
429433
Some(fullspaceout) => fullspaceout.spaceout.script_pubkey,
@@ -446,8 +450,10 @@ impl RpcWallet {
446450
if dust > SpacesAwareCoinSelection::DUST_THRESHOLD {
447451
// Allowing higher dust may space outs to be accidentally
448452
// spent during coin selection
449-
return Err(anyhow!("dust cannot be higher than {}",
450-
SpacesAwareCoinSelection::DUST_THRESHOLD));
453+
return Err(anyhow!(
454+
"dust cannot be higher than {}",
455+
SpacesAwareCoinSelection::DUST_THRESHOLD
456+
));
451457
}
452458
}
453459

@@ -486,7 +492,7 @@ impl RpcWallet {
486492
let spaces: Vec<_> = params
487493
.spaces
488494
.iter()
489-
.filter_map(|space| SName::from_str(space).ok())
495+
.filter_map(|space| SLabel::from_str(space).ok())
490496
.collect();
491497
if spaces.len() != params.spaces.len() {
492498
return Err(anyhow!("sendspaces: some names were malformed"));
@@ -498,7 +504,7 @@ impl RpcWallet {
498504
Some(r) => r,
499505
};
500506
for space in spaces {
501-
let spacehash = SpaceKey::from(Sha256::hash(space.to_bytes()));
507+
let spacehash = SpaceKey::from(Sha256::hash(space.as_ref()));
502508
match store.get_space_info(&spacehash)? {
503509
None => return Err(anyhow!("sendspaces: you don't own `{}`", space)),
504510
Some(full)
@@ -521,10 +527,10 @@ impl RpcWallet {
521527
}
522528
}
523529
RpcWalletRequest::Open(params) => {
524-
let name = SName::from_str(&params.name)?;
530+
let name = SLabel::from_str(&params.name)?;
525531
if !tx.force {
526532
// Warn if already exists
527-
let spacehash = SpaceKey::from(Sha256::hash(name.to_bytes()));
533+
let spacehash = SpaceKey::from(Sha256::hash(name.as_ref()));
528534
let spaceout = store.get_space_info(&spacehash)?;
529535
if spaceout.is_some() {
530536
return Err(anyhow!("open '{}': space already exists", params.name));
@@ -534,17 +540,17 @@ impl RpcWallet {
534540
builder = builder.add_open(&params.name, Amount::from_sat(params.amount));
535541
}
536542
RpcWalletRequest::Bid(params) => {
537-
let name = SName::from_str(&params.name)?;
538-
let spacehash = SpaceKey::from(Sha256::hash(name.to_bytes()));
543+
let name = SLabel::from_str(&params.name)?;
544+
let spacehash = SpaceKey::from(Sha256::hash(name.as_ref()));
539545
let spaceout = store.get_space_info(&spacehash)?;
540546
if spaceout.is_none() {
541547
return Err(anyhow!("bid '{}': space does not exist", params.name));
542548
}
543549
builder = builder.add_bid(spaceout.unwrap(), Amount::from_sat(params.amount));
544550
}
545551
RpcWalletRequest::Register(params) => {
546-
let name = SName::from_str(&params.name)?;
547-
let spacehash = SpaceKey::from(Sha256::hash(name.to_bytes()));
552+
let name = SLabel::from_str(&params.name)?;
553+
let spacehash = SpaceKey::from(Sha256::hash(name.as_ref()));
548554
let spaceout = store.get_space_info(&spacehash)?;
549555
if spaceout.is_none() {
550556
return Err(anyhow!("register '{}': space does not exist", params.name));
@@ -596,8 +602,8 @@ impl RpcWallet {
596602
RpcWalletRequest::Execute(params) => {
597603
let mut spaces = Vec::new();
598604
for space in params.context.iter() {
599-
let name = SName::from_str(&space)?;
600-
let spacehash = SpaceKey::from(Sha256::hash(name.to_bytes()));
605+
let name = SLabel::from_str(&space)?;
606+
let spacehash = SpaceKey::from(Sha256::hash(name.as_ref()));
601607
let spaceout = store.get_space_info(&spacehash)?;
602608
if spaceout.is_none() {
603609
return Err(anyhow!("execute on '{}': space does not exist", space));
@@ -615,7 +621,9 @@ impl RpcWallet {
615621
recipient: address.0,
616622
});
617623
}
618-
builder = builder.add_execute(spaces, params.space_script);
624+
625+
let script = SpaceScript::nop_script(params.space_script);
626+
builder = builder.add_execute(spaces, script);
619627
}
620628
}
621629
}

protocol/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ bitcoin = { version = "0.32.2", features = ["base64", "serde"], default-features
88
log = "0.4.14"
99

1010
## optional features
11-
bincode = { version = "2.0.0-rc.3", features = [ "derive", "serde" ], default-features = false, optional = true }
11+
bincode = { version = "2.0.0-rc.3", features = [ "derive", "serde", "alloc" ], default-features = false, optional = true }
1212
serde = { version = "^1.0", features = ["derive"], default-features = false, optional = true }
1313

1414
[dev-dependencies]
1515
rand = "0.8.5"
16+
serde_json = "1.0.132"
1617

1718
[features]
1819
default = []

protocol/src/constants.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,18 +67,14 @@ impl ChainAnchor {
6767
)
6868
};
6969

70-
pub const MAINNET_ALPHA: fn() -> Self = || {
71-
ChainAnchor {
72-
hash: BlockHash::all_zeros(),
73-
height: 869_000,
74-
}
70+
pub const MAINNET_ALPHA: fn() -> Self = || ChainAnchor {
71+
hash: BlockHash::all_zeros(),
72+
height: 869_000,
7573
};
7674

77-
pub const MAINNET: fn() -> Self = || {
78-
ChainAnchor {
79-
hash: BlockHash::all_zeros(),
80-
height: 871_222,
81-
}
75+
pub const MAINNET: fn() -> Self = || ChainAnchor {
76+
hash: BlockHash::all_zeros(),
77+
height: 871_222,
8278
};
8379

8480
// Testnet activation block
@@ -108,6 +104,8 @@ impl ChainAnchor {
108104

109105
#[cfg(feature = "bincode")]
110106
pub mod bincode_impl {
107+
use alloc::vec::Vec;
108+
111109
use bincode::{
112110
config,
113111
de::Decoder,

protocol/src/errors.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use alloc::string::String;
22
use core::fmt::{self, Display, Formatter};
33

4+
use crate::slabel::NameErrorKind;
5+
46
pub type Result<T> = core::result::Result<T, Error>;
57

68
#[derive(Debug)]
@@ -26,11 +28,6 @@ pub enum StateErrorKind {
2628
MissingOpenTxOut,
2729
}
2830

29-
#[derive(Debug)]
30-
pub enum NameErrorKind {
31-
MalformedName,
32-
}
33-
3431
impl Display for Error {
3532
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3633
match self {

0 commit comments

Comments
 (0)