17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
# File 'bin/wallet.rb', line 17
def build_transaction(from_address, to_address, amount)
Bitcoin.network = :bitcoin
w = Mastercoin::BitcoinWrapper.new(options[:bitcoin_rpc])
puts "+----------------------------------+"
puts "+ WARNING: ALPHA SOFTWARE +"
puts "+----------------------------------+"
puts ""
puts "This software might: "
puts "1. Skin and eat your cat alive"
puts "2. Eat your bitcoins"
puts "3. Do other scary things you never intended"
puts "So for now please only use this if you can read enough code to understand what is happening."
puts ""
puts "Please type: yup if you want to continue."
STDOUT.flush
do_it = $stdin.gets
unless do_it == "yup\n"
puts "I don't blame you, exiting"
exit
end
puts ""
puts "This script requires the private key of your mastercoin address in order to create a signed transaction. It will need to unlock your wallet in order to do so."
puts "Please type your wallet passphrase to unlock your wallet for 30 seconds."
password = STDIN.noecho(&:gets)
password = password.gsub("\n","")
w.walletpassphrase(password, 30)
puts "Checking funds for address #{from_address}"
inputs = w.unspend_for_address(from_address).find{|x| next if x.nil?; x["amount"].to_f > (0.00006 * 3)}
unless inputs
puts("There are not enough bitcoin available to create a valid looking Mastercoin transaction. We want one output with enough funds for now.")
exit
else
puts("Enough Bitcoin funds available")
end
puts ">> Not checking for Mastercoin balance yet; assuming enough."
puts "Getting private key and public key for Mastercoin address"
private_key = w.dumpprivkey(from_address)
public_key = w.validateaddress(from_address)["pubkey"]
if inputs.is_a?(Array)
chosen_input = inputs.first
else
chosen_input = inputs
end
puts "Getting raw transaction data"
prev_tx = w.getrawtransaction(chosen_input["txid"])
puts "Found raw transaction; unpacking into tx"
prev_tx = Bitcoin::Protocol::Tx.new([prev_tx].pack("H*"))
total_amount = chosen_input["amount"]
fee = 0.0001
tx_amount = 0.00006
mastercoin_tx = (4 * tx_amount)
change_amount = total_amount - fee - mastercoin_tx
puts "Setting fees"
data_key = Mastercoin::SimpleSend.new(currency_id: 2, amount: amount.to_f * 1e8).encode_to_compressed_public_key
puts "Total amount available from input: #{total_amount}"
puts "Paying #{fee} network fees"
puts "Taking #{mastercoin_tx} out of total for each mastercoin output"
puts "Sending #{change_amount} back to mastercoin address"
puts "Using public key for data: #{data_key}"
tx = build_tx do |t|
t.input do |i|
i.prev_out prev_tx
i.prev_out_index chosen_input["vout"]
i.signature_key Bitcoin::Key.from_base58(private_key)
end
t.output do |o|
o.value change_amount * 1e8
o.script do |s|
s.type :address
s.recipient from_address
end
end
t.output do |o|
o.value tx_amount * 1e8
o.script do |s|
s.type :address
s.recipient to_address
end
end
t.output do |o|
o.value tx_amount * 1e8
o.script do |s|
s.type :address
s.recipient Mastercoin::EXODUS_ADDRESS
end
end
t.output do |o|
o.value (tx_amount * 1e8) * 2
o.script do |s|
s.type :multisig
s.recipient 1, public_key, data_key
end
end
end
tx = Bitcoin::Protocol::Tx.new( tx.to_payload )
puts "Need #{tx.calculate_minimum_fee / 1e8} fee-wise"
puts "TX Size: #{tx.to_payload.bytesize}"
valid = tx.verify_input_signature(0, prev_tx) == true
multisig = Bitcoin::Script.new(tx.out.last.script).is_multisig?
puts "Does this transaction look valid: #{valid}"
puts "Is a valid multisig transaction: #{multisig}"
puts "Transaction looks like: "
pp tx.to_hash
transaction_hash = tx.to_payload.unpack("H*").first
puts "Raw hex encoded transaction for Bitcoind: "
puts "-------------------------------------------------"
puts transaction_hash
puts "-------------------------------------------------"
puts "Sending #{amount} Testnet Mastercoins to #{to_address}."
puts "Want me to send this transaction via Bitcoind? [no]"
STDOUT.flush
do_it = $stdin.gets
if do_it == "yes\n"
puts "Broadcasting transaction"
w.sendrawtransaction(transaction_hash)
else
puts "Not broadcasting transaction"
end
end
|