Class: BSV::Overlay::AdminTokenTemplate
- Inherits:
-
Object
- Object
- BSV::Overlay::AdminTokenTemplate
- Defined in:
- lib/bsv/overlay/admin_token_template.rb
Overview
Script template for creating, unlocking, and decoding SHIP and SLAP advertisements.
SHIP (Service Host Interconnect) and SLAP (Service Lookup Availability) tokens are PushDrop scripts containing four data fields:
Field 0: protocol string — 'SHIP' or 'SLAP'
Field 1: identity key — 33-byte compressed public key (binary)
Field 2: domain — UTF-8 string
Field 3: topic or service name — UTF-8 string
The locking script includes a fifth field containing a wallet signature over the concatenation of fields 0–3, which authenticates the token at creation time. The lock is secured with a P2PK condition derived from the wallet using BRC-42/43 key derivation at security level 2.
Script layout (lock-after PushDrop format):
<protocol> <identity_key> <domain> <topic> <wallet_sig>
OP_2DROP OP_2DROP OP_DROP
<derived_pubkey> OP_CHECKSIG
Defined Under Namespace
Classes: Advertisement, Unlocker
Class Method Summary collapse
-
.decode(script) ⇒ Advertisement?
Decode a SHIP or SLAP advertisement from a PushDrop locking script.
Instance Method Summary collapse
-
#initialize(wallet, originator: nil) ⇒ AdminTokenTemplate
constructor
Construct a new AdminTokenTemplate instance.
-
#lock(protocol, domain, topic_or_service) ⇒ BSV::Script::Script
Create a SHIP or SLAP advertisement locking script.
-
#unlock(protocol) ⇒ Unlocker
Return an unlocker for spending an advertisement token.
Constructor Details
#initialize(wallet, originator: nil) ⇒ AdminTokenTemplate
Construct a new AdminTokenTemplate instance.
149 150 151 152 |
# File 'lib/bsv/overlay/admin_token_template.rb', line 149 def initialize(wallet, originator: nil) @wallet = wallet @originator = originator end |
Class Method Details
.decode(script) ⇒ Advertisement?
Decode a SHIP or SLAP advertisement from a PushDrop locking script.
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/bsv/overlay/admin_token_template.rb', line 122 def self.decode(script) return nil if script.nil? || script.bytes.empty? return nil unless script.pushdrop? fields = script.pushdrop_fields raise OverlayError, 'Invalid SHIP/SLAP advertisement: expected at least 4 fields' if fields.length < 4 protocol = fields[0].force_encoding('UTF-8') raise OverlayError, "Invalid SHIP/SLAP protocol: #{protocol.inspect}" unless VALID_PROTOCOLS.include?(protocol) identity_key = fields[1].unpack1('H*') domain = normalise_field(fields[2]) topic_or_service = normalise_field(fields[3]) Advertisement.new( protocol: protocol, identity_key: identity_key, domain: domain, topic_or_service: topic_or_service ) end |
Instance Method Details
#lock(protocol, domain, topic_or_service) ⇒ BSV::Script::Script
Create a SHIP or SLAP advertisement locking script.
Derives the wallet’s identity key, builds the four advertisement fields, signs them with the protocol-derived key, and constructs a PushDrop locking script with a P2PK spending condition.
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/bsv/overlay/admin_token_template.rb', line 165 def lock(protocol, domain, topic_or_service) raise OverlayError, "Invalid protocol: #{protocol.inspect}. Must be 'SHIP' or 'SLAP'" \ unless VALID_PROTOCOLS.include?(protocol) protocol_id = protocol_id_for(protocol) # Fetch the wallet's identity key (compressed public key hex) id_args = { identity_key: true } id_args[:originator] = @originator if @originator identity_result = @wallet.get_public_key(id_args) identity_key_hex = identity_result[:public_key] identity_key_bytes = [identity_key_hex].pack('H*') # Derive the locking public key for this protocol lock_args = { protocol_id: protocol_id, key_id: '1', counterparty: 'self' } lock_args[:originator] = @originator if @originator locking_result = @wallet.get_public_key(lock_args) locking_pubkey_hex = locking_result[:public_key] locking_pubkey_bytes = [locking_pubkey_hex].pack('H*') # Build the four advertisement fields field_protocol = protocol.b field_identity = identity_key_bytes field_domain = domain.encode('binary') field_topic = topic_or_service.encode('binary') # Sign the concatenation of all four fields as authentication data_to_sign = (field_protocol + field_identity + field_domain + field_topic).unpack('C*') sig_args = { data: data_to_sign, protocol_id: protocol_id, key_id: '1', counterparty: 'self' } sig_args[:originator] = @originator if @originator sig_result = @wallet.create_signature(sig_args) field_sig = sig_result[:signature].pack('C*') fields = [field_protocol, field_identity, field_domain, field_topic, field_sig] lock_script = BSV::Script::Script.p2pk_lock(locking_pubkey_bytes) BSV::Script::Script.pushdrop_lock(fields, lock_script) end |
#unlock(protocol) ⇒ Unlocker
Return an unlocker for spending an advertisement token.
The returned object follows the Transaction::UnlockingScriptTemplate interface and can be assigned to an input’s unlocking_script_template.
211 212 213 214 215 216 |
# File 'lib/bsv/overlay/admin_token_template.rb', line 211 def unlock(protocol) raise OverlayError, "Invalid protocol: #{protocol.inspect}. Must be 'SHIP' or 'SLAP'" \ unless VALID_PROTOCOLS.include?(protocol) Unlocker.new(@wallet, protocol_id_for(protocol), @originator) end |