Class: Ethereum::Trie::NibbleKey

Inherits:
Array show all
Defined in:
lib/ethereum/trie/nibble_key.rb

Overview

Nibble is half-byte.

Constant Summary collapse

NIBBLE_TERM_FLAG =
0b0010
NIBBLE_ODD_FLAG =
0b0001
NIBBLE_TERMINATOR =
16
HEX_VALUES =
(0..15).inject({}) {|h, i| h[i.to_s(16)] = i; h}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Array

#false?, #safe_slice

Constructor Details

#initialize(*args) ⇒ NibbleKey

Returns a new instance of NibbleKey.



113
114
115
# File 'lib/ethereum/trie/nibble_key.rb', line 113

def initialize(*args)
  super
end

Class Method Details

.decode(bytes) ⇒ NibbleKey

Decode bytes to Ethereum::Trie::NibbleKey, with flags processed.

Parameters:

  • bytes (String)

    compact hex encoded string.

Returns:

  • (NibbleKey)

    nibbles array, may have a terminator

See Also:

  • in pyethereum


58
59
60
61
62
63
64
65
66
# File 'lib/ethereum/trie/nibble_key.rb', line 58

def decode(bytes)
  o = from_string bytes
  flags = o[0]

  o.push NIBBLE_TERMINATOR if flags & NIBBLE_TERM_FLAG > 0
  fill = flags & NIBBLE_ODD_FLAG > 0 ? 1 : 2

  new o[fill..-1]
end

.encode(nibbles) ⇒ String

Encode nibbles to string.

Parameters:

  • nibbles (Array[Integer])

    array of nibbles to encode

Returns:

See Also:

  • in pyethereum


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/ethereum/trie/nibble_key.rb', line 27

def encode(nibbles)
  flags = 0

  if nibbles.last == NIBBLE_TERMINATOR
    flags |= NIBBLE_TERM_FLAG
    nibbles = nibbles[0...-1]
  end

  odd = nibbles.size % 2
  flags |= odd
  if odd == 1
    nibbles = [flags] + nibbles
  else
    nibbles = [flags, 0b0000] + nibbles
  end

  (nibbles.size/2).times.reduce('') do |s, i|
    base = 2*i
    s += (16*nibbles[base] + nibbles[base+1]).chr
  end
end

.from_string(s) ⇒ NibbleKey

Convert arbitrary string to Ethereum::Trie::NibbleKey.

Examples:

from_string('') # => []
from_string('h') # => [6, 8]
from_string('he') # => [6, 8, 6, 5]
from_string('hello') # => [6, 8, 6, 5, 6, 12, 6, 12, 6, 15]

Parameters:

Returns:

  • (NibbleKey)

    array of nibbles presented as interger smaller than 16, has no terminator because plain string has no flags

See Also:

  • in pyethereum


84
85
86
87
# File 'lib/ethereum/trie/nibble_key.rb', line 84

def from_string(s)
  nibbles = RLP::Utils.encode_hex(s).each_char.map {|nibble| HEX_VALUES[nibble] }
  new nibbles
end

.terminatorObject



108
109
110
# File 'lib/ethereum/trie/nibble_key.rb', line 108

def terminator
  new([NIBBLE_TERMINATOR])
end

.to_string(nibbles) ⇒ String

Convert array of nibbles to string.

Parameters:

  • nibbles (Array)

    array of nibbles

Returns:

  • (String)

    string represented by nibbles

Raises:

  • (ArgumentError)

See Also:

  • in pyethereum


98
99
100
101
102
103
104
105
106
# File 'lib/ethereum/trie/nibble_key.rb', line 98

def to_string(nibbles)
  raise ArgumentError, "nibbles can only be in 0..15" if nibbles.any? {|x| x > 15 || x < 0 }
  raise ArgumentError, "nibbles must be of even numbers" if nibbles.size % 2 == 1

  (nibbles.size/2).times.map do |i|
    base = i*2
    (16*nibbles[base] + nibbles[base+1]).chr
  end.join
end

Instance Method Details

#+(array) ⇒ Object



177
178
179
# File 'lib/ethereum/trie/nibble_key.rb', line 177

def +(array)
  self.class.new(super(array))
end

#common_prefix(another_key) ⇒ Array

Find common prefix to another key.

Parameters:

  • another_key (Array)

    another array of nibbles

Returns:

  • (Array)

    common prefix of both nibbles array



158
159
160
161
162
163
164
165
166
167
# File 'lib/ethereum/trie/nibble_key.rb', line 158

def common_prefix(another_key)
  prefix = []

  [size, another_key.size].min.times do |i|
    break if self[i] != another_key[i]
    prefix.push self[i]
  end

  self.class.new prefix
end

#encodeObject



169
170
171
# File 'lib/ethereum/trie/nibble_key.rb', line 169

def encode
  self.class.encode self
end

#prefix?(another_key) ⇒ Bool

test whether this is prefix of another Ethereum::Trie::NibbleKey

Parameters:

  • another_key (NibbleKey)

    the full key to test

Returns:

  • (Bool)


146
147
148
149
# File 'lib/ethereum/trie/nibble_key.rb', line 146

def prefix?(another_key)
  return false if another_key.size < size
  another_key.take(size) == self
end

#terminate(flag) ⇒ NibbleKey

Get with or without terminator copy of this Ethereum::Trie::NibbleKey.

Parameters:

  • flag (Bool)

    set true to get a copy with terminator, otherwise set false

Returns:

  • (NibbleKey)

    a copy with or without terminator at end



129
130
131
132
133
134
135
136
137
# File 'lib/ethereum/trie/nibble_key.rb', line 129

def terminate(flag)
  dup.tap do |copy|
    if flag
      copy.push NIBBLE_TERMINATOR unless copy.terminate?
    else
      copy.pop if copy.terminate?
    end
  end
end

#terminate?Boolean

Returns:

  • (Boolean)


117
118
119
# File 'lib/ethereum/trie/nibble_key.rb', line 117

def terminate?
  last == NIBBLE_TERMINATOR
end

#to_stringObject



173
174
175
# File 'lib/ethereum/trie/nibble_key.rb', line 173

def to_string
  self.class.to_string self
end