Class: X402::BSV::PrefixStore::Memory

Inherits:
Object
  • Object
show all
Defined in:
lib/x402/bsv/prefix_store.rb

Overview

In-memory backend suitable for development and single-process deployments. Thread-safe via Monitor. Entries expire after +ttl+ seconds and the store rejects new prefixes once +max_issued+ unconsumed entries are held.

NOTE: This store provides no replay protection across OS processes (e.g. Puma pre-fork, multiple dynos). Production multi-process deployments should use a shared backend (Redis, database).

Constant Summary collapse

DEFAULT_TTL =
300
DEFAULT_MAX_ISSUED =
10_000

Instance Method Summary collapse

Constructor Details

#initialize(ttl: DEFAULT_TTL, max_issued: DEFAULT_MAX_ISSUED) ⇒ Memory

Returns a new instance of Memory.

Parameters:

  • ttl (Integer) (defaults to: DEFAULT_TTL)

    seconds before an issued prefix expires (default 300)

  • max_issued (Integer) (defaults to: DEFAULT_MAX_ISSUED)

    cap on unconsumed prefixes (default 10_000)



35
36
37
38
39
40
# File 'lib/x402/bsv/prefix_store.rb', line 35

def initialize(ttl: DEFAULT_TTL, max_issued: DEFAULT_MAX_ISSUED)
  @prefixes = {}
  @monitor = Monitor.new
  @ttl = ttl
  @max_issued = max_issued
end

Instance Method Details

#consume!(prefix) ⇒ Boolean

Atomically mark a prefix as consumed. Returns false if already consumed, unknown, or expired.

Parameters:

  • prefix (String)

    hex derivation prefix

Returns:

  • (Boolean)

    true if successfully consumed, false if replay/unknown/expired



73
74
75
76
77
78
79
80
81
# File 'lib/x402/bsv/prefix_store.rb', line 73

def consume!(prefix)
  @monitor.synchronize do
    entry = @prefixes[prefix]
    return false unless entry.is_a?(Hash) && entry[:state] == :issued && !expired?(entry)

    entry[:state] = :consumed
    true
  end
end

#store!(prefix) ⇒ void

This method returns an undefined value.

Record a prefix as issued.

Parameters:

  • prefix (String)

    hex derivation prefix

Raises:



47
48
49
50
51
52
53
54
55
# File 'lib/x402/bsv/prefix_store.rb', line 47

def store!(prefix)
  @monitor.synchronize do
    purge_expired!
    issued_count = @prefixes.count { |_, v| v[:state] == :issued }
    raise StoreFullError, "prefix store at capacity (#{@max_issued})" if issued_count >= @max_issued

    @prefixes[prefix] = { state: :issued, issued_at: monotonic_now }
  end
end

#valid?(prefix) ⇒ Boolean

Non-binding read: returns true if the prefix was issued and not yet consumed.

Parameters:

  • prefix (String)

    hex derivation prefix

Returns:

  • (Boolean)


61
62
63
64
65
66
# File 'lib/x402/bsv/prefix_store.rb', line 61

def valid?(prefix)
  @monitor.synchronize do
    entry = @prefixes[prefix]
    entry.is_a?(Hash) && entry[:state] == :issued && !expired?(entry)
  end
end