cryptocoin 0.0.1b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +85 -0
- data/Rakefile +2 -0
- data/cryptocoin.gemspec +24 -0
- data/lib/cryptocoin/core_ext/integer.rb +24 -0
- data/lib/cryptocoin/core_ext/string.rb +30 -0
- data/lib/cryptocoin/digest.rb +36 -0
- data/lib/cryptocoin/merkle_tree.rb +78 -0
- data/lib/cryptocoin/network/bitcoin.rb +9 -0
- data/lib/cryptocoin/network/dogecoin.rb +9 -0
- data/lib/cryptocoin/network/litecoin.rb +9 -0
- data/lib/cryptocoin/network.rb +53 -0
- data/lib/cryptocoin/protocol/block_header.rb +58 -0
- data/lib/cryptocoin/protocol/inventory_vector.rb +28 -0
- data/lib/cryptocoin/protocol/message/addr.rb +29 -0
- data/lib/cryptocoin/protocol/message/alert.rb +0 -0
- data/lib/cryptocoin/protocol/message/block.rb +13 -0
- data/lib/cryptocoin/protocol/message/getaddr.rb +17 -0
- data/lib/cryptocoin/protocol/message/getblocks.rb +44 -0
- data/lib/cryptocoin/protocol/message/getdata.rb +31 -0
- data/lib/cryptocoin/protocol/message/getheaders.rb +44 -0
- data/lib/cryptocoin/protocol/message/headers.rb +30 -0
- data/lib/cryptocoin/protocol/message/inv.rb +31 -0
- data/lib/cryptocoin/protocol/message/mempool.rb +16 -0
- data/lib/cryptocoin/protocol/message/notfound.rb +31 -0
- data/lib/cryptocoin/protocol/message/ping.rb +24 -0
- data/lib/cryptocoin/protocol/message/pong.rb +24 -0
- data/lib/cryptocoin/protocol/message/reject.rb +54 -0
- data/lib/cryptocoin/protocol/message/tx.rb +11 -0
- data/lib/cryptocoin/protocol/message/verack.rb +16 -0
- data/lib/cryptocoin/protocol/message/version.rb +59 -0
- data/lib/cryptocoin/protocol/message.rb +27 -0
- data/lib/cryptocoin/protocol/net_addr.rb +55 -0
- data/lib/cryptocoin/protocol/packet.rb +74 -0
- data/lib/cryptocoin/protocol/var_len_int.rb +85 -0
- data/lib/cryptocoin/protocol/var_len_str.rb +18 -0
- data/lib/cryptocoin/protocol.rb +8 -0
- data/lib/cryptocoin/script/op_code/constants.rb +157 -0
- data/lib/cryptocoin/script/op_code/functions.rb +515 -0
- data/lib/cryptocoin/script/op_code.rb +59 -0
- data/lib/cryptocoin/script.rb +234 -0
- data/lib/cryptocoin/structure/address.rb +64 -0
- data/lib/cryptocoin/structure/block.rb +109 -0
- data/lib/cryptocoin/structure/key_pair.rb +57 -0
- data/lib/cryptocoin/structure/merkle_branch.rb +37 -0
- data/lib/cryptocoin/structure/transaction/input.rb +80 -0
- data/lib/cryptocoin/structure/transaction/output.rb +49 -0
- data/lib/cryptocoin/structure/transaction.rb +94 -0
- data/lib/cryptocoin/version.rb +3 -0
- data/lib/cryptocoin.rb +29 -0
- data/spec/script_spec.rb +42 -0
- data/spec/spec_helper.rb +20 -0
- metadata +145 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
module Cryptocoin
|
2
|
+
module Protocol
|
3
|
+
class Message
|
4
|
+
class Getheaders
|
5
|
+
attr_reader :digest_count
|
6
|
+
|
7
|
+
def parse_from_raw(payload)
|
8
|
+
block_locator_digests, i = [], 0
|
9
|
+
version = payload[0..3]
|
10
|
+
digest_count = Cryptocoin::Protocol::VarLenInt.parse_from_raw(payload[4..-1])
|
11
|
+
digest_count.times do
|
12
|
+
c = digest_count.raw.bytesize+i*32
|
13
|
+
block_locator_digests.push(payload[c..c+31])
|
14
|
+
i+=1
|
15
|
+
end
|
16
|
+
digest_stop = payload[5+i*32..-1]
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(version, digest_count, block_locator_digests, digest_stop)
|
20
|
+
@version_raw = version
|
21
|
+
@digest_count = digest_count
|
22
|
+
@block_locator_digests_raw = block_locator_digests
|
23
|
+
@digest_stop_raw = digest_stop
|
24
|
+
end
|
25
|
+
|
26
|
+
def version
|
27
|
+
@version ||= @version_raw.unpack('L')[0]
|
28
|
+
end
|
29
|
+
|
30
|
+
def block_locator_digests
|
31
|
+
@block_locator_digests ||= @block_locator_digests_raw.map{|e| e.unpack('H*')[0] }
|
32
|
+
end
|
33
|
+
|
34
|
+
def digest_stop
|
35
|
+
@digest_stop ||= @digest_stop_raw.unpack('H*')[0]
|
36
|
+
end
|
37
|
+
|
38
|
+
def raw
|
39
|
+
@version_raw + @digest_count.raw + @block_locator_digests_raw.join + @digest_stop_raw
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'cryptocoin/protocol/block_header'
|
2
|
+
|
3
|
+
module Cryptocoin
|
4
|
+
module Protocol
|
5
|
+
class Message
|
6
|
+
class Headers
|
7
|
+
attr_reader :count, :headers
|
8
|
+
def self.parse_from_raw(payload)
|
9
|
+
headers, i = [], 0
|
10
|
+
count = Cryptocoin::Protocol::VarLenInt.parse_from_raw(payload)
|
11
|
+
count.times do
|
12
|
+
c = count.raw.bytesize + i*81
|
13
|
+
headers.push(Cryptocoin::Protocol::BlockHeader.parse_from_raw(payload[c..c+80]))
|
14
|
+
i+=1
|
15
|
+
end
|
16
|
+
self.new(count, headers)
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(count, headers)
|
20
|
+
@count = count
|
21
|
+
@headers = headers
|
22
|
+
end
|
23
|
+
|
24
|
+
def raw
|
25
|
+
@count.raw + @headers.map{|e| e.raw}.join
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'cryptocoin/protocol/inventory_vector'
|
2
|
+
require 'cryptocoin/protocol/var_len_int'
|
3
|
+
|
4
|
+
module Cryptocoin
|
5
|
+
module Protocol
|
6
|
+
class Message
|
7
|
+
class Inv
|
8
|
+
def self.parse_from_raw(payload)
|
9
|
+
inventory = []
|
10
|
+
i = 0
|
11
|
+
count = Cryptocoin::Protocol::VarLenInt.parse_from_raw(payload)
|
12
|
+
count.times do
|
13
|
+
c = count.raw.bytesize+i*36
|
14
|
+
inventory.push(Cryptocoin::Protocol::InventoryVector.parse_from_raw(payload[c..c+35]))
|
15
|
+
i+=1
|
16
|
+
end
|
17
|
+
self.new(count, inventory)
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(count, inventory)
|
21
|
+
@count_raw = count
|
22
|
+
@inventory = inventory
|
23
|
+
end
|
24
|
+
|
25
|
+
def raw
|
26
|
+
@count_raw + @inventory.map{|e| e.raw}.join
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Cryptocoin
|
2
|
+
module Protocol
|
3
|
+
class Message
|
4
|
+
class Mempool
|
5
|
+
def self.parse_from_raw(payload)
|
6
|
+
# https://en.bitcoin.it/wiki/Protocol_specification#mempool
|
7
|
+
# No data is sent with this message
|
8
|
+
self.new
|
9
|
+
end
|
10
|
+
def raw
|
11
|
+
nil
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'cryptocoin/protocol/inventory_vector'
|
2
|
+
require 'cryptocoin/protocol/var_len_int'
|
3
|
+
|
4
|
+
module Cryptocoin
|
5
|
+
module Protocol
|
6
|
+
class Message
|
7
|
+
class Notfound
|
8
|
+
def self.parse_from_raw(payload)
|
9
|
+
inventory = []
|
10
|
+
i = 0
|
11
|
+
count = Cryptocoin::Protocol::VarLenInt.parse_from_raw(payload)
|
12
|
+
count.times do
|
13
|
+
c = count.raw.bytesize+i*36
|
14
|
+
inventory.push(Cryptocoin::Protocol::InventoryVector.parse_from_raw(payload[c..c+35]))
|
15
|
+
i+=1
|
16
|
+
end
|
17
|
+
self.new(count, inventory)
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(count, inventory)
|
21
|
+
@count_raw = count
|
22
|
+
@inventory = inventory
|
23
|
+
end
|
24
|
+
|
25
|
+
def raw
|
26
|
+
@count_raw + @inventory.map{|e| e.raw}.join
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Cryptocoin
|
2
|
+
module Protocol
|
3
|
+
class Message
|
4
|
+
class Ping
|
5
|
+
def self.parse_from_raw(payload)
|
6
|
+
nonce = payload
|
7
|
+
self.new(nonce)
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(nonce)
|
11
|
+
@nonce_raw = nonce
|
12
|
+
end
|
13
|
+
|
14
|
+
def nonce
|
15
|
+
@nonce ||= @nonce_raw.unpack('Q')[0]
|
16
|
+
end
|
17
|
+
|
18
|
+
def raw
|
19
|
+
@nonce_raw
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Cryptocoin
|
2
|
+
module Protocol
|
3
|
+
class Message
|
4
|
+
class Pong
|
5
|
+
def self.parse_from_raw(payload)
|
6
|
+
nonce = payload
|
7
|
+
self.new(nonce)
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(nonce)
|
11
|
+
@nonce_raw = nonce
|
12
|
+
end
|
13
|
+
|
14
|
+
def nonce
|
15
|
+
@nonce ||= @nonce_raw.unpack('Q')[0]
|
16
|
+
end
|
17
|
+
|
18
|
+
def raw
|
19
|
+
@nonce_raw
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'cryptocoin/protocol/var_len_str'
|
2
|
+
|
3
|
+
module Cryptocoin
|
4
|
+
module Protocol
|
5
|
+
class Message
|
6
|
+
class Reject
|
7
|
+
attr_reader :message, :reason
|
8
|
+
|
9
|
+
def self.parse_from_raw(payload)
|
10
|
+
message = Cryptocoin::Protocol::VarLenStr.parse_from_raw(payload)
|
11
|
+
c = message.raw.bytesize
|
12
|
+
ccode = payload[c..c]
|
13
|
+
reason = Cryptocoin::Protocol::VarLenStr.parse_from_raw(payload[c+1..-1])
|
14
|
+
self.new(message, ccode, reason)
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(message, ccode, reason)
|
18
|
+
@message = message
|
19
|
+
@ccode_raw = ccode
|
20
|
+
@reason = reason
|
21
|
+
end
|
22
|
+
|
23
|
+
def ccode
|
24
|
+
@ccode ||= @ccode_raw.unpack('H*')[0]
|
25
|
+
end
|
26
|
+
|
27
|
+
def ccode_name
|
28
|
+
case ccode
|
29
|
+
when '1'
|
30
|
+
'REJECT_MALFORMED'
|
31
|
+
when '10'
|
32
|
+
'REJECT_INVALID'
|
33
|
+
when '11'
|
34
|
+
'REJECT_OBSOLETE'
|
35
|
+
when '12'
|
36
|
+
'REJECT_DUPLICATE'
|
37
|
+
when '40'
|
38
|
+
'REJECT_NONSTANDARD'
|
39
|
+
when '41'
|
40
|
+
'REJECT_DUST'
|
41
|
+
when '42'
|
42
|
+
'REJECT_INSUFFICIENTFEE'
|
43
|
+
when '43'
|
44
|
+
'REJECT_CHECKPOINT'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def raw
|
49
|
+
@message.raw + @ccode_raw + @reason.raw
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Cryptocoin
|
2
|
+
module Protocol
|
3
|
+
class Message
|
4
|
+
class Verack
|
5
|
+
def self.parse_from_raw(payload)
|
6
|
+
# https://en.bitcoin.it/wiki/Protocol_specification#verack
|
7
|
+
# Has no payload
|
8
|
+
self.new
|
9
|
+
end
|
10
|
+
def raw
|
11
|
+
nil
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Cryptocoin
|
2
|
+
module Protocol
|
3
|
+
class Message
|
4
|
+
class Version
|
5
|
+
def self.parse_from_raw(payload)
|
6
|
+
version = payload[0..3]
|
7
|
+
services = payload[4..11]
|
8
|
+
timestamp = payload[12..19]
|
9
|
+
address_received = Cryptocoin::Protocol::NetAddr.parse_from_raw(payload[20..45])
|
10
|
+
address_from = Cryptocoin::Protocol::NetAddr.parse_from_raw(payload[46..71])
|
11
|
+
nonce = payload[71..79]
|
12
|
+
user_agent = Cryptocoin::Protocol::VarLenStr.parse_from_raw(payload[80..-1])
|
13
|
+
start_height = payload[-5..-2]
|
14
|
+
relay = payload[-1]
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(version, services, timestamp, address_received, address_from, nonce, user_agent, start_height, relay)
|
18
|
+
@version_raw = version
|
19
|
+
@services_raw = services
|
20
|
+
@timestamp_raw = timestamp
|
21
|
+
@address_received = address_received
|
22
|
+
@address_from = address_from
|
23
|
+
@nonce_raw = nonce
|
24
|
+
@user_agent = user_agent
|
25
|
+
@start_height_raw = start_height
|
26
|
+
@relay_raw = relay
|
27
|
+
end
|
28
|
+
|
29
|
+
def version
|
30
|
+
@version ||= @version_raw.unpack('l')[0]
|
31
|
+
end
|
32
|
+
|
33
|
+
def services
|
34
|
+
@services ||= @services_raw.unpack('Q')[0]
|
35
|
+
end
|
36
|
+
|
37
|
+
def timestamp
|
38
|
+
@timestamp ||= @timestamp_raw.unpack('q')[0]
|
39
|
+
end
|
40
|
+
|
41
|
+
def nonce
|
42
|
+
@nonce ||= @nonce_raw.unpack('Q')[0]
|
43
|
+
end
|
44
|
+
|
45
|
+
def start_height
|
46
|
+
@start_height ||= @start_height_raw.unpack('l')[0]
|
47
|
+
end
|
48
|
+
|
49
|
+
def relay
|
50
|
+
@relay ||= @relay_raw.unpack('c')[0]
|
51
|
+
end
|
52
|
+
|
53
|
+
def raw
|
54
|
+
@version_raw + @services_raw + @timestamp_raw + @address_received.raw + @address_from.raw + @nonce_raw + @user_agent.raw + @start_height_raw + @relay_raw
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'cryptocoin/protocol/message/addr'
|
2
|
+
require 'cryptocoin/protocol/message/alert'
|
3
|
+
require 'cryptocoin/protocol/message/block'
|
4
|
+
require 'cryptocoin/protocol/message/getaddr'
|
5
|
+
require 'cryptocoin/protocol/message/getblocks'
|
6
|
+
require 'cryptocoin/protocol/message/getdata'
|
7
|
+
require 'cryptocoin/protocol/message/getheaders'
|
8
|
+
require 'cryptocoin/protocol/message/headers'
|
9
|
+
require 'cryptocoin/protocol/message/inv'
|
10
|
+
require 'cryptocoin/protocol/message/mempool'
|
11
|
+
require 'cryptocoin/protocol/message/notfound'
|
12
|
+
require 'cryptocoin/protocol/message/ping'
|
13
|
+
require 'cryptocoin/protocol/message/pong'
|
14
|
+
require 'cryptocoin/protocol/message/reject'
|
15
|
+
require 'cryptocoin/protocol/message/tx'
|
16
|
+
require 'cryptocoin/protocol/message/verack'
|
17
|
+
require 'cryptocoin/protocol/message/version'
|
18
|
+
|
19
|
+
module Cryptocoin
|
20
|
+
module Protocol
|
21
|
+
class Message
|
22
|
+
def self.parse(command, payload)
|
23
|
+
Cryptocoin::Protocol::Message.const_get(command.capitalize).parse_from_raw(payload)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Cryptocoin
|
2
|
+
module Protocol
|
3
|
+
class NetAddr
|
4
|
+
def self.parse_from_raw(raw)
|
5
|
+
timestamp = raw[0..3]
|
6
|
+
services = raw[4..11]
|
7
|
+
address = raw[12..27]
|
8
|
+
port = raw[28..29]
|
9
|
+
self.new(timestamp, services, address, port)
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(timestamp, services, address, port)
|
13
|
+
@timestamp_raw = timestamp
|
14
|
+
@services_raw = services
|
15
|
+
@address_raw = address
|
16
|
+
@port_raw = port
|
17
|
+
end
|
18
|
+
|
19
|
+
def timestamp
|
20
|
+
@timestamp ||= @timestamp_raw.unpack('L')[0]
|
21
|
+
end
|
22
|
+
|
23
|
+
def services
|
24
|
+
@services ||= @services_raw.unpack('Q')[0]
|
25
|
+
end
|
26
|
+
|
27
|
+
def address
|
28
|
+
return @address if @address
|
29
|
+
address = @address_raw.unpack('H*')[0]
|
30
|
+
if address[0..11] == "000000000000" # IPv4 address
|
31
|
+
address = address[12..-1]
|
32
|
+
@address = address.each_char.each_slice(2).map{|e| e.join.to_i(16)}.join('.')
|
33
|
+
@address_version = 4
|
34
|
+
else
|
35
|
+
@address = address.each_char.each_slice(4).map{|e| e.join}.join(':')
|
36
|
+
@address_version = 6
|
37
|
+
end
|
38
|
+
@address
|
39
|
+
end
|
40
|
+
|
41
|
+
def port
|
42
|
+
@port ||= @port_raw.unpack('S')[0]
|
43
|
+
end
|
44
|
+
|
45
|
+
def address_with_port
|
46
|
+
return "#{@address}:#{@port}" if @address_version == 4
|
47
|
+
"[#{@address}]:#{@port}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def raw
|
51
|
+
@timestamp_raw + @services_raw + @address_raw + @port_raw
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'digest/sha2'
|
2
|
+
require 'cryptocoin/protocol/message'
|
3
|
+
|
4
|
+
module Cryptocoin
|
5
|
+
module Protocol
|
6
|
+
class Packet
|
7
|
+
attr_reader :message, :network
|
8
|
+
|
9
|
+
def self.parse_from_raw(raw)
|
10
|
+
magic = raw[0..4]
|
11
|
+
command = raw[5..16]
|
12
|
+
payload_length = raw[17..20]
|
13
|
+
payload_checksum = raw[21..24]
|
14
|
+
payload = raw[25..-1]
|
15
|
+
message = Cryptocoin::Protocol::Message.parse(command, payload)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.parse_from_io
|
19
|
+
magic = io.read(4)
|
20
|
+
command = io.read(12)
|
21
|
+
payload_length = io.read(4)
|
22
|
+
payload_checksum = io.read(4)
|
23
|
+
payload = io.read
|
24
|
+
message = Cryptocoin::Protocol::Message.parse(command, payload)
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize(magic, command, payload_length, payload_checksum, message, network)
|
28
|
+
@magic_raw = magic
|
29
|
+
@command_raw = command
|
30
|
+
@payload_length_raw = payload_length
|
31
|
+
@payload_checksum_raw = payload_checksum
|
32
|
+
@message = message
|
33
|
+
@network = network
|
34
|
+
end
|
35
|
+
|
36
|
+
def magic
|
37
|
+
@magic_raw.unpack('L')[0]
|
38
|
+
end
|
39
|
+
|
40
|
+
def command
|
41
|
+
@command_raw.unpack('a*')[0]
|
42
|
+
end
|
43
|
+
|
44
|
+
def payload_length
|
45
|
+
@payload_length_raw.unpack('L')[0]
|
46
|
+
end
|
47
|
+
|
48
|
+
def payload_checksum
|
49
|
+
@payload_checksum_raw.unpack('L')[0]
|
50
|
+
end
|
51
|
+
|
52
|
+
def valid?
|
53
|
+
valid_checksum and valid_magic and valid_message
|
54
|
+
end
|
55
|
+
|
56
|
+
def raw
|
57
|
+
@magic_raw + @command_raw + @payload_length_raw + @payload_checksum_raw + @message.raw
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def valid_checksum
|
62
|
+
Cryptocoin::Digest.new(@message.raw, :binary).sha256[0..4] == @payload_checksum_raw
|
63
|
+
end
|
64
|
+
|
65
|
+
def valid_magic
|
66
|
+
magic == network.magic
|
67
|
+
end
|
68
|
+
|
69
|
+
def valid_message
|
70
|
+
@message.valid?
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Cryptocoin
|
2
|
+
module Protocol
|
3
|
+
class VarLenInt
|
4
|
+
# https://github.com/andrew12/bitcoin-ruby/blob/master/lib/bitcoin.rb#L132
|
5
|
+
# TODO: test this implementation
|
6
|
+
def self.from_int(i)
|
7
|
+
if i < -0xffffffffffffffff
|
8
|
+
return ArgumentError, "Unrepresentable"
|
9
|
+
elsif i < 0
|
10
|
+
top_32 = ((-i) & 0xffffffff00000000) >> 32
|
11
|
+
btm_32 = (-i) & 0x00000000ffffffff
|
12
|
+
return self.new([0xff, top_32, btm_32].pack("CVV"))
|
13
|
+
elsif i <= 0xfc
|
14
|
+
return self.new([i].pack('C'))
|
15
|
+
elsif i <= 0xffff
|
16
|
+
return self.new([0xfd, i].pack("Cv"))
|
17
|
+
elsif i <= 0xffffffff
|
18
|
+
return self.new([0xfe, i].pack("CV"))
|
19
|
+
else
|
20
|
+
return ArgumentError, "Unrepresentable"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.parse_from_io(io)
|
25
|
+
i = io.read(1)
|
26
|
+
j = i.unpack('C')[0]
|
27
|
+
case j
|
28
|
+
when 0xfd
|
29
|
+
self.new(i + io.read(2))
|
30
|
+
when 0xfe
|
31
|
+
self.new(i + io.read(4))
|
32
|
+
when 0xff
|
33
|
+
self.new(i + io.read(8))
|
34
|
+
else
|
35
|
+
puts "Something: #{i}"
|
36
|
+
self.new(i)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize(raw)
|
41
|
+
@head_raw = raw[0]
|
42
|
+
@head = @head_raw.unpack('C')[0]
|
43
|
+
@body = case @head
|
44
|
+
when 0xfd
|
45
|
+
@raw_i = raw[1..3]
|
46
|
+
@raw_i.unpack('v')[0]
|
47
|
+
when 0xfe
|
48
|
+
@raw_i = raw[1..5]
|
49
|
+
@raw_i.unpack('V')[0]
|
50
|
+
when 0xff
|
51
|
+
@raw_i = raw[1..9]
|
52
|
+
@raw_i.unpack('Q')[0]
|
53
|
+
else
|
54
|
+
@raw_i = @head_raw
|
55
|
+
@head
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_i
|
60
|
+
@body
|
61
|
+
end
|
62
|
+
|
63
|
+
def head
|
64
|
+
@head
|
65
|
+
end
|
66
|
+
|
67
|
+
def body_raw
|
68
|
+
@raw_i
|
69
|
+
end
|
70
|
+
|
71
|
+
def body
|
72
|
+
@body
|
73
|
+
end
|
74
|
+
|
75
|
+
def raw
|
76
|
+
@head_raw + (@raw_i == @head_raw ? '' : @raw_i)
|
77
|
+
end
|
78
|
+
|
79
|
+
def method_missing(name, *args, &block)
|
80
|
+
ret = body.send(name, *args, &block)
|
81
|
+
ret
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'cryptocoin/protocol/var_len_int'
|
2
|
+
|
3
|
+
module Cryptocoin
|
4
|
+
module Protocol
|
5
|
+
class VarLenStr < String
|
6
|
+
def initialize(raw)
|
7
|
+
@size = Cryptocoin::Protocol::VarLenInt.new(raw)
|
8
|
+
@str = raw.read(@size)
|
9
|
+
end
|
10
|
+
def size
|
11
|
+
@size
|
12
|
+
end
|
13
|
+
def to_s
|
14
|
+
@str
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|