open-core 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.travis.yml +15 -0
- data/.yardopts +8 -0
- data/CONTRIBUTING.md +48 -0
- data/Gemfile +15 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +202 -0
- data/README.md +83 -0
- data/Rakefile +4 -0
- data/examples/create_account.rb +26 -0
- data/examples/low_level_transaction_post.rb +46 -0
- data/examples/mid_level_transaction_post.rb +33 -0
- data/examples/non_native_payment.rb +60 -0
- data/examples/offer.rb +75 -0
- data/examples/transaction_merge.rb +23 -0
- data/generated/stellar-base-generated.rb +134 -0
- data/generated/stellar/account_entry.rb +53 -0
- data/generated/stellar/account_entry/ext.rb +24 -0
- data/generated/stellar/account_flags.rb +27 -0
- data/generated/stellar/account_merge_result.rb +26 -0
- data/generated/stellar/account_merge_result_code.rb +30 -0
- data/generated/stellar/allow_trust_op.rb +38 -0
- data/generated/stellar/allow_trust_op/asset.rb +33 -0
- data/generated/stellar/allow_trust_result.rb +25 -0
- data/generated/stellar/allow_trust_result_code.rb +31 -0
- data/generated/stellar/asset.rb +47 -0
- data/generated/stellar/asset/alpha_num12.rb +22 -0
- data/generated/stellar/asset/alpha_num4.rb +22 -0
- data/generated/stellar/asset_type.rb +24 -0
- data/generated/stellar/bucket_entry.rb +28 -0
- data/generated/stellar/bucket_entry_type.rb +22 -0
- data/generated/stellar/change_trust_op.rb +22 -0
- data/generated/stellar/change_trust_result.rb +25 -0
- data/generated/stellar/change_trust_result_code.rb +30 -0
- data/generated/stellar/claim_offer_atom.rb +33 -0
- data/generated/stellar/create_account_op.rb +20 -0
- data/generated/stellar/create_account_result.rb +25 -0
- data/generated/stellar/create_account_result_code.rb +32 -0
- data/generated/stellar/create_passive_offer_op.rb +24 -0
- data/generated/stellar/crypto_key_type.rb +20 -0
- data/generated/stellar/decorated_signature.rb +20 -0
- data/generated/stellar/dont_have.rb +20 -0
- data/generated/stellar/envelope_type.rb +22 -0
- data/generated/stellar/error.rb +20 -0
- data/generated/stellar/hello.rb +26 -0
- data/generated/stellar/inflation_payout.rb +20 -0
- data/generated/stellar/inflation_result.rb +26 -0
- data/generated/stellar/inflation_result_code.rb +24 -0
- data/generated/stellar/ledger_entry.rb +44 -0
- data/generated/stellar/ledger_entry/data.rb +33 -0
- data/generated/stellar/ledger_entry/ext.rb +24 -0
- data/generated/stellar/ledger_entry_change.rb +31 -0
- data/generated/stellar/ledger_entry_change_type.rb +24 -0
- data/generated/stellar/ledger_entry_type.rb +24 -0
- data/generated/stellar/ledger_header.rb +65 -0
- data/generated/stellar/ledger_header/ext.rb +24 -0
- data/generated/stellar/ledger_header_history_entry.rb +33 -0
- data/generated/stellar/ledger_header_history_entry/ext.rb +24 -0
- data/generated/stellar/ledger_key.rb +50 -0
- data/generated/stellar/ledger_key/account.rb +20 -0
- data/generated/stellar/ledger_key/offer.rb +22 -0
- data/generated/stellar/ledger_key/trust_line.rb +22 -0
- data/generated/stellar/ledger_upgrade.rb +27 -0
- data/generated/stellar/ledger_upgrade_type.rb +22 -0
- data/generated/stellar/manage_offer_effect.rb +24 -0
- data/generated/stellar/manage_offer_op.rb +28 -0
- data/generated/stellar/manage_offer_result.rb +26 -0
- data/generated/stellar/manage_offer_result_code.rb +48 -0
- data/generated/stellar/manage_offer_success_result.rb +34 -0
- data/generated/stellar/manage_offer_success_result/offer.rb +30 -0
- data/generated/stellar/memo.rb +38 -0
- data/generated/stellar/memo_type.rb +28 -0
- data/generated/stellar/message_type.rb +45 -0
- data/generated/stellar/offer_entry.rb +49 -0
- data/generated/stellar/offer_entry/ext.rb +24 -0
- data/generated/stellar/offer_entry_flags.rb +21 -0
- data/generated/stellar/operation.rb +51 -0
- data/generated/stellar/operation/body.rb +60 -0
- data/generated/stellar/operation_meta.rb +18 -0
- data/generated/stellar/operation_result.rb +53 -0
- data/generated/stellar/operation_result/tr.rb +61 -0
- data/generated/stellar/operation_result_code.rb +25 -0
- data/generated/stellar/operation_type.rb +38 -0
- data/generated/stellar/path_payment_op.rb +32 -0
- data/generated/stellar/path_payment_result.rb +34 -0
- data/generated/stellar/path_payment_result/success.rb +22 -0
- data/generated/stellar/path_payment_result_code.rb +45 -0
- data/generated/stellar/payment_op.rb +22 -0
- data/generated/stellar/payment_result.rb +25 -0
- data/generated/stellar/payment_result_code.rb +39 -0
- data/generated/stellar/peer_address.rb +22 -0
- data/generated/stellar/price.rb +20 -0
- data/generated/stellar/public_key.rb +23 -0
- data/generated/stellar/scp_ballot.rb +20 -0
- data/generated/stellar/scp_envelope.rb +20 -0
- data/generated/stellar/scp_nomination.rb +22 -0
- data/generated/stellar/scp_quorum_set.rb +22 -0
- data/generated/stellar/scp_statement.rb +59 -0
- data/generated/stellar/scp_statement/pledges.rb +64 -0
- data/generated/stellar/scp_statement/pledges/confirm.rb +28 -0
- data/generated/stellar/scp_statement/pledges/externalize.rb +28 -0
- data/generated/stellar/scp_statement/pledges/prepare.rb +32 -0
- data/generated/stellar/scp_statement_type.rb +26 -0
- data/generated/stellar/set_options_op.rb +41 -0
- data/generated/stellar/set_options_result.rb +25 -0
- data/generated/stellar/set_options_result_code.rb +38 -0
- data/generated/stellar/signer.rb +20 -0
- data/generated/stellar/simple_payment_result.rb +22 -0
- data/generated/stellar/stellar_message.rb +66 -0
- data/generated/stellar/stellar_value.rb +40 -0
- data/generated/stellar/stellar_value/ext.rb +24 -0
- data/generated/stellar/threshold_indexes.rb +26 -0
- data/generated/stellar/time_bounds.rb +20 -0
- data/generated/stellar/transaction.rb +50 -0
- data/generated/stellar/transaction/ext.rb +24 -0
- data/generated/stellar/transaction_envelope.rb +20 -0
- data/generated/stellar/transaction_history_entry.rb +33 -0
- data/generated/stellar/transaction_history_entry/ext.rb +24 -0
- data/generated/stellar/transaction_history_result_entry.rb +33 -0
- data/generated/stellar/transaction_history_result_entry/ext.rb +24 -0
- data/generated/stellar/transaction_meta.rb +31 -0
- data/generated/stellar/transaction_meta/v0.rb +22 -0
- data/generated/stellar/transaction_result.rb +43 -0
- data/generated/stellar/transaction_result/ext.rb +24 -0
- data/generated/stellar/transaction_result/result.rb +30 -0
- data/generated/stellar/transaction_result_code.rb +45 -0
- data/generated/stellar/transaction_result_pair.rb +20 -0
- data/generated/stellar/transaction_result_set.rb +18 -0
- data/generated/stellar/transaction_set.rb +20 -0
- data/generated/stellar/trust_line_entry.rb +41 -0
- data/generated/stellar/trust_line_entry/ext.rb +24 -0
- data/generated/stellar/trust_line_flags.rb +21 -0
- data/lib/stellar-base.rb +32 -0
- data/lib/stellar/account_flags.rb +28 -0
- data/lib/stellar/asset.rb +69 -0
- data/lib/stellar/base.rb +1 -0
- data/lib/stellar/base/version.rb +5 -0
- data/lib/stellar/convert.rb +32 -0
- data/lib/stellar/key_pair.rb +112 -0
- data/lib/stellar/networks.rb +45 -0
- data/lib/stellar/operation.rb +304 -0
- data/lib/stellar/path_payment_result.rb +17 -0
- data/lib/stellar/price.rb +32 -0
- data/lib/stellar/thresholds.rb +39 -0
- data/lib/stellar/transaction.rb +170 -0
- data/lib/stellar/transaction_envelope.rb +32 -0
- data/lib/stellar/util/continued_fraction.rb +96 -0
- data/lib/stellar/util/strkey.rb +43 -0
- data/open-core.gemspec +37 -0
- data/spec/lib/stellar/account_flags_spec.rb +19 -0
- data/spec/lib/stellar/asset_spec.rb +45 -0
- data/spec/lib/stellar/convert_spec.rb +61 -0
- data/spec/lib/stellar/key_pair_spec.rb +238 -0
- data/spec/lib/stellar/networks_spec.rb +77 -0
- data/spec/lib/stellar/path_payment_result_spec.rb +95 -0
- data/spec/lib/stellar/price_spec.rb +34 -0
- data/spec/lib/stellar/thresholds_spec.rb +62 -0
- data/spec/lib/stellar/transaction_envelope_spec.rb +93 -0
- data/spec/lib/stellar/transaction_spec.rb +54 -0
- data/spec/lib/stellar/util/strkey_spec.rb +46 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/support/matchers/be_strkey.rb +9 -0
- data/spec/support/matchers/eq_bytes.rb +5 -0
- data/spec/support/matchers/have_length.rb +5 -0
- data/tasks/rspec.rake +6 -0
- data/tasks/travis.rake +1 -0
- data/tasks/xdr.rake +50 -0
- data/xdr/Stellar-SCP.x +87 -0
- data/xdr/Stellar-ledger-entries.x +222 -0
- data/xdr/Stellar-ledger.x +231 -0
- data/xdr/Stellar-overlay.x +87 -0
- data/xdr/Stellar-transaction.x +670 -0
- data/xdr/Stellar-types.x +34 -0
- metadata +444 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Stellar::Price, "#from_f" do
|
4
|
+
subject{ Stellar::Price }
|
5
|
+
let(:seed){ 225571644875421139403973254661022579608 } #generated using Random.new
|
6
|
+
let(:random){ Random.new(seed) }
|
7
|
+
let(:iterations){ ENV["SMOKE_ITERATIONS"].present? ? ENV["SMOKE_ITERATIONS"].to_i : 2000}
|
8
|
+
|
9
|
+
it "withstands a random smoke test" do
|
10
|
+
iterations.times do |i|
|
11
|
+
expected = random.rand
|
12
|
+
actual_p = subject.from_f(expected)
|
13
|
+
actual = actual_p.to_f
|
14
|
+
|
15
|
+
expect(actual).to be_within(0.000000001).of(actual)
|
16
|
+
expect(actual_p.n).to be <= Stellar::Price::MAX_PRECISION
|
17
|
+
expect(actual_p.d).to be <= Stellar::Price::MAX_PRECISION
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "works with bigdecimal" do
|
22
|
+
whole = random.rand(1_000_000)
|
23
|
+
fractional = random.rand(10_000_000) # seven significant digits available for fractional
|
24
|
+
|
25
|
+
expected = BigDecimal.new("#{whole}.#{fractional}")
|
26
|
+
actual_p = subject.from_f(expected)
|
27
|
+
actual = BigDecimal.new(actual_p.n) / BigDecimal.new(actual_p.d)
|
28
|
+
|
29
|
+
expect(actual).to be_within(BigDecimal.new("0.000000001")).of(actual)
|
30
|
+
expect(actual_p.n).to be <= Stellar::Price::MAX_PRECISION
|
31
|
+
expect(actual_p.d).to be <= Stellar::Price::MAX_PRECISION
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Stellar::Thresholds, ".parse" do
|
4
|
+
subject{ Stellar::Thresholds }
|
5
|
+
let(:raw) { "\x01\x02\x03\x04" }
|
6
|
+
let(:result) { subject.parse raw }
|
7
|
+
|
8
|
+
it "sets master_weight as the 1st byte" do
|
9
|
+
expect(result[:master_weight]).to eq(1)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "sets low as the 2nd byte" do
|
13
|
+
expect(result[:low]).to eq(2)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "sets medium as the 3rd byte" do
|
17
|
+
expect(result[:medium]).to eq(3)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "sets high as the 4th byte" do
|
21
|
+
expect(result[:high]).to eq(4)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe Stellar::Thresholds, ".make" do
|
26
|
+
subject{ Stellar::Thresholds }
|
27
|
+
let(:good){{master_weight: 1, low: 2, medium: 3, high: 4}}
|
28
|
+
|
29
|
+
it "works" do
|
30
|
+
expect(subject.make(good)).to eq("\x01\x02\x03\x04")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "errors unless all components are provided" do
|
34
|
+
expect{ subject.make(good.except(:master_weight)) }.to raise_error(ArgumentError)
|
35
|
+
expect{ subject.make(good.except(:low)) }.to raise_error(ArgumentError)
|
36
|
+
expect{ subject.make(good.except(:medium)) }.to raise_error(ArgumentError)
|
37
|
+
expect{ subject.make(good.except(:high)) }.to raise_error(ArgumentError)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "errors unless all components are numbers" do
|
41
|
+
expect{ subject.make(good.merge(master_weight: "hello")) }.to raise_error(ArgumentError)
|
42
|
+
expect{ subject.make(good.merge(low: "hello")) }.to raise_error(ArgumentError)
|
43
|
+
expect{ subject.make(good.merge(medium: "hello")) }.to raise_error(ArgumentError)
|
44
|
+
expect{ subject.make(good.merge(high: "hello")) }.to raise_error(ArgumentError)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "errors unless all components are in (0..255)" do
|
48
|
+
expect{ subject.make(good.merge(master_weight: -1)) }.to raise_error(ArgumentError)
|
49
|
+
expect{ subject.make(good.merge(master_weight: 256)) }.to raise_error(ArgumentError)
|
50
|
+
expect{ subject.make(good.merge(low: -1)) }.to raise_error(ArgumentError)
|
51
|
+
expect{ subject.make(good.merge(low: 256)) }.to raise_error(ArgumentError)
|
52
|
+
expect{ subject.make(good.merge(medium: -1)) }.to raise_error(ArgumentError)
|
53
|
+
expect{ subject.make(good.merge(medium: 256)) }.to raise_error(ArgumentError)
|
54
|
+
expect{ subject.make(good.merge(high: -1)) }.to raise_error(ArgumentError)
|
55
|
+
expect{ subject.make(good.merge(high: 256)) }.to raise_error(ArgumentError)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "ignores additional keys" do
|
59
|
+
expect{ subject.make(good.merge(foo: "a string")) }.not_to raise_error
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Stellar::TransactionEnvelope do
|
4
|
+
let(:sender) { Stellar::KeyPair.random }
|
5
|
+
let(:receiver){ Stellar::KeyPair.random }
|
6
|
+
let(:transaction) do
|
7
|
+
Stellar::Transaction.payment({
|
8
|
+
account: sender,
|
9
|
+
destination: receiver,
|
10
|
+
sequence: 1,
|
11
|
+
amount: [:native, 20000000]
|
12
|
+
})
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:envelope){ transaction.to_envelope(*signers) }
|
16
|
+
|
17
|
+
describe "#signed_correctly?" do
|
18
|
+
subject{ envelope.signed_correctly?(*verifiers) }
|
19
|
+
|
20
|
+
context "when unsigned" do
|
21
|
+
let(:signers) { [] }
|
22
|
+
let(:verifiers){ [sender] }
|
23
|
+
|
24
|
+
it{ should be_falsey }
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when signed by a single account" do
|
28
|
+
let(:signers) { [sender] }
|
29
|
+
let(:verifiers){ signers }
|
30
|
+
|
31
|
+
context "and signed correctly" do
|
32
|
+
it{ should be_truthy }
|
33
|
+
end
|
34
|
+
|
35
|
+
context "and the signature is corrupted" do
|
36
|
+
before(:each){ envelope.signatures.first.signature = "\xFF" * 32}
|
37
|
+
it{ should be_falsey }
|
38
|
+
end
|
39
|
+
|
40
|
+
context "and the signature is from a different message" do
|
41
|
+
before(:each){ envelope.signatures = [sender.sign_decorated("hello")]}
|
42
|
+
it{ should be_falsey }
|
43
|
+
end
|
44
|
+
|
45
|
+
context "and the key for the signing account is not provided" do
|
46
|
+
let(:verifiers){ [] }
|
47
|
+
it{ should be_falsey }
|
48
|
+
end
|
49
|
+
|
50
|
+
context "and the key for the signing account is wrong" do
|
51
|
+
let(:verifiers){ [receiver] }
|
52
|
+
it{ should be_falsey }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "when signed by a multiple accounts" do
|
57
|
+
let(:alternate_signer){ Stellar::KeyPair.random }
|
58
|
+
let(:signers) { [sender, alternate_signer] }
|
59
|
+
let(:verifiers){ signers }
|
60
|
+
|
61
|
+
context "and all public keys are provided" do
|
62
|
+
it{ should be_truthy }
|
63
|
+
end
|
64
|
+
|
65
|
+
context "and all public keys are provided, with additional unused keys provided" do
|
66
|
+
let(:verifiers){ signers + [Stellar::KeyPair.random] }
|
67
|
+
it{ should be_truthy }
|
68
|
+
end
|
69
|
+
|
70
|
+
context "and not all public keys for the signers are provided" do
|
71
|
+
let(:verifiers){ [alternate_signer] }
|
72
|
+
it{ should be_falsey }
|
73
|
+
end
|
74
|
+
|
75
|
+
context "and one of the signatures is corrupted" do
|
76
|
+
before(:each){ envelope.signatures.last.signature = "\xFF" * 32}
|
77
|
+
it{ should be_falsey }
|
78
|
+
end
|
79
|
+
|
80
|
+
context "and the signature is from a different message" do
|
81
|
+
before(:each){ envelope.signatures = signers.map{|s| s.sign_decorated("hello")}}
|
82
|
+
it{ should be_falsey }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "#hash" do
|
89
|
+
let(:signers) { [sender] }
|
90
|
+
subject{ envelope.hash }
|
91
|
+
it{ should eq(Digest::SHA256.digest envelope.to_xdr)}
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Stellar::Transaction do
|
4
|
+
subject do
|
5
|
+
Stellar::Transaction.new({
|
6
|
+
source_account: Stellar::AccountID.new(:key_type_ed25519, "\x00" * 32),
|
7
|
+
fee: 10,
|
8
|
+
seq_num: 1,
|
9
|
+
memo: Stellar::Memo.new(:memo_none),
|
10
|
+
ext: Stellar::Transaction::Ext.new(0),
|
11
|
+
operations: [
|
12
|
+
Stellar::Operation.new(body: Stellar::Operation::Body.new(:inflation))
|
13
|
+
]
|
14
|
+
})
|
15
|
+
end
|
16
|
+
let(:key_pair){ Stellar::KeyPair.random }
|
17
|
+
|
18
|
+
describe "#sign" do
|
19
|
+
let(:result){ subject.sign(key_pair) }
|
20
|
+
|
21
|
+
it "returns a signature of SHA256(signature_base of the transaction)" do
|
22
|
+
hash = Digest::SHA256.digest(subject.signature_base)
|
23
|
+
expected = key_pair.sign(hash)
|
24
|
+
expect(result).to eq(expected)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#to_envelope" do
|
29
|
+
let(:result){ subject.to_envelope(key_pair) }
|
30
|
+
|
31
|
+
it "return a Stellar::TransactionEnvelope" do
|
32
|
+
expect(result).to be_a(Stellar::TransactionEnvelope)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "correctly signs the transaction" do
|
36
|
+
expect(result.signatures.length).to eq(1)
|
37
|
+
expect(result.signatures.first).to be_a(Stellar::DecoratedSignature)
|
38
|
+
expect(result.signatures.first.hint).to eq(key_pair.signature_hint)
|
39
|
+
expect(result.signatures.first.signature).to eq(subject.sign(key_pair))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#signature_base" do
|
44
|
+
|
45
|
+
it "is prefixed with the current network id" do
|
46
|
+
expect(subject.signature_base).to start_with(Stellar.current_network_id)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "includes the envelope type" do
|
50
|
+
expect(subject.signature_base[32...36]).to eql("\x00\x00\x00\x02")
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Stellar::Util::StrKey do
|
4
|
+
|
5
|
+
subject{ Stellar::Util::StrKey }
|
6
|
+
|
7
|
+
describe "#check_decode" do
|
8
|
+
it "properly decodes" do
|
9
|
+
expect(decode :seed, "SAAAAAAAAAADST3H").to eq_bytes("\x00\x00\x00\x00\x00\x00\x39")
|
10
|
+
expect(decode :account_id, "GD777777777764TU").to eq_bytes("\xFF\xFF\xFF\xFF\xFF\xFF\xFF")
|
11
|
+
expect(decode :account_id, "GBQWWBFLRP3BXZD5").to eq_bytes("\x61\x6b\x04\xab\x8b\xf6\x1b")
|
12
|
+
end
|
13
|
+
|
14
|
+
it "raises an ArgumentError if the decoded version byte does not match the expected value" do
|
15
|
+
expect{ decode :seed, "GD777777777764TU" }.to raise_error(ArgumentError)
|
16
|
+
expect{ decode :account_id, "SAAAAAAAAAADST3M" }.to raise_error(ArgumentError)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "raises an ArgumentError if the decoded value cannot be validated by the checksum" do
|
20
|
+
expect{decode :seed, "SAAAAAAAAAADST3M"}.to raise_error(ArgumentError)
|
21
|
+
end
|
22
|
+
|
23
|
+
def decode(version, bytes)
|
24
|
+
subject.check_decode(version, bytes)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe"#check_encode" do
|
29
|
+
it "properly encodes" do
|
30
|
+
expect(encode :seed, "\x00\x00\x00\x00\x00\x00\x39").to eq("SAAAAAAAAAADST3H")
|
31
|
+
expect(encode :account_id, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF").to eq("GD777777777764TU")
|
32
|
+
expect(encode :account_id, "\x61\x6b\x04\xab\x8b\xf6\x1b").to eq("GBQWWBFLRP3BXZD5")
|
33
|
+
end
|
34
|
+
|
35
|
+
it "raises an ArgumentError when an invalid version is provided" do
|
36
|
+
expect{ encode :floob, "\x39" }.to raise_error(ArgumentError)
|
37
|
+
end
|
38
|
+
|
39
|
+
def encode(version, bytes)
|
40
|
+
subject.check_encode(version, bytes)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
Bundler.setup
|
3
|
+
|
4
|
+
require 'simplecov'
|
5
|
+
SimpleCov.start
|
6
|
+
|
7
|
+
require 'pry'
|
8
|
+
require 'stellar-base'
|
9
|
+
|
10
|
+
SPEC_ROOT = File.dirname(__FILE__)
|
11
|
+
|
12
|
+
Dir["#{SPEC_ROOT}/support/**/*.rb"].each { |f| require f }
|
13
|
+
|
14
|
+
RSpec.configure do |config|
|
15
|
+
|
16
|
+
end
|
data/tasks/rspec.rake
ADDED
data/tasks/travis.rake
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
task :travis => %w(spec)
|
data/tasks/xdr.rake
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
namespace :xdr do
|
2
|
+
|
3
|
+
# As Hayashi adds more .x files, we'll need to update this array
|
4
|
+
# Prior to launch, we should be separating our .x files into a separate
|
5
|
+
# repo, and should be able to improve this integration.
|
6
|
+
HAYASHI_XDR = [
|
7
|
+
"src/xdr/Stellar-types.x",
|
8
|
+
"src/xdr/Stellar-ledger-entries.x",
|
9
|
+
"src/xdr/Stellar-transaction.x",
|
10
|
+
"src/xdr/Stellar-ledger.x",
|
11
|
+
"src/xdr/Stellar-overlay.x",
|
12
|
+
"src/xdr/Stellar-SCP.x",
|
13
|
+
]
|
14
|
+
|
15
|
+
LOCAL_XDR_PATHS = HAYASHI_XDR.map{ |src| "xdr/" + File.basename(src) }
|
16
|
+
|
17
|
+
task :update => [:download, :generate]
|
18
|
+
|
19
|
+
task :download do
|
20
|
+
require 'octokit'
|
21
|
+
require 'base64'
|
22
|
+
FileUtils.rm_rf "xdr/"
|
23
|
+
FileUtils.mkdir_p "xdr"
|
24
|
+
|
25
|
+
client = Octokit::Client.new(:netrc => true)
|
26
|
+
|
27
|
+
HAYASHI_XDR.each do |src|
|
28
|
+
local_path = "xdr/" + File.basename(src)
|
29
|
+
encoded = client.contents("stellar/stellar-core", path: src).content
|
30
|
+
decoded = Base64.decode64 encoded
|
31
|
+
|
32
|
+
IO.write(local_path, decoded)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
task :generate do
|
37
|
+
require "pathname"
|
38
|
+
require "xdrgen"
|
39
|
+
require 'fileutils'
|
40
|
+
FileUtils.rm_rf "generated"
|
41
|
+
|
42
|
+
compilation = Xdrgen::Compilation.new(
|
43
|
+
LOCAL_XDR_PATHS,
|
44
|
+
output_dir: "generated",
|
45
|
+
namespace: "stellar-base-generated",
|
46
|
+
language: :ruby
|
47
|
+
)
|
48
|
+
compilation.compile
|
49
|
+
end
|
50
|
+
end
|
data/xdr/Stellar-SCP.x
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
// Copyright 2015 Stellar Development Foundation and contributors. Licensed
|
2
|
+
// under the Apache License, Version 2.0. See the COPYING file at the root
|
3
|
+
// of this distribution or at http://www.apache.org/licenses/LICENSE-2.0
|
4
|
+
|
5
|
+
%#include "xdr/Stellar-types.h"
|
6
|
+
|
7
|
+
namespace stellar
|
8
|
+
{
|
9
|
+
|
10
|
+
typedef opaque Value<>;
|
11
|
+
|
12
|
+
struct SCPBallot
|
13
|
+
{
|
14
|
+
uint32 counter; // n
|
15
|
+
Value value; // x
|
16
|
+
};
|
17
|
+
|
18
|
+
enum SCPStatementType
|
19
|
+
{
|
20
|
+
SCP_ST_PREPARE = 0,
|
21
|
+
SCP_ST_CONFIRM = 1,
|
22
|
+
SCP_ST_EXTERNALIZE = 2,
|
23
|
+
SCP_ST_NOMINATE = 3
|
24
|
+
};
|
25
|
+
|
26
|
+
struct SCPNomination
|
27
|
+
{
|
28
|
+
Hash quorumSetHash; // D
|
29
|
+
Value votes<>; // X
|
30
|
+
Value accepted<>; // Y
|
31
|
+
};
|
32
|
+
|
33
|
+
struct SCPStatement
|
34
|
+
{
|
35
|
+
NodeID nodeID; // v
|
36
|
+
uint64 slotIndex; // i
|
37
|
+
|
38
|
+
union switch (SCPStatementType type)
|
39
|
+
{
|
40
|
+
case SCP_ST_PREPARE:
|
41
|
+
struct
|
42
|
+
{
|
43
|
+
Hash quorumSetHash; // D
|
44
|
+
SCPBallot ballot; // b
|
45
|
+
SCPBallot* prepared; // p
|
46
|
+
SCPBallot* preparedPrime; // p'
|
47
|
+
uint32 nC; // n_c
|
48
|
+
uint32 nP; // n_P
|
49
|
+
} prepare;
|
50
|
+
case SCP_ST_CONFIRM:
|
51
|
+
struct
|
52
|
+
{
|
53
|
+
Hash quorumSetHash; // D
|
54
|
+
uint32 nPrepared; // n_p
|
55
|
+
SCPBallot commit; // c
|
56
|
+
uint32 nP; // n_P
|
57
|
+
} confirm;
|
58
|
+
case SCP_ST_EXTERNALIZE:
|
59
|
+
struct
|
60
|
+
{
|
61
|
+
SCPBallot commit; // c
|
62
|
+
uint32 nP; // n_P
|
63
|
+
// not from the paper, but useful to build tooling to
|
64
|
+
// traverse the graph based off only the latest statement
|
65
|
+
Hash commitQuorumSetHash; // D used before EXTERNALIZE
|
66
|
+
} externalize;
|
67
|
+
case SCP_ST_NOMINATE:
|
68
|
+
SCPNomination nominate;
|
69
|
+
}
|
70
|
+
pledges;
|
71
|
+
};
|
72
|
+
|
73
|
+
struct SCPEnvelope
|
74
|
+
{
|
75
|
+
SCPStatement statement;
|
76
|
+
Signature signature;
|
77
|
+
};
|
78
|
+
|
79
|
+
// supports things like: A,B,C,(D,E,F),(G,H,(I,J,K,L))
|
80
|
+
// only allows 2 levels of nesting
|
81
|
+
struct SCPQuorumSet
|
82
|
+
{
|
83
|
+
uint32 threshold;
|
84
|
+
PublicKey validators<>;
|
85
|
+
SCPQuorumSet innerSets<>;
|
86
|
+
};
|
87
|
+
}
|