forked from dsias/blockchain.info
-
Notifications
You must be signed in to change notification settings - Fork 0
/
signer.min.js
1 lines (1 loc) · 26.7 KB
/
signer.min.js
1
function exceptionToString(b){var a="";for(var c in b){a+="property: "+c+" value: ["+b[c]+"]\n"}return"toString(): value: ["+b.toString()+"]"}function generateNewMiniPrivateKey(){while(true){var c=new Bitcoin.ECKey(false);var b="S"+Bitcoin.Base58.encode(c.priv).substr(0,21);var f=Crypto.SHA256(b+"?",{asBytes:true});if(f[0]==0){var a=Crypto.SHA256(b,{asBytes:true});var d=new Bitcoin.ECKey(a);if(MyWallet.addPrivateKey(d)){return{key:d,miniKey:b}}}}}function IsCanonicalSignature(c){if(c.length<9){throw"Non-canonical signature: too short"}if(c.length>73){throw"Non-canonical signature: too long"}var b=c[c.length-1];if(b!=SIGHASH_ALL&&b!=SIGHASH_NONE&&b!=SIGHASH_SINGLE&&b!=SIGHASH_ANYONECANPAY){throw"Non-canonical signature: unknown hashtype byte "+b}if(c[0]!=48){throw"Non-canonical signature: wrong type"}if(c[1]!=c.length-3){throw"Non-canonical signature: wrong length marker"}var a=c[3];if(5+a>=c.length){throw"Non-canonical signature: S length misplaced"}var f=c[5+a];if(a+f+7!=c.length){throw"Non-canonical signature: R+S length mismatch"}var d=4;if(c[d-2]!=2){throw"Non-canonical signature: R value type mismatch"}if(a==0){throw"Non-canonical signature: R length is zero"}if(c[d+0]&128){throw"Non-canonical signature: R value negative"}if(a>1&&(c[d+0]==0)&&!(c[d+1]&128)){throw"Non-canonical signature: R value excessively padded"}var d=6+a;if(c[d-2]!=2){throw"Non-canonical signature: S value type mismatch"}if(f==0){throw"Non-canonical signature: S length is zero"}if(c[d+0]&128){throw"Non-canonical signature: S value negative"}if(f>1&&(c[d+0]==0)&&!(c[d+1]&128)){throw"Non-canonical signature: S value excessively padded"}return true}try{if(typeof window=="undefined"||!window){self.addEventListener("message",function(h){var g=h.data;try{switch(g.cmd){case"seed":var b=Crypto.util.bytesToWords(Crypto.util.hexToBytes(g.seed));for(var f in b){rng_seed_int(b[f])}break;case"decrypt":var c=Crypto.AES.decrypt(g.data,g.password,{mode:new Crypto.mode.CBC(Crypto.pad.iso10126),iterations:g.pbkdf2_iterations});self.postMessage({cmd:"on_decrypt",data:c});break;case"load_resource":importScripts(g.path);break;case"sign_input":var a=new Bitcoin.Transaction(g.tx);var d=new Bitcoin.Script(g.connected_script);var j=signInput(a,g.outputN,g.priv_to_use,d);if(j){self.postMessage({cmd:"on_sign",script:j,outputN:g.outputN})}else{throw"Unknown Error Signing Script "+g.outputN}break;default:throw"Unknown Command"}}catch(h){self.postMessage({cmd:"on_error",e:exceptionToString(h)})}},false)}}catch(e){}function showPrivateKeyModal(g,a,h){var c=$("#private-key-modal");c.modal({keyboard:true,backdrop:"static",show:true});c.center();c.find(".address").text(h);var d=null;var b=null;var f=c.find('input[name="key"]');f.val("");c.find(".qrcodeicon span").click(function(){c.modal("hide");MyWallet.scanQRCode(function(i){console.log("Scanned "+i);try{d=MyWallet.privateKeyStringToKey(i,MyWallet.detectPrivateKeyFormat(i));if(d==null){b="Error decoding private key"}}catch(j){b="Error decoding private key "+j}c.modal("show");f.val(i)},function(i){c.modal("show");MyWallet.makeNotice("error","misc-error",i)})});c.find(".btn.btn-primary").unbind().click(function(){var i=$.trim(f.val());try{if(i.length==0){throw"You must enter a private key to import"}d=MyWallet.privateKeyStringToKey(i,MyWallet.detectPrivateKeyFormat(i));if(d==null){throw"Could not decode private key"}}catch(j){b="Error importing private key "+j}c.modal("hide");if(d){g(d)}else{a(b)}});c.find(".btn.btn-secondary").unbind().click(function(){c.modal("hide");a("User Cancelled")})}function resolveAddress(a){a=$.trim(a);try{return new Bitcoin.Address(a).toString()}catch(f){}a=a.toLowerCase();var h=MyWallet.getAddressBook();for(var c in h){var d=MyWallet.getAddressBookLabel(c);if(d.toLowerCase()==a){return $.trim(c)}}var g=MyWallet.getAllAddresses();for(var b=0;b<g.length;++b){var c=g[b];var d=MyWallet.getAddressLabel(c);if(d&&d.toLowerCase()==a){return c}}return null}function startTxUI(a,j,f,c){function l(){a.find('input[name="send-value"]').val("");a.find('input[name="send-to-address"]').val("")}try{a.find("input,select,button").prop("disabled",true);f.addListener({on_success:function(n){a.find("input,select,button").removeProp("disabled")},on_start:function(n){a.find("input,select,button").prop("disabled",true)},on_error:function(n){a.find("input,select,button").removeProp("disabled")}});var g=0;a.find('input[name="send-value"]').each(function(){g+=parseFloat($(this).val())});var d=true;if(g>precisionFromBTC(10)){if(j=="email"||j=="sms"){throw"Cannot Send More Than 10 BTC via email or sms"}else{if(j=="quick"){j="custom";d=false}}}else{if(j=="shared"&&g<precisionFromBTC(0.2)){throw"The Minimum Amount You Can Send Shared is "+formatPrecision(precisionFromBTC(0.2))}else{if(j=="shared"&&g>precisionFromBTC(250)){throw"The Maximum Amount You Can Send Shared is "+formatPrecision(precisionFromBTC(250))}}}if(MyWallet.getMixerFee()<0&&(j=="custom"||j=="quick")&&g>=precisionFromBTC(5)&&getCookie("shared-never-ask")!="true"&&!c){var i=getCookie("shared-accepted-time");if(!i||parseInt(i)<new Date().getTime()-43200000){var m=$("#ask-for-shared");m.find(".bonus-percent").text(-MyWallet.getMixerFee());m.find(".bonus-value").text(formatPrecision((g/100)*-MyWallet.getMixerFee()));var k=m.find(".delay");if(g<=precisionFromBTC(10)){k.text("20 Seconds")}else{if(g<=precisionFromBTC(25)){k.text("10 Minutes")}else{if(g<=precisionFromBTC(250)){k.text("20 Minutes")}else{k.text("1 hour")}}}m.modal({keyboard:false,backdrop:"static",show:true});m.find(".btn.btn-primary").unbind().click(function(){var n=startTxUI(a,"shared",f);n.addListener({on_success:function(){SetCookie("shared-accepted-time",new Date().getTime())}});m.modal("hide")});m.find(".btn.btn-secondary").unbind().click(function(){m.modal("hide");startTxUI(a,j,f,true)});return}}if(j=="custom"||j=="shared"){var b={on_error:function(n){if(this.modal){this.modal.modal("hide")}},on_success:function(){l()},on_start:function(){var n=this;this.modal=$("#new-transaction-modal");this.modal.modal({keyboard:false,backdrop:"static",show:true});this.modal.find(".offline-transaction").hide();this.modal.find("#missing-private-key").hide();this.modal.find("#review-tx").hide();this.modal.find(".modal-header h3").html("Creating transaction");this.modal.find("#tx-sign-progress").hide();this.modal.find(".btn.btn-primary").prop("disabled",true);this.modal.find(".btn.btn-primary").text("Send Transaction");this.modal.find(".btn.btn-secondary").unbind().click(function(){if(n.modal){n.modal.modal("hide")}n.cancel()})},on_begin_signing:function(){$("#tx-sign-progress").show().find(".t").text(this.tx.ins.length)},on_sign_progress:function(n){$("#tx-sign-progress").find(".n").text(n)},on_finish_signing:function(){$("#tx-sign-progress").hide()}};f.addListener(b);if(d){f.ask_for_fee=function(q,p){var n=this;if(n.modal){n.modal.modal("hide")}var o=$("#ask-for-fee");o.modal({keyboard:false,backdrop:"static",show:true});o.find(".btn.btn-primary").unbind().click(function(){o.modal("hide");q()});o.find(".btn.btn-secondary").unbind().click(function(){o.modal("hide");p()});o.unbind().on("hidden",function(){if(n.modal){n.modal.modal("show")}})}}f.ask_to_send=function(){var n=this;try{n.modal.find(".modal-header h3").html(n.ready_to_send_header);n.modal.find("#missing-private-key").hide();n.modal.find("#review-tx").show();setReviewTransactionContent(n.modal,n.tx,n.type);setAdv(false);n.modal.center();var o=n.modal.find(".btn.btn-primary");MyWallet.setLoadingText("Checking Connectivity");$.ajax({type:"GET",url:root+"ping",data:{format:"plain",date:new Date().getTime()},success:function(){o.removeAttr("disabled");o.text("Send Transaction");o.unbind().click(function(){o.prop("disabled",true);if(n.modal){n.modal.modal("hide")}n.send()})},error:function(){n.modal.find(".modal-header h3").html("Created Offline Transaction.");o.removeAttr("disabled");o.text("Show Offline Instructions");o.unbind().click(function(){o.prop("disabled",true);n.modal.find("#missing-private-key").hide();n.modal.find("#review-tx").hide();n.modal.find(".offline-transaction").show();var q=n.tx.serialize();var r=Crypto.util.bytesToHex(q);n.modal.find('.offline-transaction textarea[name="data"]').val(r)});n.modal.center()}})}catch(p){n.error(p)}}}else{if(j=="quick"||j=="email"||j=="dice"||j=="sms"){var b={on_error:function(n){a.find(".send").show();if(this.p){this.p.hide()}},on_success:function(){try{a.find(".send").show();if(j!="dice"){l()}if(this.p){this.p.hide()}}catch(n){console.log(n)}},on_start:function(){this.p=a.find(".progress");a.find(".send").hide();this.p.show();this.p.children().css("width","10%")},on_begin_signing:function(){this.p.children().css("width","25%")},on_sign_progress:function(n){this.p.children().css("width",25+((100/this.tx.ins.length)*n)+"%")},on_finish_signing:function(){this.p.children().css("width","100%")}};f.addListener(b);if(j=="sms"){f.ask_to_send=function(){try{var n=this;MyWallet.securePost("send-via",{type:"sms",to:n.sms_data.number,priv:n.sms_data.miniKey,hash:Crypto.util.bytesToHex(n.tx.getHash().reverse())},function(){n.send()},function(p){n.error(p?p.responseText:null)})}catch(o){n.error(o)}}}else{if(j=="email"){f.ask_to_send=function(){var n=this;var o=$("#send-email-modal");try{MyWallet.securePost("wallet",{method:"get-info",format:"json"},function(q){try{o.modal({keyboard:true,backdrop:"static",show:true});var s=q.alias;if(s==null){s=q.email}if(s==null){s="Shared"}o.find(".amount").text(formatBTC(n.email_data.amount.toString()));o.find(".email").text(n.email_data.email);o.find(".frame").html('<iframe frameBorder="0" style="box-sizing:border-box;width:100%;height:100%" src="'+root+"email-template?from_name="+s+"&amount="+n.email_data.amount+'&priv=Preview&type=send-bitcoins-get"></iframe>');o.find(".btn.btn-secondary").unbind().click(function(){n.cancel();o.modal("hide")});o.find(".btn.btn-primary").unbind().click(function(){o.modal("hide");try{MyWallet.securePost("send-via",{type:"email",to:n.email_data.email,priv:n.email_data.priv,hash:Crypto.util.bytesToHex(n.tx.getHash().reverse())},function(u){n.send()},function(u){n.error(u?u.responseText:null)})}catch(t){n.error(t)}})}catch(r){o.modal("hide");n.error(r)}},function(q){o.modal("hide");n.error("Error Getting Account Data")})}catch(p){o.modal("hide");n.error(p)}}}}}}f.insufficient_funds=function(p,n,s,r){var o=this;if(o.modal){o.modal.modal("hide")}var q=$("#insufficient-funds");q.find(".amount-required").text(formatBTC(p));q.find(".amount-available").text(formatBTC(n));q.modal({keyboard:false,backdrop:"static",show:true});q.find(".btn.btn-primary").unbind().click(function(){q.modal("hide");s()});q.find(".btn.btn-secondary").unbind().click(function(){q.modal("hide");r()});q.unbind().on("hidden",function(){if(o.modal){o.modal.modal("show")}})};f.ask_for_private_key=function(p,o,q){var n=this;if(n.modal){n.modal.modal("hide")}showPrivateKeyModal(function(r){if(n.modal){n.modal.modal("show")}p(r)},function(r){if(n.modal){n.modal.modal("show")}o(r)},q)};f.type=j;if(MyWallet.getFeePolicy()==1){f.base_fee=BigInteger.valueOf(100000);f.fee=BigInteger.valueOf(100000)}else{if(MyWallet.getFeePolicy()==-1){f.base_fee=BigInteger.valueOf(10000);f.ask_for_fee=function(o,n){n()}}}MyWallet.getSecondPassword(function(){try{var o=a.find('select[name="from"]');var t=o.val();if(t==null||t=="any"){f.from_addresses=MyWallet.getActiveAddresses()}else{if(o.attr("multiple")=="multiple"){f.from_addresses=t}else{f.from_addresses=[t]}}var w=a.find('textarea[name="public-note"]').val();if(w!=null&&w.length>0){if(w.length>255){throw"Notes are restricted to 255 characters in length"}f.note=w}var s=$.trim(a.find('select[name="change"]').val());if(s.length>0){if(s=="new"){var x=MyWallet.generateNewKey();var q=x.getBitcoinAddress();f.change_address=q;f.generated_addresses.push(q.toString())}else{if(s!="any"){try{f.change_address=new Bitcoin.Address(s)}catch(v){throw"Invalid change address: "+v}}}}var n=precisionToSatoshiBN(a.find('input[name="fees"]').val());if(n.compareTo(BigInteger.ZERO)>0){f.fee=n}var p=a.find(".recipient");if(p.length==0){throw"A transaction must have at least one recipient"}var u=p.length;var r=function(){if(u==0){f.error("Nothing to send.");return}if(f.to_addresses.length<u){return}if(f.to_addresses.length>u){f.error("We seem to have more recipients than required. Unknown error");return}f.start()};p.each(function(){try{var z=$(this);var A=z.find('input[name="send-value"]');var L=z.find('input[name="send-to-address"]');var G=z.find('input[name="send-to-email"]');var B=z.find('input[name="send-to-sms"]');var I=0;try{I=precisionToSatoshiBN(A.val());if(I==null||I.compareTo(BigInteger.ZERO)<=0){throw"You must enter a value greater than zero"}}catch(E){console.log(E);if(A.data("optional")==true){--u;return true}else{throw"Invalid send amount"}}if(L.length>0){var C=$.trim(L.val()).replace(/[\u200B-\u200D\uFEFF]/g,"");if(C==null||C.length==0){throw"You must enter a bitcoin address for each recipient"}else{var H=resolveAddress(C);if(j=="shared"){if(!H){throw"Invalid Bitcoin Address"}MyWallet.setLoadingText("Creating Forwarding Address");MyWallet.securePost("forwarder",{action:"create-mix",address:H,shared:true,format:"json"},function(N){try{if(N.destination!=H){throw"Mismatch between requested and returned destination address"}if(N.fee_percent!=MyWallet.getMixerFee()){MyWallet.get_history();throw"The mixer fee may have changed"}f.to_addresses.push({address:new Bitcoin.Address(N.input_address),value:I});r()}catch(M){f.error(M)}},function(M){f.error(M?M.responseText:null)})}else{if(H){f.to_addresses.push({address:new Bitcoin.Address(H),value:I})}else{if(C.length<10){BlockchainAPI.resolve_firstbits(C,function(M){try{f.to_addresses.push({address:new Bitcoin.Address(M),value:I});r()}catch(N){f.error(N)}},function(){f.error("Invalid to address: "+C)});return false}else{f.error("Invalid to address: "+C)}}}}}else{if(B.length>0){var D=$.trim(B.val());if(D.charAt(0)=="0"){D=D.substring(1)}if(D.charAt(0)!="+"){D="+"+z.find('select[name="sms-country-code"]').val()+D}var F=generateNewMiniPrivateKey();var H=F.key.getBitcoinAddress().toString();MyWallet.setAddressTag(H,2);MyWallet.setAddressLabel(H,D+" (Sent Via SMS)");f.generated_addresses.push(H);f.to_addresses.push({address:new Bitcoin.Address(H),value:I});if(f.sms_data){throw"Cannot send to more than one SMS recipient at a time"}f.sms_data={number:D,miniKey:F.miniKey}}else{if(G.length>0){var K=$.trim(G.val());function y(O){var N=O.lastIndexOf("@");var M=O.lastIndexOf(".");return(N<M&&N>0&&O.indexOf("@@")==-1&&M>2&&(O.length-M)>2)}if(y(K)){var J=MyWallet.generateNewKey();var H=J.getBitcoinAddress().toString();MyWallet.setAddressTag(H,2);MyWallet.setAddressLabel(H,K+" (Sent Via Email)");f.generated_addresses.push(H);f.to_addresses.push({address:new Bitcoin.Address(H),value:I});if(f.email_data){throw"Cannot send to more than one email recipient at a time"}f.email_data={email:K,priv:B58.encode(J.priv),amount:I}}else{throw"Invalid Email Address"}}}}}catch(E){console.log(E);f.error(E)}});r()}catch(v){f.error(v)}},function(){f.error()})}catch(h){f.error(h)}return f}function signInput(i,c,b,m,k){k=k?k:SIGHASH_ALL;var a=m.simpleOutPubKeyHash();var d=new Bitcoin.Address(a).toString();var n=new Bitcoin.ECKey(b);var j;if(n.getBitcoinAddress().toString()==d.toString()){j=false}else{if(n.getBitcoinAddressCompressed().toString()==d.toString()){j=true}else{throw"Private key does not match bitcoin address "+d.toString()+" = "+n.getBitcoinAddress().toString()+" | "+n.getBitcoinAddressCompressed().toString()}}var h=i.hashTransactionForSignature(m,c,k);var g=n.sign(h);var f=Bitcoin.ECDSA.serializeSig(g.r,g.s);f.push(k);if(!IsCanonicalSignature(f)){throw"IsCanonicalSignature returned false"}var l;if(j){l=Bitcoin.Script.createInputScript(f,n.getPubCompressed())}else{l=Bitcoin.Script.createInputScript(f,n.getPub())}if(l==null){throw"Error creating input script"}return l}function formatAddresses(b,f,a){var g="";if(f.length==1){var c=f[0].toString();if(a&&MyWallet.addressExists(c)&&MyWallet.getAddressLabel(c)){g=MyWallet.getAddressLabel(c)}else{if(a&&MyWallet.getAddressBookLabel(c)){g=MyWallet.getAddressBookLabel(c)}else{g=c}}}else{g="Escrow (<i>";for(var d=0;d<f.length;++d){g+=f[d].toString()+", "}g=g.substring(0,g.length-2);g+="</i> - "+b+" Required)"}return g}function setReviewTransactionContent(r,u,a){$("#rtc-hash").html(Crypto.util.bytesToHex(u.getHash()));$("#rtc-version").html(u.version);$("#rtc-from").html("");$("#rtc-to").html("");var v=BigInteger.ZERO;var t=BigInteger.ZERO;var n=BigInteger.ZERO;var g="send ";var q=true;var c=BigInteger.ZERO;for(var o=0;o<u.ins.length;++o){var k=u.ins[o];t=t.add(k.outpoint.value);n=n.add(k.outpoint.value);var f=null;try{f=new Bitcoin.Address(k.script.simpleInPubKeyHash())}catch(s){f="Unable To Decode Address"}$("#rtc-from").append(f+' <font color="green">'+formatBTC(k.outpoint.value.toString())+" <br />")}var j=true;for(var o=0;o<u.outs.length;++o){var p=u.outs[o];var d=p.value.slice();d.reverse();var w=new BigInteger(d);var h=[];var l=1;try{l=p.script.extractAddresses(h)}catch(s){console.log(s);h.push("Unknown Address!")}$("#rtc-to").append(formatAddresses(l,h)+' <font color="green">'+formatBTC(w.toString())+" </font><br />");v=v.add(w);t=t.subtract(w);if(h.length>1){if(!j){g+=" and "}g+="<b>"+formatBTC(w.toString())+"</b> to "+formatAddresses(l,h,true);q=false;n=n.subtract(w)}else{if(h.length>0){var b=h[0].toString();if(!MyWallet.addressExists(b)||MyWallet.getAddressTag(b)==2){if(w.compareTo(BigInteger.ZERO)==0){continue}if(!j){g+=" and "}if(a&&a=="shared"){g+="<b>"+formatBTC(w.toString())+"</b> Shared"}else{g+="<b>"+formatBTC(w.toString())+"</b> to "+formatAddresses(1,[b],true)}q=false}else{n=n.subtract(w);c=c.add(w)}}}j=false}if(t.compareTo(BigInteger.valueOf(1).multiply(BigInteger.valueOf(satoshi)))>=0){alert("Warning fees are very high for this transaction. Please double check each output!")}if(q==true){g="move <b>"+formatBTC(v.toString())+"</b> between your own bitcoin addresses"}$("#rtc-basic-summary").html(g);$("#rtc-effect").html("-"+formatBTC(n.toString()));$("#rtc-fees").html(formatBTC(t.toString()));$("#rtc-value").html(formatBTC(v.toString()))}function initNewTx(){var a={generated_addresses:[],to_addresses:[],fee:BigInteger.ZERO,extra_private_keys:{},listeners:[],is_cancelled:false,ask_to_send_shared:false,base_fee:BigInteger.valueOf(10000),min_free_output_size:BigInteger.valueOf(1000000),allow_adjust:true,ready_to_send_header:"Transaction Ready to Send.",min_input_confirmations:0,min_input_size:BigInteger.ZERO,addListener:function(b){this.listeners.push(b)},invoke:function(b,f,g){for(var c in this.listeners){try{if(this.listeners[c][b]){this.listeners[c][b].call(this,f,g)}}catch(d){console.log(d)}}},start:function(){var b=this;try{b.invoke("on_start");BlockchainAPI.get_unspent(b.from_addresses,function(j){try{if(b.is_cancelled){throw"Transaction Cancelled"}if(j.unspent_outputs==null||j.unspent_outputs.length==0){throw"No Free Outputs To Spend"}b.unspent=[];for(var g=0;g<j.unspent_outputs.length;++g){var d;try{d=new Bitcoin.Script(Crypto.util.hexToBytes(j.unspent_outputs[g].script));if(d.getOutType()=="Strange"){throw"Strange Script"}}catch(h){MyWallet.makeNotice("error","misc-error","Error decoding script: "+h);continue}var f={script:d,value:BigInteger.fromByteArrayUnsigned(Crypto.util.hexToBytes(j.unspent_outputs[g].value_hex)),tx_output_n:j.unspent_outputs[g].tx_output_n,tx_hash:j.unspent_outputs[g].tx_hash,confirmations:j.unspent_outputs[g].confirmations};b.unspent.push(f)}b.makeTransaction()}catch(h){b.error(h)}},function(d){b.error(d)},b.min_input_confirmations)}catch(c){b.error(c)}},makeTransaction:function(){var n=this;try{if(n.is_cancelled){throw"Transaction Cancelled"}n.selected_outputs=[];var j=BigInteger.ZERO;for(var p=0;p<n.to_addresses.length;++p){j=j.add(n.to_addresses[p].value)}var r=false;for(var p=0;p<n.to_addresses.length;++p){var m=n.to_addresses[p];if(m.m!=null){r=true;break}}var d=BigInteger.ZERO;if(n.fee!=null){j=j.add(n.fee)}var v=0;var c=[];var l=false;var u=false;var y=n.unspent.slice(0);function k(z){var B=new Bitcoin.Address(z.script.simpleOutPubKeyHash()).toString();if(B==null){throw"Unable to decode output address from transaction hash "+z.tx_hash}var A=Crypto.util.bytesToBase64(Crypto.util.hexToBytes(z.tx_hash));var i=new Bitcoin.TransactionIn({outpoint:{hash:A,index:z.tx_output_n,value:z.value},script:z.script,sequence:4294967295});return{addr:B,input:i}}while(true){for(var p=0;p<y.length;++p){var q=y[p];if(!q){continue}try{var o=k(q);if(!u&&MyWallet.isWatchOnly(o.addr)){continue}if(n.from_addresses!=null&&$.inArray(o.addr,n.from_addresses)==-1){continue}if(q.value.compareTo(n.min_input_size)<0){continue}if(q.value.compareTo(j)==0||q.value.compareTo(j.add(n.min_free_output_size))>=0){n.selected_outputs=[o.input];y[p]=null;c=[o.addr];v=q.value.intValue()*q.confirmations;d=q.value;break}else{n.selected_outputs.push(o.input);y[p]=null;c.push(o.addr);v+=q.value.intValue()*q.confirmations;d=d.add(q.value);if(d.compareTo(j)==0||d.compareTo(j.add(n.min_free_output_size))>=0){break}}}catch(t){MyWallet.makeNotice("info","tx-error",t)}}if(d.compareTo(j)>=0){break}if(u){break}u=true}function h(){n.error("Insufficient funds. Value Needed "+formatBTC(j.toString())+". Available amount "+formatBTC(d.toString()))}var w=d.subtract(j);if(w.compareTo(BigInteger.ZERO)<0){if(n.to_addresses.length==1&&d.compareTo(BigInteger.ZERO)>0&&n.allow_adjust){n.insufficient_funds(j,d,function(){var i=n.to_addresses[0].value.add(w);if(i.compareTo(BigInteger.ZERO)>0&&i.compareTo(j)<=0){n.to_addresses[0].value=i;n.makeTransaction();return}else{h()}},function(){h()})}else{h()}return}if(n.selected_outputs.length==0){n.error("No Available Outputs To Spend.");return}var g=new Bitcoin.Transaction();for(var p=0;p<n.selected_outputs.length;p++){g.addInput(n.selected_outputs[p])}for(var p=0;p<n.to_addresses.length;++p){var m=n.to_addresses[p];if(m.m!=null){g.addOutputScript(Bitcoin.Script.createMultiSigOutputScript(m.m,m.pubkeys),m.value)}else{g.addOutput(m.address,m.value)}if(m.value.compareTo(n.min_free_output_size)<0){l=true}}var s=d.subtract(j);if(s.compareTo(BigInteger.ZERO)>0){if(n.change_address!=null){g.addOutput(n.change_address,s)}else{if(c.length>0){g.addOutput(new Bitcoin.Address(c[Math.floor(Math.random()*c.length)]),s)}else{g.addOutput(new Bitcoin.Address(MyWallet.getPreferredAddress()),s)}}if(s.compareTo(n.min_free_output_size)<0){l=true}}var b=g.serialize(g).length+(138*g.ins.length);v/=b;var f=Math.max(1,Math.ceil(parseFloat(b/1000)));var x=(!n.fee||n.fee.compareTo(n.base_fee)<0);if(x&&(l||f>1)){n.fee=n.base_fee.multiply(BigInteger.valueOf(f));n.makeTransaction()}else{if(x&&(v<77600000||r)){n.ask_for_fee(function(){n.fee=n.base_fee.multiply(BigInteger.valueOf(f));n.makeTransaction()},function(){n.tx=g;n.determinePrivateKeys(function(){n.signInputs()})})}else{n.tx=g;n.determinePrivateKeys(function(){n.signInputs()})}}}catch(t){this.error(t)}},ask_for_fee:function(c,b){c()},insufficient_funds:function(c,b,f,d){d()},determinePrivateKeys:function(k){var b=this;try{if(b.is_cancelled){throw"Transaction Cancelled"}var h={};for(var d in b.selected_outputs){var c=b.selected_outputs[d].script;if(c.priv_to_use==null){var g=c.simpleOutPubKeyHash();var f=new Bitcoin.Address(g).toString();if(h[f]){c.priv_to_use=h[f]}else{if(b.extra_private_keys[f]){c.priv_to_use=Bitcoin.Base58.decode(b.extra_private_keys[f])}else{if(MyWallet.addressExists(f)&&!MyWallet.isWatchOnly(f)){try{c.priv_to_use=MyWallet.decodePK(MyWallet.getPrivateKey(f))}catch(j){console.log(j)}}}}if(c.priv_to_use==null){b.ask_for_private_key(function(i){try{if(f==i.getBitcoinAddress().toString()||f==i.getBitcoinAddressCompressed().toString()){b.extra_private_keys[f]=Bitcoin.Base58.encode(i.priv);b.determinePrivateKeys(k)}else{throw"The private key you entered does not match the bitcoin address"}}catch(l){b.error(l)}},function(i){b.from_addresses=$.grep(b.from_addresses,function(l){return l!=f});b.makeTransaction()},f);return false}else{h[f]=c.priv_to_use}}}k()}catch(j){b.error(j)}},signWebWorker:function(n,m){var b=false;var k=function(i){if(!b){m(i);b=true}};try{var p=this;var h=0;var o=Math.min(3,p.tx.ins.length);var c=new SecureRandom();p.worker=[];for(var d=0;d<o;++d){p.worker[d]=new Worker(resource+"wallet/signer"+(min?".min.js":".js"));p.worker[d].addEventListener("message",function(q){var i=q.data;try{switch(i.cmd){case"on_sign":p.invoke("on_sign_progress",parseInt(i.outputN)+1);p.tx.ins[i.outputN].script=new Bitcoin.Script(i.script);++h;if(h==p.tx.ins.length){p.terminateWorkers();n()}break;case"on_message":console.log(i.message);break;case"on_error":throw i.e}}catch(q){p.terminateWorkers();k(q)}},false);p.worker[d].addEventListener("error",function(i){k(i)});p.worker[d].postMessage({cmd:"load_resource",path:resource+"wallet/bitcoinjs"+(min?".min.js":".js")});var f=new Array(32);c.nextBytes(f);p.worker[d].postMessage({cmd:"seed",seed:Crypto.util.bytesToHex(f)})}for(var g in p.selected_outputs){var l=p.selected_outputs[g].script;p.worker[g%o].postMessage({cmd:"sign_input",tx:p.tx,outputN:g,priv_to_use:l.priv_to_use,connected_script:l})}}catch(j){k(j)}},signNormal:function(g,f){var c=this;var b=0;var d=function(){setTimeout(function(){if(c.is_cancelled){f();return}try{c.invoke("on_sign_progress",b+1);var h=c.selected_outputs[b].script;var j=signInput(c.tx,b,h.priv_to_use,h);if(j){c.tx.ins[b].script=j;b++;if(b==c.tx.ins.length){g()}else{d()}}else{throw"Unknown error signing transaction"}}catch(i){f(i)}},1)};d()},signInputs:function(){var b=this;try{b.invoke("on_begin_signing");var d=function(){b.invoke("on_finish_signing");b.is_ready=true;b.ask_to_send()};MyWallet._seed();b.signWebWorker(d,function(f){console.log(f);b.signNormal(d,function(g){b.error(g)})})}catch(c){b.error(c)}},terminateWorkers:function(){if(this.worker){for(var b in this.worker){try{this.worker[b].terminate()}catch(c){}}}},cancel:function(){if(!this.has_pushed){this.terminateWorkers();this.error("Transaction Cancelled")}},send:function(){var b=this;if(b.is_cancelled){b.error("This transaction has already been cancelled");return}if(!b.is_ready){b.error("Transaction is not ready to send yet");return}b.invoke("on_before_send");if(b.generated_addresses.length>0){b.has_saved_addresses=true;MyWallet.backupWallet("update",function(){b.pushTx()},function(){b.error("Error Backing Up Wallet. Cannot Save Newly Generated Keys.")})}else{b.pushTx()}},pushTx:function(){var b=this;if(b.is_cancelled){return}b.has_pushed=true;BlockchainAPI.push_tx(b.tx,b.note,function(c){b.success(c)},function(c){b.error(c)})},ask_for_private_key:function(c,b){b("Cannot ask for private key without user interaction disabled")},ask_to_send:function(){this.send()},error:function(b){if(this.is_cancelled){return}this.is_cancelled=true;if(!this.has_pushed&&this.generated_addresses.length>0){for(var c in this.generated_addresses){MyWallet.deleteAddress(this.generated_addresses[c])}if(this.has_saved_addresses){MyWallet.backupWallet()}}this.invoke("on_error",b)},success:function(){this.invoke("on_success")}};a.addListener({on_error:function(b){console.log(b);if(b){MyWallet.makeNotice("error","tx-error",b)}},on_begin_signing:function(){this.start=new Date().getTime()},on_finish_signing:function(){console.log("Took "+(new Date().getTime()-this.start)+"ms")}});return a};