Module: BSV::Script::BIP276

Defined in:
lib/bsv/script/bip276.rb

Overview

Note:

Field order is version-then-network, matching the BIP-276 spec and the Go SDK reference. The Python SDK has these reversed — a known py-sdk bug that is invisible at default v=1, n=1.

BIP-276 text encoding for scripts and templates.

Encodes and decodes typed bitcoin data using the scheme described in github.com/moneybutton/bips/blob/master/bip-0276.mediawiki

Format: ‘<prefix>:<version-byte><network-byte><hex-payload><checksum>` where version and network are each one byte (two hex digits), and checksum is the first 4 bytes of double-SHA256 over the full preimage (the string up to and including the payload), hex-encoded.

Defined Under Namespace

Classes: Error, InvalidChecksum, InvalidFormat, Result

Constant Summary collapse

PREFIX_SCRIPT =
'bitcoin-script'
PREFIX_TEMPLATE =
'bitcoin-template'
CURRENT_VERSION =
1
NETWORK_MAINNET =
1
NETWORK_TESTNET =
2
VALID_BIP276 =

Regex: prefix(:)(version 2 hex)(network 2 hex)(data hex*)(checksum 8 hex)

/\A(.+?):([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]*)([0-9A-Fa-f]{8})\z/

Class Method Summary collapse

Class Method Details

.decode(str) ⇒ Result

Decode a BIP-276 string.

Parameters:

  • str (String)

    BIP-276 encoded string

Returns:

  • (Result)

    value object with :prefix, :version, :network, :data

Raises:



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/bsv/script/bip276.rb', line 62

def decode(str)
  match = VALID_BIP276.match(str)
  raise InvalidFormat, 'not a valid BIP-276 string' unless match

  prefix  = match[1]
  version = match[2].to_i(16)
  network = match[3].to_i(16)

  raise InvalidFormat, 'data payload has odd number of hex digits' if match[4].length.odd?

  data = [match[4]].pack('H*')

  # Compute the checksum over the EXACT input bytes (everything except
  # the trailing 8-hex-digit checksum) rather than rebuilding the
  # preimage from parsed fields. Rebuilding via build_preimage would
  # lowercase the payload hex, causing valid mixed-case input to fail.
  preimage = str[0..-9]
  expected = checksum(preimage)
  raise InvalidChecksum, 'checksum mismatch' unless match[5].downcase == expected

  Result.new(prefix: prefix, version: version, network: network, data: data)
end

.decode_script(str) ⇒ Result

Decode a BIP-276 string that must have the PREFIX_SCRIPT prefix.

Parameters:

  • str (String)

    BIP-276 encoded string

Returns:

Raises:



107
108
109
110
111
112
113
# File 'lib/bsv/script/bip276.rb', line 107

def decode_script(str)
  result = decode(str)
  raise InvalidFormat, "expected prefix '#{PREFIX_SCRIPT}', got '#{result.prefix}'" \
    unless result.prefix == PREFIX_SCRIPT

  result
end

.decode_template(str) ⇒ Result

Decode a BIP-276 string that must have the PREFIX_TEMPLATE prefix.

Parameters:

  • str (String)

    BIP-276 encoded string

Returns:

Raises:



121
122
123
124
125
126
127
# File 'lib/bsv/script/bip276.rb', line 121

def decode_template(str)
  result = decode(str)
  raise InvalidFormat, "expected prefix '#{PREFIX_TEMPLATE}', got '#{result.prefix}'" \
    unless result.prefix == PREFIX_TEMPLATE

  result
end

.encode(data, prefix: PREFIX_SCRIPT, network: NETWORK_MAINNET, version: CURRENT_VERSION) ⇒ String

Encode a binary payload as a BIP-276 string.

Parameters:

  • data (String)

    binary payload (e.g. a Script‘s binary form)

  • prefix (String) (defaults to: PREFIX_SCRIPT)

    PREFIX_SCRIPT or PREFIX_TEMPLATE (or any custom prefix)

  • version (Integer) (defaults to: CURRENT_VERSION)

    1..255 — CURRENT_VERSION by default

  • network (Integer) (defaults to: NETWORK_MAINNET)

    1..255 — NETWORK_MAINNET by default

Returns:

  • (String)

    BIP-276 encoded string

Raises:

  • (ArgumentError)

    if version or network is out of the range 1..255



48
49
50
51
52
53
54
# File 'lib/bsv/script/bip276.rb', line 48

def encode(data, prefix: PREFIX_SCRIPT, network: NETWORK_MAINNET, version: CURRENT_VERSION)
  raise ArgumentError, "version must be 1..255, got #{version}"  unless (1..255).cover?(version)
  raise ArgumentError, "network must be 1..255, got #{network}"  unless (1..255).cover?(network)

  preimage = build_preimage(prefix, version, network, data)
  preimage + checksum(preimage)
end

.encode_script(data, network: NETWORK_MAINNET, version: CURRENT_VERSION) ⇒ String

Encode a script payload using the PREFIX_SCRIPT prefix.

Parameters:

  • data (String)

    binary payload (e.g. a Script‘s binary form)

  • prefix (String)

    PREFIX_SCRIPT or PREFIX_TEMPLATE (or any custom prefix)

  • version (Integer) (defaults to: CURRENT_VERSION)

    1..255 — CURRENT_VERSION by default

  • network (Integer) (defaults to: NETWORK_MAINNET)

    1..255 — NETWORK_MAINNET by default

Returns:

  • (String)

    BIP-276 encoded string with bitcoin-script prefix



89
90
91
# File 'lib/bsv/script/bip276.rb', line 89

def encode_script(data, network: NETWORK_MAINNET, version: CURRENT_VERSION)
  encode(data, prefix: PREFIX_SCRIPT, network: network, version: version)
end

.encode_template(data, network: NETWORK_MAINNET, version: CURRENT_VERSION) ⇒ String

Encode a template payload using the PREFIX_TEMPLATE prefix.

Parameters:

  • data (String)

    binary payload (e.g. a Script‘s binary form)

  • prefix (String)

    PREFIX_SCRIPT or PREFIX_TEMPLATE (or any custom prefix)

  • version (Integer) (defaults to: CURRENT_VERSION)

    1..255 — CURRENT_VERSION by default

  • network (Integer) (defaults to: NETWORK_MAINNET)

    1..255 — NETWORK_MAINNET by default

Returns:

  • (String)

    BIP-276 encoded string with bitcoin-template prefix



97
98
99
# File 'lib/bsv/script/bip276.rb', line 97

def encode_template(data, network: NETWORK_MAINNET, version: CURRENT_VERSION)
  encode(data, prefix: PREFIX_TEMPLATE, network: network, version: version)
end