diff --git a/.gitmodules b/.gitmodules index 0931976031587fb56e7c1a0e3686211263906bf3..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,18 +0,0 @@ -[submodule "static/jquery"] - path = static/jquery - url = git://github.com/components/jquery.git -[submodule "static/jqueryui"] - path = static/jqueryui - url = git://github.com/components/jqueryui.git -[submodule "static/bootstrap"] - path = static/bootstrap - url = git://github.com/components/bootstrap.git -[submodule "static/chartjs"] - path = static/chartjs - url = git://github.com/nnnick/Chart.js.git -[submodule "static/typeahead"] - path = static/typeahead - url = https://github.com/twitter/typeahead.js -[submodule "static/hogan"] - path = static/hogan - url = https://github.com/twitter/hogan.js diff --git a/README.md b/README.md index b835c301817aa40e7c3cac4e89a41bb02b613ff1..bc7645edaedbb45dd675a162404bd93cacca0440 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,12 @@ A python implementation of [uCoin](https://github.com/c-geek/ucoin) API +## Requirements + +In order to use the API, you have to first install the required dependencies given below thanks to pip3: + * requests + * python-gnupg + ##Installation Here is a fast installation procedure (a bit dirty) we suggest to quickly use this API. diff --git a/config.json-dist b/config.json-dist deleted file mode 100644 index f43496f53c55850ce9b12dfbb6bab3a299cf6d5a..0000000000000000000000000000000000000000 --- a/config.json-dist +++ /dev/null @@ -1,6 +0,0 @@ -{ - "server": "localhost", - "port": 8081, - "auth": false, - "user": "" -} diff --git a/doc/history.png b/doc/history.png deleted file mode 100644 index 60b7c6517c77222b82c10c8d89899cd32a45c8cf..0000000000000000000000000000000000000000 Binary files a/doc/history.png and /dev/null differ diff --git a/doc/transfer.png b/doc/transfer.png deleted file mode 100644 index 2fb6f94db6712387d74a404bddd0cfedd17e22b1..0000000000000000000000000000000000000000 Binary files a/doc/transfer.png and /dev/null differ diff --git a/merkle.py b/merkle.py deleted file mode 100644 index dbddb2387cc0f6f1a39d046a8f4a9a048d853813..0000000000000000000000000000000000000000 --- a/merkle.py +++ /dev/null @@ -1,131 +0,0 @@ -import hashlib, re -from pprint import pprint - -class Merkle: - """ - class to create a Merkle Tree. - - Here is the example we want that it works: - - >>> tree = Merkle('abcde').process() - >>> tree.root() - '114B6E61CB5BB93D862CA3C1DFA8B99E313E66E9' - >>> tree.depth() - 3 - >>> tree.levels() - 4 - >>> tree.nodes() - 6 - >>> tree.level(0) - ['114B6E61CB5BB93D862CA3C1DFA8B99E313E66E9'] - >>> tree.level(1) - ['585DD1B0A3A55D9A36DE747EC37524D318E2EBEE', '58E6B3A414A1E090DFC6029ADD0F3555CCBA127F'] - >>> tree.level(2) - ['F4D9EEA3797499E52CC2561F722F935F10365E40', '734F7A56211B581395CB40129D307A0717538088', '58E6B3A414A1E090DFC6029ADD0F3555CCBA127F'] - """ - - def __init__(self, strings, hashfunc=hashlib.sha1): - """ctor enables to set a list of strings used to process merkle tree and set the hash function - - Arguments: - - `strings`: list of strings - - `hashfunc`: hash function - """ - - self.strings = strings - self.hashfunc = hashfunc - - self.leaves = [] - self.tree_depth = 0 - self.rows = [] - self.nodes_count = 0 - - for s in strings: self.feed(s) - - def feed(self, anydata): - """add a new string into leaves - - Arguments: - - `anydata`: new string - """ - - if anydata and re.match(r'^[\w\d]{40}$', anydata): - self.leaves.append(anydata.upper()) - else: - self.leaves.append(self.hashfunc(anydata.encode('ascii')).hexdigest().upper()) - - return self - - def depth(self): - """computes and returns the depth value""" - - if not self.tree_depth: - power = 0 - while 2**power < len(self.leaves): - power += 1 - self.tree_depth = power - - return self.tree_depth - - def levels(self): - """returns the number of levels""" - - return self.depth()+1 - - def nodes(self): - """returns the number of nodes""" - - self.process() - return self.nodes_count - - def process(self): - """computes the merkle tree thanks to the data fullfilled in leaves""" - - d = self.depth() - if not len(self.rows): - for i in range(d): self.rows.append([]) - self.rows.append(self.leaves) - for i in reversed(range(d)): - self.rows[i] = self.__get_nodes__(self.rows[i+1]) - self.nodes_count += len(self.rows[i]) - - return self - - def root(self): - """returns the root node of the tree""" - - return self.rows[0][0] - - def level(self, i): - """returns a level thanks to the level number passed in argument - - Arguments: - - `i`: level number - """ - - return self.rows[i] - - def __get_nodes__(self, leaves): - """Compute nodes for a specific level. This method is private and used in intern from process method. - - Arguments: - - `leaves`: set of nodes to process - """ - - class List(list): - """Wrapper to enable to define what ever index you want even if the size doesnot fit yet.""" - - def __setitem__(self, index, value): - if index >= len(self): - for _ in range(index-len(self)+1): - self.append(None) - super().__setitem__(index, value) - - l = len(leaves) - r = l % 2 - nodes = List() - for i in range(0, l-1, 2): - nodes[int(i/2)] = self.hashfunc((leaves[i] + leaves[i+1]).encode('ascii')).hexdigest().upper() - if r == 1: - nodes[int((l-r)/2)] = leaves[l-1] - return nodes diff --git a/static/bootstrap b/static/bootstrap deleted file mode 160000 index 9393bcef9f6585317aecca38cd4f4c885037f761..0000000000000000000000000000000000000000 --- a/static/bootstrap +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9393bcef9f6585317aecca38cd4f4c885037f761 diff --git a/static/chartjs b/static/chartjs deleted file mode 160000 index 8f025f33c08c66991a12f02f908bab156a963aef..0000000000000000000000000000000000000000 --- a/static/chartjs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8f025f33c08c66991a12f02f908bab156a963aef diff --git a/static/favicon.ico b/static/favicon.ico deleted file mode 100644 index 895fc96a76b68b4924f1c51d022e1b82fa0f461f..0000000000000000000000000000000000000000 Binary files a/static/favicon.ico and /dev/null differ diff --git a/static/google-code-prettify/run_prettify.js b/static/google-code-prettify/run_prettify.js deleted file mode 100644 index e3d9a9c298b7a1c2bea03993c65454fa89f64de1..0000000000000000000000000000000000000000 --- a/static/google-code-prettify/run_prettify.js +++ /dev/null @@ -1,34 +0,0 @@ -!function(){var r=null; -(function(){function X(e){function j(){try{J.doScroll("left")}catch(e){P(j,50);return}w("poll")}function w(j){if(!(j.type=="readystatechange"&&x.readyState!="complete")&&((j.type=="load"?n:x)[z](i+j.type,w,!1),!m&&(m=!0)))e.call(n,j.type||j)}var Y=x.addEventListener,m=!1,C=!0,t=Y?"addEventListener":"attachEvent",z=Y?"removeEventListener":"detachEvent",i=Y?"":"on";if(x.readyState=="complete")e.call(n,"lazy");else{if(x.createEventObject&&J.doScroll){try{C=!n.frameElement}catch(A){}C&&j()}x[t](i+"DOMContentLoaded", -w,!1);x[t](i+"readystatechange",w,!1);n[t](i+"load",w,!1)}}function Q(){S&&X(function(){var e=K.length;$(e?function(){for(var j=0;j<e;++j)(function(e){P(function(){n.exports[K[e]].apply(n,arguments)},0)})(j)}:void 0)})}for(var n=window,P=n.setTimeout,x=document,J=x.documentElement,L=x.head||x.getElementsByTagName("head")[0]||J,z="",A=x.getElementsByTagName("script"),m=A.length;--m>=0;){var M=A[m],T=M.src.match(/^[^#?]*\/run_prettify\.js(\?[^#]*)?(?:#.*)?$/);if(T){z=T[1]||"";M.parentNode.removeChild(M); -break}}var S=!0,D=[],N=[],K=[];z.replace(/[&?]([^&=]+)=([^&]+)/g,function(e,j,w){w=decodeURIComponent(w);j=decodeURIComponent(j);j=="autorun"?S=!/^[0fn]/i.test(w):j=="lang"?D.push(w):j=="skin"?N.push(w):j=="callback"&&K.push(w)});m=0;for(z=D.length;m<z;++m)(function(){var e=x.createElement("script");e.onload=e.onerror=e.onreadystatechange=function(){if(e&&(!e.readyState||/loaded|complete/.test(e.readyState)))e.onerror=e.onload=e.onreadystatechange=r,--R,R||P(Q,0),e.parentNode&&e.parentNode.removeChild(e), -e=r};e.type="text/javascript";e.src="https://google-code-prettify.googlecode.com/svn/loader/lang-"+encodeURIComponent(D[m])+".js";L.insertBefore(e,L.firstChild)})(D[m]);for(var R=D.length,A=[],m=0,z=N.length;m<z;++m)A.push("https://google-code-prettify.googlecode.com/svn/loader/skins/"+encodeURIComponent(N[m])+".css");A.push("https://google-code-prettify.googlecode.com/svn/loader/prettify.css");(function(e){function j(m){if(m!==w){var n=x.createElement("link");n.rel="stylesheet";n.type="text/css"; -if(m+1<w)n.error=n.onerror=function(){j(m+1)};n.href=e[m];L.appendChild(n)}}var w=e.length;j(0)})(A);var $=function(){window.PR_SHOULD_USE_CONTINUATION=!0;var e;(function(){function j(a){function d(f){var b=f.charCodeAt(0);if(b!==92)return b;var a=f.charAt(1);return(b=i[a])?b:"0"<=a&&a<="7"?parseInt(f.substring(1),8):a==="u"||a==="x"?parseInt(f.substring(2),16):f.charCodeAt(1)}function h(f){if(f<32)return(f<16?"\\x0":"\\x")+f.toString(16);f=String.fromCharCode(f);return f==="\\"||f==="-"||f==="]"|| -f==="^"?"\\"+f:f}function b(f){var b=f.substring(1,f.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),f=[],a=b[0]==="^",c=["["];a&&c.push("^");for(var a=a?1:0,g=b.length;a<g;++a){var k=b[a];if(/\\[bdsw]/i.test(k))c.push(k);else{var k=d(k),o;a+2<g&&"-"===b[a+1]?(o=d(b[a+2]),a+=2):o=k;f.push([k,o]);o<65||k>122||(o<65||k>90||f.push([Math.max(65,k)|32,Math.min(o,90)|32]),o<97||k>122||f.push([Math.max(97,k)&-33,Math.min(o,122)&-33]))}}f.sort(function(f, -a){return f[0]-a[0]||a[1]-f[1]});b=[];g=[];for(a=0;a<f.length;++a)k=f[a],k[0]<=g[1]+1?g[1]=Math.max(g[1],k[1]):b.push(g=k);for(a=0;a<b.length;++a)k=b[a],c.push(h(k[0])),k[1]>k[0]&&(k[1]+1>k[0]&&c.push("-"),c.push(h(k[1])));c.push("]");return c.join("")}function e(f){for(var a=f.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),c=a.length,d=[],g=0,k=0;g<c;++g){var o=a[g];o==="("?++k:"\\"===o.charAt(0)&&(o=+o.substring(1))&&(o<=k? -d[o]=-1:a[g]=h(o))}for(g=1;g<d.length;++g)-1===d[g]&&(d[g]=++j);for(k=g=0;g<c;++g)o=a[g],o==="("?(++k,d[k]||(a[g]="(?:")):"\\"===o.charAt(0)&&(o=+o.substring(1))&&o<=k&&(a[g]="\\"+d[o]);for(g=0;g<c;++g)"^"===a[g]&&"^"!==a[g+1]&&(a[g]="");if(f.ignoreCase&&F)for(g=0;g<c;++g)o=a[g],f=o.charAt(0),o.length>=2&&f==="["?a[g]=b(o):f!=="\\"&&(a[g]=o.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var j=0,F=!1,l=!1,I=0,c=a.length;I<c;++I){var p= -a[I];if(p.ignoreCase)l=!0;else if(/[a-z]/i.test(p.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){F=!0;l=!1;break}}for(var i={b:8,t:9,n:10,v:11,f:12,r:13},q=[],I=0,c=a.length;I<c;++I){p=a[I];if(p.global||p.multiline)throw Error(""+p);q.push("(?:"+e(p)+")")}return RegExp(q.join("|"),l?"gi":"g")}function m(a,d){function h(a){var c=a.nodeType;if(c==1){if(!b.test(a.className)){for(c=a.firstChild;c;c=c.nextSibling)h(c);c=a.nodeName.toLowerCase();if("br"===c||"li"===c)e[l]="\n",F[l<<1]=j++, -F[l++<<1|1]=a}}else if(c==3||c==4)c=a.nodeValue,c.length&&(c=d?c.replace(/\r\n?/g,"\n"):c.replace(/[\t\n\r ]+/g," "),e[l]=c,F[l<<1]=j,j+=c.length,F[l++<<1|1]=a)}var b=/(?:^|\s)nocode(?:\s|$)/,e=[],j=0,F=[],l=0;h(a);return{a:e.join("").replace(/\n$/,""),d:F}}function n(a,d,h,b){d&&(a={a:d,e:a},h(a),b.push.apply(b,a.g))}function x(a){for(var d=void 0,h=a.firstChild;h;h=h.nextSibling)var b=h.nodeType,d=b===1?d?a:h:b===3?S.test(h.nodeValue)?a:d:d;return d===a?void 0:d}function C(a,d){function h(a){for(var l= -a.e,j=[l,"pln"],c=0,p=a.a.match(e)||[],m={},q=0,f=p.length;q<f;++q){var B=p[q],y=m[B],u=void 0,g;if(typeof y==="string")g=!1;else{var k=b[B.charAt(0)];if(k)u=B.match(k[1]),y=k[0];else{for(g=0;g<i;++g)if(k=d[g],u=B.match(k[1])){y=k[0];break}u||(y="pln")}if((g=y.length>=5&&"lang-"===y.substring(0,5))&&!(u&&typeof u[1]==="string"))g=!1,y="src";g||(m[B]=y)}k=c;c+=B.length;if(g){g=u[1];var o=B.indexOf(g),H=o+g.length;u[2]&&(H=B.length-u[2].length,o=H-g.length);y=y.substring(5);n(l+k,B.substring(0,o),h, -j);n(l+k+o,g,A(y,g),j);n(l+k+H,B.substring(H),h,j)}else j.push(l+k,y)}a.g=j}var b={},e;(function(){for(var h=a.concat(d),l=[],i={},c=0,p=h.length;c<p;++c){var m=h[c],q=m[3];if(q)for(var f=q.length;--f>=0;)b[q.charAt(f)]=m;m=m[1];q=""+m;i.hasOwnProperty(q)||(l.push(m),i[q]=r)}l.push(/[\S\s]/);e=j(l)})();var i=d.length;return h}function t(a){var d=[],h=[];a.tripleQuotedStrings?d.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/, -r,"'\""]):a.multiLineStrings?d.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,r,"'\"`"]):d.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,r,"\"'"]);a.verbatimStrings&&h.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,r]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,r,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\n\r]*)/, -r,"#"]),h.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,r])):d.push(["com",/^#[^\n\r]*/,r,"#"]));a.cStyleComments&&(h.push(["com",/^\/\/[^\n\r]*/,r]),h.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,r]));if(b=a.regexLiterals){var e=(b=b>1?"":"\n\r")?".":"[\\S\\s]";h.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+ -("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+e+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+e+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&h.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&h.push(["kwd",RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),r]);d.push(["pln",/^\s+/,r," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");h.push(["lit",/^@[$_a-z][\w$@]*/i,r],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,r],["pln",/^[$_a-z][\w$@]*/i,r],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i, -r,"0123456789"],["pln",/^\\[\S\s]?/,r],["pun",RegExp(b),r]);return C(d,h)}function z(a,d,h){function b(a){var c=a.nodeType;if(c==1&&!j.test(a.className))if("br"===a.nodeName)e(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&h){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(l.createTextNode(d),a.nextSibling),e(a),c||a.parentNode.removeChild(a)}} -function e(a){function b(a,c){var d=c?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),h=a.nextSibling;f.appendChild(d);for(var e=h;e;e=h)h=e.nextSibling,f.appendChild(e)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var j=/(?:^|\s)nocode(?:\s|$)/,m=/\r\n?|\n/,l=a.ownerDocument,i=l.createElement("li");a.firstChild;)i.appendChild(a.firstChild);for(var c=[i],p=0;p<c.length;++p)b(c[p]);d===(d|0)&&c[0].setAttribute("value", -d);var n=l.createElement("ol");n.className="linenums";for(var d=Math.max(0,d-1|0)||0,p=0,q=c.length;p<q;++p)i=c[p],i.className="L"+(p+d)%10,i.firstChild||i.appendChild(l.createTextNode("\u00a0")),n.appendChild(i);a.appendChild(n)}function i(a,d){for(var h=d.length;--h>=0;){var b=d[h];U.hasOwnProperty(b)?V.console&&console.warn("cannot override language handler %s",b):U[b]=a}}function A(a,d){if(!a||!U.hasOwnProperty(a))a=/^\s*</.test(d)?"default-markup":"default-code";return U[a]}function D(a){var d= -a.h;try{var h=m(a.c,a.i),b=h.a;a.a=b;a.d=h.d;a.e=0;A(d,b)(a);var e=/\bMSIE\s(\d+)/.exec(navigator.userAgent),e=e&&+e[1]<=8,d=/\n/g,i=a.a,j=i.length,h=0,l=a.d,n=l.length,b=0,c=a.g,p=c.length,t=0;c[p]=j;var q,f;for(f=q=0;f<p;)c[f]!==c[f+2]?(c[q++]=c[f++],c[q++]=c[f++]):f+=2;p=q;for(f=q=0;f<p;){for(var x=c[f],y=c[f+1],u=f+2;u+2<=p&&c[u+1]===y;)u+=2;c[q++]=x;c[q++]=y;f=u}c.length=q;var g=a.c,k;if(g)k=g.style.display,g.style.display="none";try{for(;b<n;){var o=l[b+2]||j,H=c[t+2]||j,u=Math.min(o,H),E=l[b+ -1],W;if(E.nodeType!==1&&(W=i.substring(h,u))){e&&(W=W.replace(d,"\r"));E.nodeValue=W;var Z=E.ownerDocument,s=Z.createElement("span");s.className=c[t+1];var z=E.parentNode;z.replaceChild(s,E);s.appendChild(E);h<o&&(l[b+1]=E=Z.createTextNode(i.substring(u,o)),z.insertBefore(E,s.nextSibling))}h=u;h>=o&&(b+=2);h>=H&&(t+=2)}}finally{if(g)g.style.display=k}}catch(v){V.console&&console.log(v&&v.stack||v)}}var V=window,G=["break,continue,do,else,for,if,return,while"],O=[[G,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], -"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],J=[O,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],K=[O,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"], -L=[K,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],O=[O,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],M=[G,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], -N=[G,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],R=[G,"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"],G=[G,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],Q=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/, -S=/\S/,T=t({keywords:[J,L,O,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",M,N,G],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),U={};i(T,["default-code"]);i(C([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-", -/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);i(C([["pln",/^\s+/,r," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,r,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/], -["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);i(C([],[["atv",/^[\S\s]+/]]),["uq.val"]);i(t({keywords:J,hashComments:!0,cStyleComments:!0,types:Q}),["c","cc","cpp","cxx","cyc","m"]);i(t({keywords:"null,true,false"}),["json"]);i(t({keywords:L,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:Q}), -["cs"]);i(t({keywords:K,cStyleComments:!0}),["java"]);i(t({keywords:G,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);i(t({keywords:M,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);i(t({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);i(t({keywords:N, -hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);i(t({keywords:O,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);i(t({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);i(t({keywords:R,cStyleComments:!0,multilineStrings:!0}),["rc","rs","rust"]); -i(C([],[["str",/^[\S\s]+/]]),["regex"]);var X=V.PR={createSimpleLexer:C,registerLangHandler:i,sourceDecorator:t,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:function(a,d,e){var b=document.createElement("div");b.innerHTML="<pre>"+a+"</pre>";b=b.firstChild;e&&z(b,e,!0);D({h:d,j:e,c:b,i:1});return b.innerHTML}, -prettyPrint:e=e=function(a,d){function e(){for(var b=V.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;p<j.length&&c.now()<b;p++){for(var d=j[p],m=k,l=d;l=l.previousSibling;){var n=l.nodeType,s=(n===7||n===8)&&l.nodeValue;if(s?!/^\??prettify\b/.test(s):n!==3||/\S/.test(l.nodeValue))break;if(s){m={};s.replace(/\b(\w+)=([\w%+\-.:]+)/g,function(a,b,c){m[b]=c});break}}l=d.className;if((m!==k||f.test(l))&&!w.test(l)){n=!1;for(s=d.parentNode;s;s=s.parentNode)if(g.test(s.tagName)&&s.className&&f.test(s.className)){n= -!0;break}if(!n){d.className+=" prettyprinted";n=m.lang;if(!n){var n=l.match(q),A;if(!n&&(A=x(d))&&u.test(A.tagName))n=A.className.match(q);n&&(n=n[1])}if(y.test(d.tagName))s=1;else var s=d.currentStyle,v=i.defaultView,s=(s=s?s.whiteSpace:v&&v.getComputedStyle?v.getComputedStyle(d,r).getPropertyValue("white-space"):0)&&"pre"===s.substring(0,3);v=m.linenums;if(!(v=v==="true"||+v))v=(v=l.match(/\blinenums\b(?::(\d+))?/))?v[1]&&v[1].length?+v[1]:!0:!1;v&&z(d,v,s);t={h:n,c:d,j:v,i:s};D(t)}}}p<j.length? -P(e,250):"function"===typeof a&&a()}for(var b=d||document.body,i=b.ownerDocument||document,b=[b.getElementsByTagName("pre"),b.getElementsByTagName("code"),b.getElementsByTagName("xmp")],j=[],m=0;m<b.length;++m)for(var l=0,n=b[m].length;l<n;++l)j.push(b[m][l]);var b=r,c=Date;c.now||(c={now:function(){return+new Date}});var p=0,t,q=/\blang(?:uage)?-([\w.]+)(?!\S)/,f=/\bprettyprint\b/,w=/\bprettyprinted\b/,y=/pre|xmp/i,u=/^code$/i,g=/^(?:pre|code|xmp)$/i,k={};e()}};typeof define==="function"&&define.amd&& -define("google-code-prettify",[],function(){return X})})();return e}();R||P(Q,0)})();}() diff --git a/static/hogan b/static/hogan deleted file mode 160000 index 5450e5ab61be562c843985409b04316a96840066..0000000000000000000000000000000000000000 --- a/static/hogan +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5450e5ab61be562c843985409b04316a96840066 diff --git a/static/jquery b/static/jquery deleted file mode 160000 index eb3580559f01546764e92fc50304138250d688a3..0000000000000000000000000000000000000000 --- a/static/jquery +++ /dev/null @@ -1 +0,0 @@ -Subproject commit eb3580559f01546764e92fc50304138250d688a3 diff --git a/static/jqueryui b/static/jqueryui deleted file mode 160000 index 2e11ec45e1a2b3ab9a9334414f1a569abf1d2671..0000000000000000000000000000000000000000 --- a/static/jqueryui +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2e11ec45e1a2b3ab9a9334414f1a569abf1d2671 diff --git a/static/typeahead b/static/typeahead deleted file mode 160000 index 331cff944d00f1d8e98694fc6f73ab80455bd3be..0000000000000000000000000000000000000000 --- a/static/typeahead +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 331cff944d00f1d8e98694fc6f73ab80455bd3be diff --git a/static/wallets/slider.js b/static/wallets/slider.js deleted file mode 100644 index 16accc1c1aeb7f129212d2a7b4a0c2757a93563f..0000000000000000000000000000000000000000 --- a/static/wallets/slider.js +++ /dev/null @@ -1,164 +0,0 @@ -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU Affero General Public License -// version 3 as published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -// USA -// -// Authors: -// Caner Candan <caner@candan.fr>, http://caner.candan.fr -// Geraldine Starke <geraldine@starke.fr>, http://www.vegeclic.fr -// - -$(function() { - var sliders = $("#sliders .slider"); - var availableTotal = parseInt($('#available_total').val()); - - sliders.each(function() { - var s = $(this); - var coin_value = parseInt(s.parent().find('.coin_value').val()); - var max_value = parseInt(s.parent().find('.max_value').val()); - - s.empty().slider({ - value: 0, - min: 0, - max: max_value, - range: "max", - step: 1, - coin: coin_value, - animate: false, - - stop: function(event, ui) { - // Get current total - var total = 0; - sliders.not(this).each(function() { - total += $(this).slider('option', 'value') * $(this).slider('option', 'coin'); - }); - - var value = $(this).slider('option', 'value'); - - if ((total + (value*coin_value)) > (availableTotal)) { - value = parseInt((availableTotal-total)/coin_value); - } - - total += value * coin_value; - - $(this).slider('option', 'value', value); - $(this).siblings().find('.quantity').text(value); - $(this).siblings().find('.equal').text(value*coin_value); - $(this).siblings('.input_value').val(value); - - $('#sliders_total').text(total); - $('#remains').text(availableTotal-total); - }, - - slide: function(event, ui) { - // Get current total - var total = 0; - sliders.not(this).each(function() { - total += $(this).slider('option', 'value') * $(this).slider('option', 'coin'); - }); - - if ((total + (ui.value*coin_value)) > (availableTotal)) { - ui.value = parseInt((availableTotal-total)/coin_value); - } - - // Need to do this because apparently jQ UI - // does not update value until this event completes - total += ui.value * coin_value; - - // Update display to current value - $(this).siblings().find('.quantity').text(ui.value); - $(this).siblings().find('.equal').text(ui.value*coin_value); - $(this).siblings('.input_value').val(ui.value); - - $('#sliders_total').text(total); - $('#remains').text(availableTotal-total); - } - }); - }); - - var initialize = function() { - var total = 0; - sliders.each(function() { - $(this).slider('value', 0); - $(this).siblings().find('.quantity').text(0); - $(this).siblings().find('.equal').text(0); - $(this).siblings('.input_value').val(0); - }); - $('#sliders_total').text(0); - $('#remains').text(availableTotal); - }; - - var randomize = function() { - initialize(); - - var total = 0 - sliders.each(function() { - if (total >= availableTotal) { return; } - - var value = $(this).slider('option', 'value'); - var max = $(this).slider('option', 'max'); - var coin = $(this).slider('option', 'coin'); - - max = (availableTotal-total)/coin; - - var sol = (coin > 1) ? parseInt(Math.random()*max) : max; - total += sol*coin; - - $(this).slider('value', sol); - $(this).siblings().find('.quantity').text(sol); - $(this).siblings().find('.equal').text(sol*coin); - $(this).siblings('.input_value').val(sol); - }); - - $('#sliders_total').text(total); - $('#remains').text(availableTotal-total); - }; - - $('#init').click(initialize); - $('#random').click(randomize); - - randomize(); -}); - -function create_one_slider(choices, id, default_value, disabled) { - $('#' + id + '-slide').slider({ - range: 'max', - min: 0, - max: choices.length-1, - value: default_value, - disabled: disabled, - slide: function( event, ui ) { - var i = parseInt(ui.value); - var v = choices[i]; - $('#id_' + id)[0].selectedIndex = i; - $('#id_' + id).change(); - $('#' + id + '-slide-text').text( v[1] ); - } - }); - - var i = parseInt($('#' + id + '-slide').slider('value')); - var v = choices[i]; - $('#id_' + id)[0].selectedIndex = i; - $('#id_' + id).change(); - $('#' + id + '-slide-text').text( v[1] ); -} - -$(function() { - $('.slidebar-select').each(function() { - var s = $(this)[0]; - var options = []; - $(this).find('option').each(function() { options.push([$(this).val(), $(this).text()]); }); - create_one_slider(options, s.name, s.selectedIndex, $(this).hasClass('disabled')); - $(this).hide(); - }); -}); diff --git a/static/wallets/typeahead.css b/static/wallets/typeahead.css deleted file mode 100644 index 376e7caf2bf47afadb3e2977516bbf46fde8d8fb..0000000000000000000000000000000000000000 --- a/static/wallets/typeahead.css +++ /dev/null @@ -1,63 +0,0 @@ -.typeahead, -.tt-query, -.tt-hint { - width: 800px; - height: 30px; - padding: 8px 12px; - font-size: 24px; - line-height: 30px; - border: 2px solid #ccc; - -webkit-border-radius: 8px; - -moz-border-radius: 8px; - border-radius: 8px; - outline: none; -} - -.typeahead { - background-color: #fff; -} - -.typeahead:focus { - border: 2px solid #0097cf; -} - -.tt-query { - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.tt-hint { - color: #999 -} - -.tt-dropdown-menu { - width: 800px; - margin-top: 12px; - padding: 8px 0; - background-color: #fff; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - -webkit-border-radius: 8px; - -moz-border-radius: 8px; - border-radius: 8px; - -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2); - -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2); - box-shadow: 0 5px 10px rgba(0,0,0,.2); -} - -.tt-suggestion { - padding: 3px 20px; - font-size: 18px; - line-height: 24px; -} - -.tt-suggestion.tt-is-under-cursor { - color: #fff; - background-color: #0097cf; - -} - -.tt-suggestion p { - margin: 0; -} diff --git a/templates/_messages.html b/templates/_messages.html deleted file mode 100644 index beb5b2152e3468b26af76f0416b9782c81ac148a..0000000000000000000000000000000000000000 --- a/templates/_messages.html +++ /dev/null @@ -1,14 +0,0 @@ -{% with messages=get_flashed_messages(with_categories=true) %} - {% if messages %} - <div class="row"> - <div class="span12"> - {% for category, message in messages %} - <div class="alert alert-{% if category == 'error' %}danger{% else %}{{category}}{% endif %} fade in"> - <a class="close" title="Close" href="#" data-dismiss="alert">×</a> - <strong>{{category|title}}:</strong> {{message}} - </div> - {% endfor %} - </div><!-- end span --> - </div><!-- end row --> - {% endif %} -{% endwith %} diff --git a/templates/api/base.html b/templates/api/base.html deleted file mode 100644 index 8547f0c792f242a88ecb17a90a070245a3c32954..0000000000000000000000000000000000000000 --- a/templates/api/base.html +++ /dev/null @@ -1,82 +0,0 @@ -{% extends "base.html" %} - -{% block section_title %}API{% endblock %} - -{% block content %} - -<div class="row"> - <div class="col-lg-3"> - - <div class="panel panel-default"> - <div class="panel-heading">PKS</div> - <div class="list-group" style="background-color: #f7f5fa;"> - <a id="pks_add" href="{{ url_for('pks_add') }}" class="list-group-item"><i class="glyphicon glyphicon-minus"></i> Add</a> - <a id="pks_lookup" href="{{ url_for('pks_lookup') }}" class="list-group-item"><i class="glyphicon glyphicon-minus"></i> Lookup</a> - <a id="pks_all" href="{{ url_for('pks_all') }}" class="list-group-item"><i class="glyphicon glyphicon-minus"></i> All</a> - </div> - </div> - - <div class="panel panel-default"> - <div class="panel-heading">UCG</div> - <div class="list-group" style="background-color: #f7f5fa;"> - <a id="ucg_pubkey" href="{{ url_for('ucg_pubkey') }}" class="list-group-item"><i class="glyphicon glyphicon-minus"></i> Pubkey</a> - <a id="ucg_peering" href="{{ url_for('ucg_peering') }}" class="list-group-item"><i class="glyphicon glyphicon-minus"></i> Peering</a> - <a id="ucg_peering_keys" href="{{ url_for('ucg_peering_keys') }}" class="list-group-item"><i class="glyphicon glyphicon-minus"></i> Keys (peering)</a> - <a id="ucg_peering_peer" href="{{ url_for('ucg_peering_peer') }}" class="list-group-item"><i class="glyphicon glyphicon-minus"></i> Peer (peering)</a> - <a id="ucg_peering_peers" href="{{ url_for('ucg_peering_peers') }}" class="list-group-item"><i class="glyphicon glyphicon-minus"></i> Peers (peering)</a> - <a id="ucg_peering_peers_upstream" href="{{ url_for('ucg_peering_peers_upstream') }}" class="list-group-item"><i class="glyphicon glyphicon-minus"></i> Upstream (peering/peers)</a> - <a id="ucg_peering_peers_downstream" href="{{ url_for('ucg_peering_peers_downstream') }}" class="list-group-item"><i class="glyphicon glyphicon-minus"></i> Downstream (peering/peers)</a> - <a id="ucg_peering_forward" href="{{ url_for('ucg_peering_forward') }}" class="list-group-item"><i class="glyphicon glyphicon-minus"></i> Forward (peering)</a> - <a id="ucg_peering_status" href="{{ url_for('ucg_peering_status') }}" class="list-group-item"><i class="glyphicon glyphicon-minus"></i> Status (peering)</a> - <a id="ucg_tht" href="{{ url_for('ucg_tht') }}" class="list-group-item"><i class="glyphicon glyphicon-minus"></i> THT</a> - </div> - </div> - - <div class="panel panel-default"> - <div class="panel-heading">HDC</div> - <div class="list-group" style="background-color: #f7f5fa;"> - <a id="hdc_amendments_current" href="{{ url_for('hdc_amendments_current') }}" class="list-group-item"><i class="glyphicon glyphicon-minus"></i> Current (amendments)</a> - <a id="hdc_amendments_current_votes" href="{{ url_for('hdc_amendments_current_votes') }}" class="list-group-item"><i class="glyphicon glyphicon-minus"></i> Votes (amendments/current)</a> - <a id="hdc_amendments_votes" href="{{ url_for('hdc_amendments_votes') }}" class="list-group-item"><i class="glyphicon glyphicon-minus"></i> Votes (amendments)</a> - </div> - </div> - - </div> - <div class="col-lg-9"> - {% block sub_content %}{% endblock %} - </div> -</div> - -{% endblock %} - -{% block foot %} - <script src="{{ url_for('static', filename='google-code-prettify/run_prettify.js') }}"></script> - - <script type="text/javascript"> - $('body').ready(function () { - var urls = { - '{{ url_for('pks_add') }}': 'pks_add', - '{{ url_for('pks_lookup') }}': 'pks_lookup', - '{{ url_for('pks_all') }}': 'pks_all', - - '{{ url_for('ucg_pubkey') }}': 'ucg_pubkey', - '{{ url_for('ucg_peering') }}': 'ucg_peering', - '{{ url_for('ucg_peering_keys') }}': 'ucg_peering_keys', - '{{ url_for('ucg_peering_peer') }}': 'ucg_peering_peer', - '{{ url_for('ucg_peering_peers') }}': 'ucg_peering_peers', - '{{ url_for('ucg_peering_peers_upstream') }}': 'ucg_peering_peers_upstream', - '{{ url_for('ucg_peering_peers_downstream') }}': 'ucg_peering_peers_downstream', - '{{ url_for('ucg_peering_forward') }}': 'ucg_peering_forward', - '{{ url_for('ucg_peering_status') }}': 'ucg_peering_status', - '{{ url_for('ucg_tht') }}': 'ucg_tht', - - '{{ url_for('hdc_amendments_current') }}': 'hdc_amendments_current', - '{{ url_for('hdc_amendments_current_votes') }}': 'hdc_amendments_current_votes', - '{{ url_for('hdc_amendments_votes') }}': 'hdc_amendments_votes', - }; - - var matches = window.location.pathname.match(/^(\/[^?]*)/g); - $('#' + urls[matches[0]]).addClass('active'); - }); - </script> -{% endblock %} diff --git a/templates/api/index.html b/templates/api/index.html deleted file mode 100644 index 4d2e358fe86b5fcf8ede0366556337a37c9b9743..0000000000000000000000000000000000000000 --- a/templates/api/index.html +++ /dev/null @@ -1,9 +0,0 @@ -{% extends "api/base.html" %} - -{% block sub_content %} -<h1><span class="label label-default">API</span></h1> - -<div class="alert alert-info"> - On the left side, click on the link request you want to test. -</div> -{% endblock %} diff --git a/templates/api/result.html b/templates/api/result.html deleted file mode 100644 index 707049268594ddb044b68df1b5f1629fe42b0676..0000000000000000000000000000000000000000 --- a/templates/api/result.html +++ /dev/null @@ -1,7 +0,0 @@ -{% extends "api/base.html" %} - -{% block sub_content %} -<h1><span class="label label-default">Result</span></h1> - -<pre class="{{style}}">{{result}}</pre> -{% endblock %} diff --git a/templates/base.html b/templates/base.html deleted file mode 100644 index 721fc035851fcfff531a76df9c659af6b31f04e7..0000000000000000000000000000000000000000 --- a/templates/base.html +++ /dev/null @@ -1,63 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8"/> - <title>{% block page_title %}uCoin - {% block section_title %}{% endblock %}{% endblock %}</title> - <meta name="viewport" content="width=device-width, initial-scale=1.0"/> - <!-- Bootstrap --> - <link href="{{ url_for('static', filename='bootstrap/css/bootstrap.min.css') }}" rel="stylesheet" media="screen"/> - <link href="{{ url_for('static', filename='bootstrap/css/bootstrap-theme.min.css') }}" rel="stylesheet" media="screen"/> - <link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}"/> - <style>body {overflow-y: scroll;}</style> - - <script type="text/javascript"> - var $SCRIPT_ROOT = {{ request.script_root|tojson|safe }}; - </script> - - {% block head -%}{% endblock -%} - </head> - <body> - {% include "nav.html" %} - - {% block header %}{% endblock %} - - <div class="{% block content_class %}container{% endblock %}"> - - <div role="main"> - {% include "_messages.html" %} - {% block content %}{% endblock %} - </div> <!--/main --> - - {% include "footer.html" %} - - </div> <!--/.container --> - - <!-- JavaScript plugins (requires jQuery) --> - {#<script src="http://code.jquery.com/jquery.js"></script>#} - <script src="{{ url_for('static', filename='jquery/jquery.min.js') }}"></script> - <!-- Include all compiled plugins (below), or include individual files as needed --> - <script src="{{ url_for('static', filename='bootstrap/js/bootstrap.min.js') }}"></script> - - <script type="text/javascript"> - $('body').ready(function () { - var urlMenu = { - '/': 'wallets', - '{{ url_for('wallets') }}': 'wallets', - '{{ url_for('api') }}': 'api', - }; - - var matches = window.location.pathname.match(/^(\/[^\/]*)/g); - $('#' + (urlMenu[matches[0]] ? urlMenu[matches[0]] : urlMenu['/'])).addClass('active'); - }); - </script> - - <script type="text/javascript"> - $(function() { - $('.tooltip_link').tooltip(); - }); - </script> - - {% block foot %}{% endblock %} - - </body> -</html> diff --git a/templates/footer.html b/templates/footer.html deleted file mode 100644 index 4f95c25504dfee9c7b26730ea6845acc4f26b9e4..0000000000000000000000000000000000000000 --- a/templates/footer.html +++ /dev/null @@ -1,18 +0,0 @@ -<hr/> - -{% block footer %} - <footer class="footer"> - <div class="pull-right"> - {#<a class="tooltip_link" href="http://ask.vegeclic.fr" title="Questions - Réponses"><img src="{% static "ask.png" %}"/></a> - <a class="tooltip_link" href="#" title="+33 6 47 78 24 00" alt="+33 6 47 78 24 00"><img src="{% static "telephone.png" %}"/></a> - <a class="tooltip_link" href="http://twitter.com/Vegeclic" title="Suivez nous sur twitter"><img src="{% static "twitter.png" %}" /></a> - <a class="tooltip_link" href="https://www.facebook.com/Vegeclic" title="Aimez nous sur Facebook"><img src="{% static "facebook.png" %}" /></a>#} - </div> - <div class="copy"> - <a class="badge" href="https://github.com/canercandan/ucoin-python-api">ucoin-python-api - version 0.1</a> | Under <a href="http://www.gnu.org/licenses/agpl-3.0.html">GNU Affero General Public License</a> - </div> - <nav> - {% block footernav %}{% endblock %} - </nav> - </footer> -{% endblock footer %} diff --git a/templates/nav.html b/templates/nav.html deleted file mode 100644 index 8df7bfd1d63b8f5e10d775605f5ddfc5cea5406b..0000000000000000000000000000000000000000 --- a/templates/nav.html +++ /dev/null @@ -1,27 +0,0 @@ -<div class="navbar navbar-default navbar-static-top"> - <div class="container"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - <a href="#" class="navbar-brand"> - <span class="label label-default"><strong>uCoin</strong></span> - </a> - </div> - <div class="navbar-collapse collapse"> - <ul class="nav navbar-nav"> - <li id="wallets"><a href="{{ url_for('wallets') }}"><i class="glyphicon glyphicon-briefcase"></i> Wallets</a></li> - <li id="api"><a href="{{ url_for('api') }}"><i class="glyphicon glyphicon-cog"></i> API</a></li> - </ul> - <h4 class="navbar-text pull-right"> - {% if auth %} - <span class="label label-success">signed responses (secure mode)</span> - {% else %} - <span class="label label-warning">unsigned responses (fast mode)</span> - {% endif %} - </h4> - </div> - </div> -</div> diff --git a/templates/wallets/base.html b/templates/wallets/base.html deleted file mode 100644 index 44bed71852d186ab79e0398c2a2956cfb660467f..0000000000000000000000000000000000000000 --- a/templates/wallets/base.html +++ /dev/null @@ -1,60 +0,0 @@ -{% extends "base.html" %} - -{% block section_title %}Wallets{% endblock %} - -{% block head -%} - {% block subhead -%}{% endblock -%} -{% endblock -%} - -{% block content %} - -<div class="row"> - <div class="col-lg-3"> - <div class="list-group" style="background-color: #f7f5fa;"> - <a id="new" href="{{ url_for('new_wallet') }}" class="list-group-item"><i class="glyphicon glyphicon-plus-sign"></i> New</a> - <a id="list" href="{{ url_for('wallets') }}" class="list-group-item"><i class="glyphicon glyphicon-credit-card"></i> Wallets</a> - <a id="contacts" href="{{ url_for('wallet_contacts') }}" class="list-group-item"><i class="glyphicon glyphicon-user"></i> Contacts</a> - </div> - - {% if key -%} - <div class="panel panel-default"> - <div class="panel-heading">{{key.uids.0}}</div> - <div class="list-group" style="background-color: #f7f5fa;"> - <a id="history" href="{{ url_for('wallet_history', pgp_fingerprint=key.fingerprint) }}" class="list-group-item"><i class="glyphicon glyphicon-calendar"></i> History</a> - <a id="transfer" href="{{ url_for('wallet_transfer', pgp_fingerprint=key.fingerprint) }}" class="list-group-item"><i class="glyphicon glyphicon-transfer"></i> Transfer</a> - <a id="issuance" href="{{ url_for('wallet_issuance', pgp_fingerprint=key.fingerprint) }}" class="list-group-item"><i class="glyphicon glyphicon-cloud-download"></i> Issuance</a> - </div> - </div> - {% endif -%} - </div> - <div class="col-lg-9"> - {% block sub_content %}{% endblock %} - </div> -</div> - -{% endblock %} - -{% block foot %} - <script type="text/javascript"> - $('body').ready(function () { - var urls = { - '/': 'list', - '{{ url_for('new_wallet') }}': 'new', - '{{ url_for('wallets') }}': 'list', - '{{ url_for('wallet_contacts') }}': 'contacts', - - {% if key -%} - '{{ url_for('wallet_history', pgp_fingerprint=key.fingerprint) }}': 'history', - '{{ url_for('wallet_history', pgp_fingerprint=key.fingerprint, type=type) }}': 'history', - '{{ url_for('wallet_transfer', pgp_fingerprint=key.fingerprint) }}': 'transfer', - '{{ url_for('wallet_issuance', pgp_fingerprint=key.fingerprint) }}': 'issuance', - {% endif -%} - }; - - var matches = window.location.pathname.match(/^(\/[^?]*)/g); - $('#' + urls[matches[0]]).addClass('active'); - }); - </script> - - {% block subfoot %}{% endblock %} -{% endblock %} diff --git a/templates/wallets/contacts.html b/templates/wallets/contacts.html deleted file mode 100644 index 333eb98bb95a6dbd337b73ad81c6ebe1306c6d28..0000000000000000000000000000000000000000 --- a/templates/wallets/contacts.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends "wallets/base.html" %} - -{% block sub_content %} -<h1><span class="label label-default">Contacts</span></h1> - -<div class="list-group"> - {% for fp,k in settings.public_keys.items() %} - <a href="#" class="list-group-item {% if k.keyid == settings.keyid %}active{% endif %}"> - <h4 class="list-group-item-heading">{{k.uids.0}}</h4> - <p class="list-group-item-text">{{fp}}</p> - </a> - {% endfor %} -</div> - -{% endblock %} diff --git a/templates/wallets/detail.html b/templates/wallets/detail.html deleted file mode 100644 index 522db3c631ba954785c29d91eb798c3041b5c7cf..0000000000000000000000000000000000000000 --- a/templates/wallets/detail.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends "wallets/base.html" %} - -{% block sub_content %} -<h1><span class="label label-default">Wallet</span> <span class="label label-primary">{{key.uids.0|truncate(50)}}</span></h1> - -<div class="well"> - {{key}} -</div> - -{% endblock %} diff --git a/templates/wallets/history.html b/templates/wallets/history.html deleted file mode 100644 index 3ebafc0cdc8e83cb5e271d86790b9b991e7f1009..0000000000000000000000000000000000000000 --- a/templates/wallets/history.html +++ /dev/null @@ -1,88 +0,0 @@ -{% extends "wallets/base.html" %} - -{% block sub_content %} -<h1><span class="label label-default">History</span> <span class="label label-primary">{{key.uids.0|truncate(50)}}</span></h1> - -<br/> - -<div class="row"> - {% with coins=clist.1|map(attribute="amount")|list|join(" + ") -%} - <div class="col-md-3"> - <div class="alert alert-info tooltip_link" title="{{coins}}">Account balance: <span class="badge alert-default">{{clist.0}}</span></div> - </div> - <div class="col-md-2"> - {# <div class="alert alert-info">{{coins}}</div> #} - </div> - {% endwith %} - <div class="col-md-7"> - <ul class="nav nav-tabs pull-right"> - {% for name, color in [("all", "default"), ("transfer", "info"), ("issuance", "success"), ("fusion", "warning"), ("division", "danger")] -%} - <li {% if type == name %}class="active"{% endif %}> - <a href="{{ url_for('wallet_history', pgp_fingerprint=key.fingerprint, type=name) }}"> - <span class="label label-{{color}}">{{name|title}}</span> - </a> - </li> - {% endfor -%} - <li> - <a href="{{ url_for('wallet_history_refresh', pgp_fingerprint=key.fingerprint, type=type) }}"> - <i class="glyphicon glyphicon-refresh"></i> - </a> - </li> - </ul> - </div> -</div> - -{% for label,data in [("Received", recipient), ("Sent", sender)] -%} - <h3>{{label}} transactions</h3> - - <table class="table table-bordered table-hover"> - <thead> - <tr> - <th class="col-md-1 text-left">#</th> - <th class="col-md-2 text-center">{{"Sender" if label == "Received" else "Recipient" }}</th> - <th class="col-md-8 text-center">Comment</th> - <th class="col-md-1 text-center">Amount</th> - </tr> - </thead> - <tbody> - {% for number, tx in data.items()|reverse -%} - {# {% with tx=r.value.transaction -%} #} - {% if type == "all" or tx.type|lower == type|lower -%} - <tr class="row1 {% if tx.type == 'TRANSFER' %}active{% elif tx.type == 'ISSUANCE' %}success{% elif tx.type == 'FUSION' %}warning{% else %}danger{% endif %}"> - <td>{{tx.number}}</td> - - <td> - {% with reference=tx.sender if label == "Received" else tx.recipient -%} - {% with name=settings.public_keys[reference].uids.0 if settings.public_keys[reference] else "", keyid=reference[-8:] -%} - <a class="tooltip_link" title="{{name}} ({{keyid}})"> - {% if reference == key.fingerprint -%} - <span class="label label-default">me</span> - {% else -%} - <span class="label label-info">{{name|truncate(25) if name else keyid}}</span> - {% endif -%} - </a> - {% endwith -%} - {% endwith -%} - </td> - - <td> - <span class="label label-{% if tx.type == 'TRANSFER' %}info{% elif tx.type == 'ISSUANCE' %}success{% elif tx.type == 'FUSION' %}warning{% else %}danger{% endif %}">{{tx.type|title}}</span> - <a class="tooltip_link" title="{{tx.comment|trim}}">{{tx.comment|trim|truncate(150)}}</a> - </td> - - <td class="text-right"> - {% with coins=tx.coins|map(attribute="id")|map("compute_coin")|list -%} - <span class="badge alert-{{'success' if label == 'Received' else 'danger'}} tooltip_link" title="{{coins|join(' + ')}}"> - {{coins|sum}} - </span> - {% endwith -%} - </td> - </tr> - {% endif -%} - {# {% endwith -%} #} - {% endfor -%} - </tbody> - </table> -{% endfor -%} - -{% endblock %} diff --git a/templates/wallets/index.html b/templates/wallets/index.html deleted file mode 100644 index 0ac392164ee89f201048e846935e2f6088fdc33b..0000000000000000000000000000000000000000 --- a/templates/wallets/index.html +++ /dev/null @@ -1,19 +0,0 @@ -{% extends "wallets/base.html" %} - -{% block sub_content %} -<h1><span class="label label-default">Wallets</span></h1> - -<div class="alert alert-info"> - Select the wallet you want to use. -</div> - -<div class="list-group"> - {% for fp,k in settings.secret_keys.items() %} - <a href="{{ url_for('wallet_history', pgp_fingerprint=fp) }}" class="list-group-item {% if k.keyid == settings.keyid %}active{% endif %}"> - <h4 class="list-group-item-heading">{{k.uids.0}}</h4> - <p class="list-group-item-text">{{fp}}</p> - </a> - {% endfor %} -</div> - -{% endblock %} diff --git a/templates/wallets/issuance.html b/templates/wallets/issuance.html deleted file mode 100644 index c3511a5d35f67d15348ed30b4882d5d03399c379..0000000000000000000000000000000000000000 --- a/templates/wallets/issuance.html +++ /dev/null @@ -1,67 +0,0 @@ -{% extends "wallets/base.html" %} - -{% block subhead -%} - <link rel="stylesheet" href="{{ url_for('static', filename='jqueryui/themes/base/jquery.ui.all.css') }}" /> -{% endblock -%} - -{% block sub_content %} - <h1><span class="label label-default">Issuance</span> <span class="label label-primary">{{key.uids.0|truncate(50)}}</span></h1> - - <br/> - - <div class="form-group"> - <a class="btn btn-primary btn-lg btn-block tooltip_link" id="random" title="Click here in order to balance the set of coins values"><strong>Suggest</strong></a> - </div> - - <form role="form" method="post" action="{{ url_for('wallet_issuance', pgp_fingerprint=key.fingerprint) }}"> - - <div id="sliders"> - <input id="available_total" type="hidden" value="{{remainder}}" /> - - {% for coin, count in coins|reverse %} - <div class="form-group well"> - <div class="row"> - <div class="col-md-2"> - <span class="badge alert-info">{{coin}} coins</span> - </div> - <div class="col-md-8 slider"></div> - <div class="col-md-2 value_content"> - <span class="badge">{{coin}} x <span class="quantity">0</span> = <span class="equal">0</span></span> - </div> - <input class="input_value" id="coin_{{coin}}" name="coin_{{coin}}" type="hidden" value="0" /> - <input class="coin_value" type="hidden" value="{{coin}}" /> - <input class="max_value" type="hidden" value="{{count}}" /> - </div> - </div> - {% endfor %} - - </div> - - <div class="form-group well text-center"> - <h4> - <span class="label label-info">Total</span> - <span id="sliders_total" class="label label-info">0</span> - - <span class="label label-success">Remains</span> - <span class="label label-success">+ <span id="remains">{{remainder}}</span></span> - </h4> - </div> - - <div class="form-group"> - <button class="btn btn-lg btn-primary btn-block" type="submit">Ready ? Issue</button> - </div> - </form> -{% endblock %} - -{% block subfoot %} - <script src="{{ url_for('static', filename='jqueryui/ui/jquery.ui.core.js') }}"></script> - <script src="{{ url_for('static', filename='jqueryui/ui/jquery.ui.widget.js') }}"></script> - <script src="{{ url_for('static', filename='jqueryui/ui/jquery.ui.mouse.js') }}"></script> - <script src="{{ url_for('static', filename='jqueryui/ui/jquery.ui.slider.js') }}"></script> - <script src="{{ url_for('static', filename='wallets/slider.js') }}"></script> - - <style type="text/css"> - .ui-slider { height: 1.9em; } - .ui-slider .ui-slider-handle { height: 2.3em; } - </style> -{% endblock %} diff --git a/templates/wallets/new.html b/templates/wallets/new.html deleted file mode 100644 index e1c1845185ddd3f7c8273b652a459836989edf5c..0000000000000000000000000000000000000000 --- a/templates/wallets/new.html +++ /dev/null @@ -1,117 +0,0 @@ -{% extends "wallets/base.html" %} - -{% block sub_content %} -<h1><span class="label label-default">Create a new wallet</span></h1> - -<div class="row"> - <div class="col-md-6"> - <div class="panel panel-info"> - <div class="panel-heading"><h4>Type</h4></div> - <div class="panel-body"> - <div class="btn-group" data-toggle="buttons"> - {% for key, checked in [('rsa', True), ('dsa', False)] %} - <label class="btn btn-default btn-lg {% if checked %}active{% endif %}" for="type_{{key}}"> - <input checked="checked" id="type_{{key}}" name="type" type="radio" value="{{key}}"/> {{key|upper}} - </label> - {% endfor %} - </div> - </div> - </div> - </div> - <div class="col-md-6"> - <div class="panel panel-info"> - <div class="panel-heading"><h4>Length</h4></div> - <div class="panel-body"> - <div class="btn-group" data-toggle="buttons"> - {% for length, checked in [('1024', False), ('2048', True), ('4096', False)] %} - <label class="btn btn-default btn-lg {% if checked %}active{% endif %}" for="length_{{length}}"> - <input checked="checked" id="length_{{length}}" name="length" type="radio" value="{{length}}"/> {{length}} - </label> - {% endfor %} - </div> - </div> - </div> - </div> -</div> - -<div class="panel panel-info"> - <div class="panel-heading"><h4>Email</h4></div> - <div class="panel-body"> - <div class="form-group"> - <input name="email" id="email" class="form-control input-lg"/> - </div> - </div> -</div> - -<div class="panel panel-info"> - <div class="panel-heading"><h4>Realm</h4></div> - <div class="panel-body"> - <div class="form-group"> - <input name="realm" id="realm" class="form-control input-lg"/> - </div> - </div> -</div> - -<div class="alert alert-info lg"><h3 id="result">Click on "create" in order to create the new key.</h3></div> - -<div class="form-group"> - <button type="button" id="create" class="btn btn-lg btn-primary btn-block" data-loading-text="Loading… It takes a moment…" data-complete-text="Finished! Create a new one." data-error-text="Fix and create" data-toggle="button">Create</button> -</div> - -{% endblock %} - -{% block subfoot %} -<script type=text/javascript> - $(function() { - var type = $('input[name="type"]'); - var length = $('input[name="length"]'); - var email = $('input[name="email"]'); - var realm = $('input[name="realm"]'); - var create = $('#create'); - var result = $('#result'); - - var submit_form = function(e) { - $(this).button('loading'); - - if (!(email.val())) { - email.parent().addClass('has-error'); - create.button('error'); - email.focus().select(); - return false; - } - - if (!(realm.val())) { - realm.parent().addClass('has-error'); - create.button('error'); - realm.focus().select(); - return false; - } - - $.getJSON($SCRIPT_ROOT + "{{ url_for('new_wallet_create') }}", { - type: type.val(), - length: length.val(), - email: email.val(), - realm: realm.val(), - }, function(data) { - result.parent().removeClass('alert-info'); - result.parent().addClass('alert-success'); - result.text(data.result); - email.focus().select(); - create.button('complete'); - }); - - return false; - }; - - create.bind('click', submit_form); - - $('input[type=text]').bind('keydown', function(e) { - if (e.keyCode == 13) { - submit_form(e); - } - }); - - email.focus(); - }); -</script> -{% endblock %} diff --git a/templates/wallets/no_issuance.html b/templates/wallets/no_issuance.html deleted file mode 100644 index ba0778377a072377a9ae67cafec3b496a5ef4485..0000000000000000000000000000000000000000 --- a/templates/wallets/no_issuance.html +++ /dev/null @@ -1,12 +0,0 @@ -{% extends "wallets/base.html" %} - -{% block sub_content %} -<h1><span class="label label-default">Issue</span> <span class="label label-primary">{{key.uids.0|truncate(50)}}</span></h1> - -<br/> - -<div class="alert alert-warning"> - Currently, there is no dividend to issue. Try out this feature later on. -</div> - -{% endblock %} diff --git a/templates/wallets/transfer.html b/templates/wallets/transfer.html deleted file mode 100644 index fc59240dcf6d3aa49e69d113f720e93e89452048..0000000000000000000000000000000000000000 --- a/templates/wallets/transfer.html +++ /dev/null @@ -1,73 +0,0 @@ -{% extends "wallets/base.html" %} - -{% block subhead -%} - <link rel="stylesheet" href="{{ url_for('static', filename='wallets/typeahead.css') }}" /> -{% endblock -%} - -{% block sub_content %} -<h1><span class="label label-default">Transfer</span> <span class="label label-primary">{{key.uids.0|truncate(50)}}</span></h1> - -<br/> - -<div class="row"> - {% with coins=clist.1|map(attribute="amount")|list|join(" + ") -%} - <div class="col-md-3"> - <div class="alert alert-info tooltip_link" title="{{coins}}">Account balance: <span class="badge alert-default">{{clist.0}}</span></div> - </div> - <div class="col-md-9"> - {# <div class="alert alert-info">{{coins}}</div> #} - </div> - {% endwith -%} -</div> - -<form role="form" method="post" action="{{ url_for('wallet_transfer', pgp_fingerprint=key.fingerprint) }}"> - <div class="panel panel-success"> - <div class="panel-heading"><h4>Recipient</h4></div> - <div class="panel-body"> - <input class="typeahead form-control" type="text" placeholder="Your recipient" name="recipient"/> - </div> - <div class="panel-footer">Type the name, email or fingerprint of your recipient.</div> - </div> - - <div class="panel panel-success"> - <div class="panel-heading"><h4>Amount</h4></div> - <div class="panel-body"> - <input class="form-control" type="text" placeholder="0" name="amount" autocomplete="off"/> - </div> - <div class="panel-footer">Choose the amount you want to send.</div> - </div> - - <div class="panel panel-success"> - <div class="panel-heading"><h4>Message</h4></div> - <div class="panel-body"> - <textarea class="form-control" name="message" placeholder="Write here a comment" rows="5"></textarea> - </div> - </div> - - <div class="form-group"> - <button class="btn btn-lg btn-primary btn-block" type="submit">Transfer</button> - </div> -</form> -{% endblock %} - -{% block subfoot %} - <script src="{{ url_for('static', filename='typeahead/dist/typeahead.min.js') }}"></script> - <script src="{{ url_for('static', filename='hogan/web/builds/2.0.0/hogan-2.0.0.min.js') }}"></script> - - <script> - $(function() { - $('.typeahead').typeahead({ - name: 'recipient', - prefetch: '{{ url_for('wallet_public_keys') }}', - template: [ - {% raw -%} - '<p class="key-name">{{name}}</p>', - '<p class="key-fingerprint">{{fingerprint}}</p>', - '<hr/>' - {% endraw -%} - ].join(''), - engine: Hogan, - }); - }); - </script> -{% endblock %} diff --git a/ucoin.py b/ucoin.py deleted file mode 100755 index 2c7290ea3d9271f7421f29b53f2bebfa2ea65853..0000000000000000000000000000000000000000 --- a/ucoin.py +++ /dev/null @@ -1,760 +0,0 @@ -#!/usr/bin/env python3 -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# Authors: -# Caner Candan <caner@candan.fr>, http://caner.candan.fr -# - -from pprint import pprint -import ucoin, json, logging, argparse, sys, gnupg, hashlib, re, datetime as dt -from collections import OrderedDict -from merkle import Merkle - -logger = logging.getLogger("cli") - -# def action_transactions(): -# for tx in ucoin.hdc.transactions.All().get(): -# print(tx['hash']) - -def print_amendment(am): - print("""\ -Version\t\t\t%(version)s -Currency\t\t%(currency)s -Number\t\t\t%(number)s -GeneratedOn\t\t%(generated)s -UniversalDividend\t%(dividend)s -NextRequiredVotes\t%(nextVotes)s -PreviousHash\t\t%(previousHash)s -MembersRoot\t\t%(membersRoot)s -MembersCount\t\t%(membersCount)s\ - """ % am) - - if am['membersChanges']: - print('MembersChanges') - for x in am['membersChanges']: print(x) - - print("""\ -VotersRoot\t\t%(votersRoot)s -VotersCount\t\t%(votersCount)s\ - """ % am) - - if am['votersChanges']: - print('VotersChanges') - for x in am['votersChanges']: print(x) - -def current(): - logger.debug('current') - - print_amendment(ucoin.hdc.amendments.Current().get()) - -def contract(): - logger.debug('contract') - - print("""\ ------------------------------------ -- CONTRACT - ------------------------------------\ - """) - - for am in ucoin.hdc.amendments.List().get(): - print_amendment(am) - print('------------------------------------') - -def lookup(): - logger.debug('lookup') - - print(ucoin.pks.Lookup().get(search=ucoin.settings['search'], op='get')) - -def peering(): - logger.debug('peering') - - peer = ucoin.ucg.Peering().get() - - __dict = {} - for d in [peer, peer['contract'], peer['merkles']['pks/all'], peer['remote'],]: - __dict.update(d) - - print("""\ -Currency\t%(currency)s -Public key FPR\t%(key)s -Contract\t%(currentNumber)s-%(hash)s -Public keys\t%(leavesCount)d -Remote host\t%(host)s\ - """ % __dict) - - if __dict['ipv4']: print('Remote ipv4\t%(ipv4)s' % __dict) - if __dict['ipv6']: print('Remote ipv6\t%(ipv6)s' % __dict) - - print("""\ -Remote port\t%(port)d\ - """ % __dict) - -def pubkey(): - logger.debug('pubkey') - - print(ucoin.ucg.Pubkey().get()) - -def index(): - logger.debug('index') - - __dict = ucoin.hdc.amendments.Votes().get()['amendments'] - - i = 0 - while True: - if str(i) not in __dict: break - for k,v in __dict[str(i)].items(): - print('%d-%s:%d' % (i, k, v)) - i += 1 - -def issue(): - logger.debug('issue') - - try: - last_tx = ucoin.hdc.transactions.sender.Last(ucoin.settings['fingerprint']).get() - except ValueError: - last_tx = None - - try: - last_issuance = ucoin.hdc.transactions.sender.issuance.Last(ucoin.settings['fingerprint']).get() - except ValueError: - last_issuance = None - - __dict = {} - __dict.update(ucoin.settings) - __dict['version'] = 1 - __dict['number'] = 0 if not last_tx else last_tx['transaction']['number']+1 - __dict['previousHash'] = hashlib.sha1(("%(raw)s%(signature)s" % last_tx).encode('ascii')).hexdigest().upper() if last_tx else None - __dict['type'] = 'ISSUANCE' - - # pprint(__dict) - - tx = """\ -Version: %(version)d -Currency: %(currency)s -Sender: %(fingerprint)s -Number: %(number)d -""" % __dict - - if last_tx: tx += "PreviousHash: %(previousHash)s\n" % __dict - - tx += """\ -Recipient: %(fingerprint)s -Type: %(type)s -Coins: -""" % __dict - - def get_next_coin_number(coins): - number = 0 - for c in coins: - candidate = int(c['id'].split('-')[1]) - if candidate > number: number = candidate - return number+1 - - previous_idx = 0 if not last_issuance else get_next_coin_number(last_issuance['transaction']['coins']) - - for idx, coin in enumerate(ucoin.settings['coins']): - __dict['idx'] = idx+previous_idx - __dict['base'], __dict['power'] = [int(x) for x in coin.split(',')] - tx += '%(fingerprint)s-%(idx)d-%(base)d-%(power)d-A-%(amendment)d\n' % __dict - - tx += """\ -Comment: -%(message)s -""" % __dict - - tx = tx.replace("\n", "\r\n") - txs = ucoin.settings['gpg'].sign(tx, detach=True, keyid=ucoin.settings['user']) - - try: - ucoin.hdc.transactions.Process().post(transaction=tx, signature=txs) - except ValueError as e: - print(e) - else: - print('Posted issuance transaction') - -def transfer(): - logger.debug('transfer') - logger.debug('recipient: %s' % ucoin.settings['recipient']) - - if not ucoin.settings['coins']: ucoin.settings['coins'] = input() - - logger.debug('coins: %s' % ucoin.settings['coins']) - - try: - last_tx = ucoin.hdc.transactions.sender.Last(ucoin.settings['fingerprint']).get() - except ValueError: - last_tx = None - - __dict = {} - __dict.update(ucoin.settings) - __dict['version'] = 1 - __dict['number'] = 0 if not last_tx else last_tx['transaction']['number']+1 - __dict['previousHash'] = hashlib.sha1(("%(raw)s%(signature)s" % last_tx).encode('ascii')).hexdigest().upper() - __dict['type'] = 'TRANSFER' - - # pprint(__dict) - - tx = """\ -Version: %(version)d -Currency: %(currency)s -Sender: %(fingerprint)s -Number: %(number)d -""" % __dict - - if last_tx: tx += "PreviousHash: %(previousHash)s\n" % __dict - - tx += """\ -Recipient: %(recipient)s -Type: %(type)s -Coins: -""" % __dict - - for coin in ucoin.settings['coins'].split(','): - data = coin.split(':') - issuer = data[0] - for number in data[1:]: - __dict.update(ucoin.hdc.coins.View(issuer, int(number)).get()) - tx += '%(id)s, %(transaction)s\n' % __dict - - tx += """\ -Comment: -%(message)s -""" % __dict - - tx = tx.replace("\n", "\r\n") - txs = ucoin.settings['gpg'].sign(tx, detach=True, keyid=ucoin.settings['user']) - - try: - ucoin.hdc.transactions.Process().post(transaction=tx, signature=txs) - except ValueError as e: - print(e) - else: - print('Posted transfer transaction') - -def fusion(): - logger.debug('fusion') - - if not ucoin.settings['coins']: ucoin.settings['coins'] = input() - - logger.debug('coins: %s' % ucoin.settings['coins']) - - try: - last_tx = ucoin.hdc.transactions.sender.Last(ucoin.settings['fingerprint']).get() - except ValueError: - last_tx = None - - try: - last_issuance = ucoin.hdc.transactions.sender.issuance.Last(ucoin.settings['fingerprint']).get() - except ValueError: - last_issuance = None - - __dict = {} - __dict.update(ucoin.settings) - __dict['version'] = 1 - __dict['number'] = 0 if not last_tx else last_tx['transaction']['number']+1 - __dict['previousHash'] = hashlib.sha1(("%(raw)s%(signature)s" % last_tx).encode('ascii')).hexdigest().upper() - __dict['type'] = 'FUSION' - - # pprint(__dict) - - tx = """\ -Version: %(version)d -Currency: %(currency)s -Sender: %(fingerprint)s -Number: %(number)d -""" % __dict - - if last_tx: tx += "PreviousHash: %(previousHash)s\n" % __dict - - tx += """\ -Recipient: %(fingerprint)s -Type: %(type)s -Coins: -""" % __dict - - coins = [] - for coin in ucoin.settings['coins'].split(','): - data = coin.split(':') - issuer = data[0] - for number in data[1:]: - coins.append(ucoin.hdc.coins.View(issuer, int(number)).get()) - - __sum = 0 - for coin in coins: - base, power = coin['id'].split('-')[2:4] - __sum += int(base) * 10**int(power) - - m = re.match(r'^(\d)(0*)$', str(__sum)) - - if not m: - print('bad sum value %d' % __sum) - return - - def get_next_coin_number(coins): - number = 0 - for c in coins: - candidate = int(c['id'].split('-')[1]) - if candidate > number: number = candidate - return number+1 - - __dict['idx'] = 0 if not last_issuance else get_next_coin_number(last_issuance['transaction']['coins']) - - __dict['base'], __dict['power'] = int(m.groups()[0]), len(m.groups()[1]) - tx += '%(fingerprint)s-%(idx)d-%(base)d-%(power)d-F-%(number)d\n' % __dict - - for coin in coins: - __dict.update(coin) - tx += '%(id)s, %(transaction)s\n' % __dict - - tx += """\ -Comment: -%(message)s -""" % __dict - - tx = tx.replace("\n", "\r\n") - txs = ucoin.settings['gpg'].sign(tx, detach=True, keyid=ucoin.settings['user']) - - try: - ucoin.hdc.transactions.Process().post(transaction=tx, signature=txs) - except ValueError as e: - print(e) - else: - print('Posted fusion transaction') - -def host_add(): - logger.debug('host_add') - -def host_rm(): - logger.debug('host_rm') - -def host_list(): - logger.debug('host_list') - -def trust_add(): - logger.debug('trust_add') - -def trust_rm(): - logger.debug('trust_rm') - -def trust_list(): - logger.debug('trust_list') - -def tht(): - logger.debug('tht') - -def pub_tht(): - logger.debug('pub_tht') - -def forge_am(): - logger.debug('forge_am') - - def format_changes(s): - changes_str = (s or '')\ - .replace('"', '')\ - .replace('+', ';+')\ - .replace('-', ';-') - changes = [] - - for item in changes_str.split(';'): - if not item: continue - changes.append(item) - - return changes - - filter_plus = lambda x: x[0] == '+' - filter_minus = lambda x: x[0] == '-' - remove_sign = lambda x: x[1:] - - if not ucoin.settings['timestamp']: - ucoin.settings['timestamp'] = int(dt.datetime.timestamp(dt.datetime.today())) - - if not ucoin.settings['changes'] and ucoin.settings['stdin']: - ucoin.settings['changes'] = input() - - try: - current = ucoin.hdc.amendments.Current().get() - except ValueError: - current = None - - __dict = {} - __dict.update(ucoin.settings) - __dict['version'] = 1 - __dict['previousNumber'] = -1 if not current else current['number'] - __dict['number'] = __dict['previousNumber']+1 - __dict['previousHash'] = hashlib.sha1(("%(raw)s" % current).encode('ascii')).hexdigest().upper() if current else None - - am = """\ -Version: %(version)s -Currency: %(currency)s -Number: %(number)d -GeneratedOn: %(timestamp)d -""" % __dict - - if __dict['dividend']: am += "UniversalDividend: %(dividend)s\n" % __dict - if __dict['power10']: am += "CoinMinimalPower: %(power10)d\n" % __dict - - am += """\ -NextRequiredVotes: %(votes)d -""" % __dict - - if current: am += "PreviousHash: %(previousHash)s\n" % __dict - - if ucoin.settings['changes']: - ucoin.settings['changes'] = ucoin.settings['changes'].split(';') - - members_changes = format_changes(ucoin.settings['changes'][0]) if ucoin.settings['changes'] else [] - voters_changes = format_changes(ucoin.settings['changes'][1] if len(ucoin.settings['changes']) > 1 else '') if ucoin.settings['changes'] else [] - members_to_add = list(map(remove_sign, filter(filter_plus, members_changes))) - members_to_remove = list(map(remove_sign, filter(filter_minus, members_changes))) - voters_to_add = list(map(remove_sign, filter(filter_plus, voters_changes))) - voters_to_remove = list(map(remove_sign, filter(filter_minus, voters_changes))) - members_to_add = list(set(members_to_add) - set(members_to_remove)) - - if __dict['number']: - members_view = ucoin.hdc.amendments.view.Members('%(previousNumber)d-%(previousHash)s' % __dict).get() - else: - members_view = None - - members = [] - previous_members = [] - really_added_members = [] - really_removed_members = [] - - for fingerprint in members_view: - members.append(fingerprint['hash']) - previous_members.append(fingerprint['hash']) - - for fingerprint in members_to_add: - members.append(fingerprint) - - members = list(set(members)) - members = list(set(members) - set(members_to_remove)) - - members.sort() - - really_added_members = list(set(members) - set(previous_members)) - really_removed_members = list(set(members_to_remove) - set(members)) - really_removed_members = list(set(really_removed_members) & set(previous_members)) - - members_merkle = Merkle(members).process() - - members_changes = [] - for fpr in really_added_members: - members_changes.append('+' + fpr) - for fpr in really_removed_members: - members_changes.append('-' + fpr) - members_changes.sort() - __dict['members_count'] = len(members_merkle.leaves) - __dict['members_root'] = members_merkle.root() - - if __dict['number']: - voters_view = ucoin.hdc.amendments.view.Voters('%(previousNumber)d-%(previousHash)s' % __dict).get() - else: - voters_view = None - - voters = [] - previous_voters = [] - really_added_voters = [] - really_removed_voters = [] - - for fingerprint in voters_view: - voters.append(fingerprint['hash']) - previous_voters.append(fingerprint['hash']) - - for fingerprint in voters_to_add: - voters.append(fingerprint) - - voters = list(set(voters)) - voters = list(set(voters) - set(voters_to_remove)) - - voters.sort() - - really_added_voters = list(set(voters) - set(previous_voters)) - really_removed_voters = list(set(voters_to_remove) - set(voters)) - - voters_merkle = Merkle(voters).process() - - voters_changes = [] - for fpr in really_added_voters: - voters_changes.append('+' + fpr) - for fpr in really_removed_voters: - voters_changes.append('-' + fpr) - voters_changes.sort() - __dict['voters_count'] = len(voters_merkle.leaves) - __dict['voters_root'] = voters_merkle.root() - - am += """\ -MembersRoot: %(members_root)s -MembersCount: %(members_count)d -MembersChanges: -""" % __dict - - for m in members_changes: am += "%s\n" % m - - am += """\ -VotersRoot: %(voters_root)s -VotersCount: %(voters_count)d -VotersChanges: -""" % __dict - - for m in voters_changes: am += "%s\n" % m - - print(am) - -def clist(): - logger.debug('clist') - - if ucoin.settings['limit']: - logger.debug('limit: %d' % ucoin.settings['limit']) - - __list = ucoin.hdc.coins.List(ucoin.settings['fingerprint']).get() - - coins = [] - __sum = 0 - for c in __list['coins']: - for id in c['ids']: - n,b,p,t,i = id.split('-') - amount = int(b) * 10**int(p) - __dict = {'issuer': c['issuer'], 'number': int(n), 'base': int(b), 'power': int(p), 'type': t, 'type_number': int(i), 'amount': amount} - if not ucoin.settings['limit'] or ucoin.settings['limit'] >= amount: - coins.append(__dict) - __sum += amount - - print('Credit: %d\n-------------------\n' % __sum) - print('Value\tIssuer\t\t\t\t\t\t#\n') - for c in coins: - print('%(amount)d\t%(issuer)s\t%(number)d' % c) - -def cget(): - logger.debug('cget') - logger.debug('value: %s' % ucoin.settings['value']) - - __list = ucoin.hdc.coins.List(ucoin.settings['fingerprint']).get() - - coins = {} - for c in __list['coins']: - for id in c['ids']: - n,b,p,t,i = id.split('-') - amount = int(b) * 10**int(p) - coins[amount] = {'issuer': c['issuer'], 'number': int(n), 'base': int(b), 'power': int(p), 'type': t, 'type_number': int(i), 'amount': amount} - - issuers = {} - for v in ucoin.settings['value']: - if v in coins: - c = coins[v] - issuers[c['issuer']] = issuers.get(c['issuer']) or [] - issuers[c['issuer']].append(c) - else: - print('You do not have enough coins of value (%d)' % v) - return - - for i, issuer in enumerate(issuers): - if i > 0: print(',', end='') - print(issuer, end='') - for c in issuers[issuer]: - print(':%(number)d' % c, end='') - print() - -def send_pubkey(): - logger.debug('send_pubkey') - - data = None - - if ucoin.settings['user']: - pass - elif ucoin.settings['file']: - data = open(ucoin.settings['file']).read() - else: - data = "" - while True: - line = input() - if not line: break - data += line + "\n" - -def vote(): - logger.debug('vote') - - if ucoin.settings['file']: - am = open(ucoin.settings['file']).read() - else: - am = "" - while True: - line = input() - if not line: break - am += line + "\n" - - am = am.replace("\n", "\r\n") - ams = ucoin.settings['gpg'].sign(am, detach=True, keyid=ucoin.settings['user']) - - try: - r = ucoin.hdc.amendments.Votes().post(amendment=am, signature=ams) - except ValueError as e: - print(e) - else: - print('Posted vote for Amendment #%d' % r['amendment']['number']) - -if __name__ == '__main__': - common_options = {'formatter_class': argparse.ArgumentDefaultsHelpFormatter} - - parser = argparse.ArgumentParser(description='uCoin client.', **common_options) - - levels = OrderedDict([('debug', logging.DEBUG), - ('info', logging.INFO), - ('warning', logging.WARNING), - ('error', logging.ERROR), - ('quiet', logging.CRITICAL),]) - - parser.add_argument('--verbose', '-v', choices=[x for x in levels.keys()], default='error', help='set a verbosity level') - parser.add_argument('--levels', '-l', action='store_true', default=False, help='list all the verbosity levels') - parser.add_argument('--output', '-o', help='all the logging messages are redirected to the specified filename.') - parser.add_argument('--debug', '-d', action='store_const', const='debug', dest='verbose', help='Display all the messages.') - parser.add_argument('--info', '-i', action='store_const', const='info', dest='verbose', help='Display the info messages.') - parser.add_argument('--warning', '-w', action='store_const', const='warning', dest='verbose', help='Only display the warning and error messages.') - parser.add_argument('--error', '-e', action='store_const', const='error', dest='verbose', help='Only display the error messages') - parser.add_argument('--quiet', '-q', action='store_const', const='quiet', dest='verbose', help='Quiet level of verbosity only displaying the critical error messages.') - - parser.add_argument('--user', '-u', help='PGP key to use for signature') - parser.add_argument('--server', '-s', help='uCoin server to look data in', default='localhost') - parser.add_argument('--port', '-p', help='uCoin server port', type=int, default=8081) - - parser.add_argument('--config', '-c', help='set a config file', default='config.json') - - subparsers = parser.add_subparsers(help='sub-command help') - - subparsers.add_parser('current', help='Show current amendment of the contract', **common_options).set_defaults(func=current) - subparsers.add_parser('contract', help='List all amendments constituting the contract', **common_options).set_defaults(func=contract) - - sp = subparsers.add_parser('lookup', help='Search for a public key', **common_options) - sp.add_argument('search', help='A value for searching in PGP certificates database. May start with \'0x\' for direct search on PGP fingerprint.') - sp.set_defaults(func=lookup) - - subparsers.add_parser('peering', help='Show peering informations', **common_options).set_defaults(func=peering) - subparsers.add_parser('pubkey', help='Show pubkey of remote node', **common_options).set_defaults(func=pubkey) - subparsers.add_parser('index', help='List reiceved votes count for each amendment', **common_options).set_defaults(func=index) - - sp = subparsers.add_parser('issue', help='Issue new coins', **common_options) - sp.add_argument('amendment', type=int, help='amendment number') - sp.add_argument('coins', nargs='+', help='coins will respect this format [coin_value,number_of_zero_behind]') - sp.add_argument('--message', '-m', help='write a comment', default='') - sp.set_defaults(func=issue) - - sp = subparsers.add_parser('transfer', help='Transfers property of coins (coins a read from STDIN)', **common_options) - sp.add_argument('recipient', help='recipient address') - sp.add_argument('coins', nargs='?', help='coins to send [coin,...]. If no value has passed, it will be read from STDIN.') - sp.add_argument('--message', '-m', help='write a comment', default='') - sp.set_defaults(func=transfer) - - sp = subparsers.add_parser('fusion', help='Fusion coins to make a bigger coin (coins a read from STDIN)', **common_options) - sp.add_argument('coins', nargs='?', help='coins to fusion [coin,...]. If no value has passed, it will be read from STDIN.') - sp.add_argument('--message', '-m', help='write a comment', default='') - sp.set_defaults(func=fusion) - - sp = subparsers.add_parser('host-add', help='Add given key fingerprint to hosts managing transactions of key -u', **common_options) - sp.add_argument('key', help='key fingerprint') - sp.set_defaults(func=host_add) - - sp = subparsers.add_parser('host-rm', help='Same as \'host-add\', but remove host instead', **common_options) - sp.add_argument('key', help='key fingerprint') - sp.set_defaults(func=host_rm) - - subparsers.add_parser('host-list', help='Show the list of keys', **common_options).set_defaults(func=host_list) - - sp = subparsers.add_parser('trust-add', help='Add given key fingerprint to hosts key -u trust for receiving transactions', **common_options) - sp.add_argument('key', help='key fingerprint') - sp.set_defaults(func=trust_add) - - sp = subparsers.add_parser('trust-rm', help='Same as \'trust-add\', but remove host instead', **common_options) - sp.add_argument('key', help='key fingerprint') - sp.set_defaults(func=trust_rm) - - subparsers.add_parser('trust-list', help='Show the list of keys', **common_options).set_defaults(func=trust_list) - subparsers.add_parser('tht', help='Show THT entry resulting of host-* and trust-* commands', **common_options).set_defaults(func=tht) - subparsers.add_parser('pub-tht', help='Publish THT entry according to data returned by \'trust-list\' and \'host-list\'', **common_options).set_defaults(func=pub_tht) - - sp = subparsers.add_parser('forge-am', help='Forge an amendment, following currently promoted of given node.', **common_options) - sp.add_argument('changes', nargs='?', help='[members;voters] changes') - sp.add_argument('--dividend', '-d', type=int, help='Universal Dividend value') - sp.add_argument('--power10', '-m', type=int, help='Minimal coin 10 power') - sp.add_argument('--votes', '-n', type=int, help='Number of required votes', required=True) - sp.add_argument('--timestamp', '-t', type=int, help='Generation timestamp') - sp.add_argument('--stdin', '-C', action='store_true', default=False, help='forge-am will read community changes from STDIN') - sp.set_defaults(func=forge_am) - - sp = subparsers.add_parser('clist', help='List coins of given user. May be limited by upper amount.', **common_options) - sp.add_argument('limit', nargs='?', type=int, help='limit value') - sp.set_defaults(func=clist) - - sp = subparsers.add_parser('cget', help='Get coins for given values in user account.', **common_options) - sp.add_argument('value', nargs='+', type=int, help='value of the coin you want to select') - sp.set_defaults(func=cget) - - sp = subparsers.add_parser('send-pubkey', help='Send signed public key [file] to a uCoin server. If -u option is provided, [file] is ommited. If [file] is not provided, it is read from STDIN. Note: [file] may be forged using \'forge-*\' commands.', **common_options) - sp.add_argument('file', nargs='?', help='signed public key to send') - sp.set_defaults(func=send_pubkey) - - sp = subparsers.add_parser('vote', help='Signs given amendment [file] and sends it to a uCoin server. If [file] is not provided, it is read from STDIN.', **common_options) - sp.add_argument('file', nargs='?', help='amendment file') - sp.set_defaults(func=vote) - - args = parser.parse_args() - - if args.levels: - print("Here's the verbose levels available:") - for keys in levels.keys(): - print("\t", keys) - sys.exit() - - if (args.output): - logging.basicConfig( - level=logging.DEBUG, - format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', - filename=args.output, filemode='a' - ) - else: - logging.basicConfig( - level=levels.get(args.verbose, logging.NOTSET), - format='%(name)-12s: %(levelname)-8s %(message)s' - ) - - ucoin.settings.update(args.__dict__) - - try: - with open(args.config) as f: - ucoin.settings.update(json.load(f)) - except FileNotFoundError: - pass - - if ucoin.settings.get('user'): - logger.debug('selected keyid: %s' % ucoin.settings['user']) - ucoin.settings['gpg'] = gpg = gnupg.GPG(options=['-u %s' % ucoin.settings['user']]) - - keys = gpg.list_keys(True) - for idx, fp in enumerate(keys.fingerprints): - if fp[-8:] == ucoin.settings['user']: - ucoin.settings.update(keys[idx]) - break - else: - ucoin.settings['gpg'] = gpg = gnupg.GPG() - - ucoin.settings.update(ucoin.ucg.Peering().get()) - - logger.debug(args) - logger.debug(ucoin.settings) - - if 'func' not in args: - parser.print_help() - sys.exit() - - args.func() diff --git a/ucoin/__init__.py b/ucoin/__init__.py index 059af776adad5a44b20e66f1d8206cb150fbf7db..62ea64ab7eb9621e6623d25cbfb44325ae526778 100644 --- a/ucoin/__init__.py +++ b/ucoin/__init__.py @@ -182,4 +182,4 @@ class API: for leaf in root['leaves']: yield self.requests_get(path, leaf=leaf).json()['leaf'] -from . import pks, ucg, hdc +from . import pks, ucg, hdc, wrappers diff --git a/ucoin/wrappers/__init__.py b/ucoin/wrappers/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..d4a272760f74cc98cc7ea12e80c85028b5738dd7 --- /dev/null +++ b/ucoin/wrappers/__init__.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python3 +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# Authors: +# Caner Candan <caner@candan.fr>, http://caner.candan.fr +# + +import hashlib, logging +from .. import pks, ucg, hdc, settings + +logger = logging.getLogger("wrappers") + +class Wrapper: + def __call__(self): + pass + +class Transaction(Wrapper): + def __init__(self, type, pgp_fingerprint, message=''): + self.pgp_fingerprint = pgp_fingerprint + self.message = message + self.type = type + + def __call__(self): + try: + last_tx = hdc.transactions.sender.Last(self.pgp_fingerprint).get() + except ValueError: + last_tx = None + + context_data = {} + context_data.update(settings) + context_data['version'] = 1 + context_data['number'] = 0 if not last_tx else last_tx['transaction']['number']+1 + context_data['previousHash'] = hashlib.sha1(("%(raw)s%(signature)s" % last_tx).encode('ascii')).hexdigest().upper() if last_tx else None + context_data['message'] = self.message + context_data['type'] = self.type + context_data.update(self.get_context_data()) + + tx = """\ +Version: %(version)d +Currency: %(currency)s +Sender: %(fingerprint)s +Number: %(number)d +""" % context_data + + if last_tx: tx += "PreviousHash: %(previousHash)s\n" % context_data + + tx += self.get_message(context_data) + + tx += """\ +Comment: +%(message)s +""" % context_data + + tx = tx.replace("\n", "\r\n") + txs = settings['gpg'].sign(tx, detach=True) + + return self.process(tx, txs) + + def get_context_data(self): + return {} + + def get_message(self, context_data, tx=''): + return tx + + def process(self, tx, txs): + try: + hdc.transactions.Process().post(transaction=tx, signature=txs) + except ValueError as e: + print(e) + else: + return True + + return False + +class Transfer(Transaction): + def __init__(self, pgp_fingerprint, recipient, coins, message=''): + super().__init__('TRANSFER', pgp_fingerprint, message) + self.recipient = recipient + self.coins = coins + + def get_message(self, context_data, tx=''): + context_data['recipient'] = self.recipient + + tx += """\ +Recipient: %(recipient)s +Type: %(type)s +Coins: +""" % context_data + + for coin in self.coins.split(','): + data = coin.split(':') + issuer = data[0] + for number in data[1:]: + context_data.update(hdc.coins.View(issuer, int(number)).get()) + tx += '%(id)s, %(transaction)s\n' % context_data + + return tx + +class Issue(Transaction): + def __init__(self, pgp_fingerprint, amendment, coins, message=''): + super().__init__('ISSUANCE', pgp_fingerprint, message) + self.amendment = amendment + self.coins = coins + + def get_next_coin_number(self, coins): + number = 0 + for c in coins: + candidate = int(c['id'].split('-')[1]) + if candidate > number: number = candidate + return number+1 + + def get_message(self, context_data, tx=''): + context_data['amendment'] = self.amendment + + tx += """\ +Recipient: %(fingerprint)s +Type: %(type)s +Coins: +""" % context_data + + try: + last_issuance = hdc.transactions.sender.issuance.Last(self.pgp_fingerprint).get() + except ValueError: + last_issuance = None + + previous_idx = 0 if not last_issuance else self.get_next_coin_number(last_issuance['transaction']['coins']) + + for idx, coin in enumerate(self.coins): + context_data['idx'] = idx+previous_idx + context_data['base'], context_data['power'] = [int(x) for x in coin.split(',')] + tx += '%(fingerprint)s-%(idx)d-%(base)d-%(power)d-A-%(amendment)d\n' % context_data + + return tx + +class CoinsWrapper(Wrapper): + def __init__(self, pgp_fingerprint): + self.pgp_fingerprint = pgp_fingerprint + +class CoinsGet(CoinsWrapper): + def __init__(self, pgp_fingerprint, values): + super().__init__(pgp_fingerprint) + self.values = values + + def __call__(self): + __list = hdc.coins.List(self.pgp_fingerprint).get() + coins = {} + for c in __list['coins']: + for id in c['ids']: + n,b,p,t,i = id.split('-') + amount = int(b) * 10**int(p) + coins[amount] = {'issuer': c['issuer'], 'number': int(n), 'base': int(b), 'power': int(p), 'type': t, 'type_number': int(i), 'amount': amount} + + issuers = {} + for v in self.values: + if v in coins: + c = coins[v] + issuers[c['issuer']] = issuers.get(c['issuer']) or [] + issuers[c['issuer']].append(c) + else: + raise ValueError('You do not have enough coins of value (%d)' % v) + + res = '' + for i, issuer in enumerate(issuers): + if i > 0: res += ',' + res += issuer + for c in issuers[issuer]: + res += ':%(number)d' % c + + return res + +class CoinsList(CoinsWrapper): + def __call__(self): + __list = hdc.coins.List(self.pgp_fingerprint).get() + coins = [] + __sum = 0 + for c in __list['coins']: + for id in c['ids']: + n,b,p,t,i = id.split('-') + amount = int(b) * 10**int(p) + __dict = {'issuer': c['issuer'], 'number': int(n), 'base': int(b), 'power': int(p), 'type': t, 'type_number': int(i), 'amount': amount} + coins.append(__dict) + __sum += amount + return __sum, coins diff --git a/verify.py b/verify.py deleted file mode 100755 index f0f3349282292e65b3229b44bd750ecb681fcbd9..0000000000000000000000000000000000000000 --- a/verify.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/env python3 - -import requests, gnupg -from pprint import pprint - -def split_n_verify(response): - """ - Split the signed message thanks to the boundary value got in content-type header. - - returns a tuple with the status, the clear message and the signature. - - `response`: the response returns by requests.get() needed to access to headers and response content. - """ - - begin = '-----BEGIN PGP SIGNATURE-----' - end = '-----END PGP SIGNATURE-----' - boundary_pattern = 'boundary=' - - content_type = response.headers['content-type'] - boundary = content_type[content_type.index(boundary_pattern)+len(boundary_pattern):] - boundary = boundary[:boundary.index(';')].strip() - - data = [x.strip() for x in response.text.split('--%s' % boundary)] - - clear = data[1] - signed = data[2][data[2].index(begin):] - clearsigned = '-----BEGIN PGP SIGNED MESSAGE-----\nHash: SHA1\n\n%s\n%s' % (clear, signed) - - gpg = gnupg.GPG() - - return (bool(gpg.verify(clearsigned)), clear, signed) - -r = requests.get('http://mycurrency.candan.fr:8081/ucg/peering', headers={'Accept': 'multipart/signed'}) - -verified, clear, signed = split_n_verify(r) - -assert verified == True diff --git a/webclient.py b/webclient.py deleted file mode 100755 index a50c5246ae01c8b3e8def43a7376011d2237593c..0000000000000000000000000000000000000000 --- a/webclient.py +++ /dev/null @@ -1,784 +0,0 @@ -#!/usr/bin/env python3 -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# Authors: -# Caner Candan <caner@candan.fr>, http://caner.candan.fr -# - -from pprint import pprint -import\ - ucoin, json, logging, argparse, sys,\ - gnupg, hashlib, re, datetime as dt,\ - webbrowser, math -from collections import OrderedDict -from merkle import Merkle -from flask import\ - Flask, request, render_template,\ - jsonify, redirect, abort, url_for,\ - flash -from io import StringIO -from werkzeug.contrib.cache import SimpleCache - -logger = logging.getLogger("cli") -app = Flask(__name__) -app.secret_key = 'some_secret' -cache = SimpleCache() - -@app.template_filter('split') -def split_filter(s, sep=' '): - return s.split(sep) - -@app.template_filter('compute_coin') -def compute_coin_filter(coin): - fpr, number, base, power, origin, origin_number = coin.split('-') - return int(base)*10**int(power) - -def render_prettyprint(template_name, result): - s = StringIO() - pprint(result, s) - s = s.getvalue().replace('\\r', '').replace('\\n', '\n') - return render_template(template_name, result=s, style='prettyprint') - -def format_amendment(am): - res = """\ -Version\t\t\t%(version)s -Currency\t\t%(currency)s -Number\t\t\t%(number)s -GeneratedOn\t\t%(generated)s -UniversalDividend\t%(dividend)s -NextRequiredVotes\t%(nextVotes)s -PreviousHash\t\t%(previousHash)s -MembersRoot\t\t%(membersRoot)s -MembersCount\t\t%(membersCount)s -""" % am - - if am['membersChanges']: - res += 'MembersChanges\n' - for x in am['membersChanges']: res += '%s\n' % x - - res += """\ -VotersRoot\t\t%(votersRoot)s -VotersCount\t\t%(votersCount)s -""" % am - - if am['votersChanges']: - res += 'VotersChanges\n' - for x in am['votersChanges']: res += '%s\n' % x - - return res - -@app.route('/') -@app.route('/wallets') -def wallets(): - return render_template('wallets/index.html', settings=ucoin.settings) - -@app.route('/wallets/new') -def new_wallet(): - return render_template('wallets/new.html', settings=ucoin.settings) - -@app.route('/wallets/new/create') -def new_wallet_create(): - __input = 'Key-Type: %(type)s\nName-Email: %(email)s\nName-Real: %(realm)s\nKey-Length: %(length)s\n%%commit\n' % request.args - newkey = ucoin.settings['gpg'].gen_key(__input) - return jsonify(result="Your new key (%s) has been successfully created." % newkey.fingerprint) - -def get_sender_transactions(pgp_fingerprint): - k = 'sender_transactions_%s' % pgp_fingerprint - rv = cache.get(k) - if rv is None: - rv = list(ucoin.hdc.transactions.Sender(pgp_fingerprint).get()) - __dict = {} - for item in rv: __dict[item['value']['transaction']['number']] = item['value']['transaction'] - rv = __dict - cache.set(k, rv, timeout=5*60) - return rv - -def get_recipient_transactions(pgp_fingerprint): - k = 'recipient_transactions_%s' % pgp_fingerprint - rv = cache.get(k) - if rv is None: - rv = list(ucoin.hdc.transactions.Recipient(pgp_fingerprint).get()) - __dict = {} - for item in rv: __dict[item['value']['transaction']['number']] = item['value']['transaction'] - rv = __dict - cache.set(k, rv, timeout=5*60) - return rv - -def clist(pgp_fingerprint): - __list = ucoin.hdc.coins.List(pgp_fingerprint).get() - coins = [] - __sum = 0 - for c in __list['coins']: - for id in c['ids']: - n,b,p,t,i = id.split('-') - amount = int(b) * 10**int(p) - __dict = {'issuer': c['issuer'], 'number': int(n), 'base': int(b), 'power': int(p), 'type': t, 'type_number': int(i), 'amount': amount} - coins.append(__dict) - __sum += amount - return __sum, coins - -@app.route('/wallets/<pgp_fingerprint>/history') -@app.route('/wallets/<pgp_fingerprint>/history/<type>') -def wallet_history(pgp_fingerprint, type='all'): - sender = get_sender_transactions(pgp_fingerprint) - recipient = get_recipient_transactions(pgp_fingerprint) - - return render_template('wallets/history.html', - settings=ucoin.settings, - key=ucoin.settings['secret_keys'].get(pgp_fingerprint), - sender=sender, - recipient=recipient, - type=type, - clist=clist(pgp_fingerprint)) - -@app.route('/wallets/<pgp_fingerprint>/history/refresh') -@app.route('/wallets/<pgp_fingerprint>/history/refresh/<type>') -def wallet_history_refresh(pgp_fingerprint, type='all'): - k = 'sender_transactions_%s' % pgp_fingerprint; cache.set(k, None) - k = 'recipient_transactions_%s' % pgp_fingerprint; cache.set(k, None) - flash(u'History refreshed', 'info') - return redirect(url_for('wallet_history', pgp_fingerprint=pgp_fingerprint, type=type)) - -def cget(pgp_fingerprint, values): - __list = ucoin.hdc.coins.List(pgp_fingerprint).get() - coins = {} - for c in __list['coins']: - for id in c['ids']: - n,b,p,t,i = id.split('-') - amount = int(b) * 10**int(p) - coins[amount] = {'issuer': c['issuer'], 'number': int(n), 'base': int(b), 'power': int(p), 'type': t, 'type_number': int(i), 'amount': amount} - - issuers = {} - for v in values: - if v in coins: - c = coins[v] - issuers[c['issuer']] = issuers.get(c['issuer']) or [] - issuers[c['issuer']].append(c) - else: - raise ValueError('You do not have enough coins of value (%d)' % v) - - res = '' - for i, issuer in enumerate(issuers): - if i > 0: res += ',' - res += issuer - for c in issuers[issuer]: - res += ':%(number)d' % c - - return res - -def transfer(pgp_fingerprint, recipient, coins, message=''): - try: - last_tx = ucoin.hdc.transactions.sender.Last(pgp_fingerprint).get() - except ValueError: - last_tx = None - - __dict = {} - __dict.update(ucoin.settings) - __dict['version'] = 1 - __dict['number'] = 0 if not last_tx else last_tx['transaction']['number']+1 - __dict['previousHash'] = hashlib.sha1(("%(raw)s%(signature)s" % last_tx).encode('ascii')).hexdigest().upper() if last_tx else None - __dict['type'] = 'TRANSFER' - __dict['recipient'] = recipient - __dict['message'] = message - - tx = """\ -Version: %(version)d -Currency: %(currency)s -Sender: %(fingerprint)s -Number: %(number)d -""" % __dict - - if last_tx: tx += "PreviousHash: %(previousHash)s\n" % __dict - - tx += """\ -Recipient: %(recipient)s -Type: %(type)s -Coins: -""" % __dict - - for coin in coins.split(','): - data = coin.split(':') - issuer = data[0] - for number in data[1:]: - __dict.update(ucoin.hdc.coins.View(issuer, int(number)).get()) - tx += '%(id)s, %(transaction)s\n' % __dict - - tx += """\ -Comment: -%(message)s -""" % __dict - - tx = tx.replace("\n", "\r\n") - txs = ucoin.settings['gpg'].sign(tx, detach=True) - - try: - ucoin.hdc.transactions.Process().post(transaction=tx, signature=txs) - except ValueError as e: - print(e) - else: - return True - - return False - -@app.route('/wallets/<pgp_fingerprint>/transfer', methods=['GET', 'POST']) -def wallet_transfer(pgp_fingerprint): - balance, __clist = clist(pgp_fingerprint) - - if request.method == 'GET': - return render_template('wallets/transfer.html', - settings=ucoin.settings, - key=ucoin.settings['secret_keys'].get(pgp_fingerprint), - clist=(balance,__clist)) - - amounts = [x['amount'] for x in __clist] - amounts.sort() - amounts.reverse() - - recipient = request.form.get('recipient') - amount = request.form.get('amount', type=int) - message = request.form.get('message', '') - - if not recipient or not amount: - flash('recipient or amount field is missing.', 'error') - return redirect(url_for('wallet_transfer', pgp_fingerprint=pgp_fingerprint)) - - if amount > balance: - flash('amount is higher than available balance (%d > %d).' % (amount, balance), 'error') - return redirect(url_for('wallet_transfer', pgp_fingerprint=pgp_fingerprint)) - - coins = [] - total = 0 - for coin in amounts: - if total >= amount: break - if total+coin <= amount: - coins.append(coin) - total += coin - - if sum(coins) != amount: - flash('this amount cannot be reached with existing coins in your wallet.', 'error') - return redirect(url_for('wallet_transfer', pgp_fingerprint=pgp_fingerprint)) - - coins = cget(pgp_fingerprint, coins) - - if not transfer(pgp_fingerprint, recipient, coins, message): - flash(u'Transfer error', 'error') - else: - flash(u'Transfer succed', 'success') - - return redirect(url_for('wallet_transfer', pgp_fingerprint=pgp_fingerprint)) - -@app.route('/wallets/public_keys') -def wallet_public_keys(): - keys = ucoin.settings['public_keys'] - for k,v in keys.items(): - v['value'] = v['fingerprint'] - v['tokens'] = v['uids'] - v['name'] = v['uids'][0] - return json.dumps(list(keys.values())) - -@app.route('/wallets/contacts') -def wallet_contacts(): - return render_template('wallets/contacts.html', - settings=ucoin.settings) - -def issue(pgp_fingerprint, amendment, coins, message=''): - try: - last_tx = ucoin.hdc.transactions.sender.Last(pgp_fingerprint).get() - except ValueError: - last_tx = None - - try: - last_issuance = ucoin.hdc.transactions.sender.issuance.Last(pgp_fingerprint).get() - except ValueError: - last_issuance = None - - __dict = {} - __dict.update(ucoin.settings) - __dict['version'] = 1 - __dict['number'] = 0 if not last_tx else last_tx['transaction']['number']+1 - __dict['previousHash'] = hashlib.sha1(("%(raw)s%(signature)s" % last_tx).encode('ascii')).hexdigest().upper() if last_tx else None - __dict['type'] = 'ISSUANCE' - __dict['message'] = message - __dict['amendment'] = amendment - - tx = """\ -Version: %(version)d -Currency: %(currency)s -Sender: %(fingerprint)s -Number: %(number)d -""" % __dict - - if last_tx: tx += "PreviousHash: %(previousHash)s\n" % __dict - - tx += """\ -Recipient: %(fingerprint)s -Type: %(type)s -Coins: -""" % __dict - - def get_next_coin_number(coins): - number = 0 - for c in coins: - candidate = int(c['id'].split('-')[1]) - if candidate > number: number = candidate - return number+1 - - previous_idx = 0 if not last_issuance else get_next_coin_number(last_issuance['transaction']['coins']) - - for idx, coin in enumerate(coins): - __dict['idx'] = idx+previous_idx - __dict['base'], __dict['power'] = [int(x) for x in coin.split(',')] - tx += '%(fingerprint)s-%(idx)d-%(base)d-%(power)d-A-%(amendment)d\n' % __dict - - tx += """\ -Comment: -%(message)s -""" % __dict - - tx = tx.replace("\n", "\r\n") - txs = ucoin.settings['gpg'].sign(tx, detach=True) - - try: - ucoin.hdc.transactions.Process().post(transaction=tx, signature=txs) - except ValueError as e: - print(e) - else: - return True - - return False - -def compute_dividend_remainders(pgp_fingerprint): - remainders = {} - for am in ucoin.hdc.amendments.List().get(): - if not am['dividend']: continue - if not am['dividend']: continue - dividend_sum = 0 - for x in ucoin.hdc.transactions.sender.issuance.Dividend(pgp_fingerprint, am['number']).get(): - __sum = 0 - for coin in x['value']['transaction']['coins']: - base, power = coin['id'].split('-')[2:4] - __sum += int(base) * 10**int(power) - dividend_sum += __sum - - if am['dividend'] > dividend_sum: - remainders[int(am['number'])] = am['dividend'] - dividend_sum - return remainders - -@app.route('/wallets/<pgp_fingerprint>/issuance', methods=['GET', 'POST']) -def wallet_issuance(pgp_fingerprint): - k = 'remainders_%s' % pgp_fingerprint - remainders = cache.get(k) - if remainders is None: - remainders = compute_dividend_remainders(pgp_fingerprint) - cache.set(k, remainders, timeout=5*60) - - if not remainders: - return render_template('wallets/no_issuance.html', - settings=ucoin.settings, - key=ucoin.settings['secret_keys'].get(pgp_fingerprint)) - - # remainders = {1:10, 3:80} - - remainder = sum(remainders.values()) - max_remainder = max(remainders.values()) if remainders.values() else 0 - - # flash(remainders, 'info') - - def count_coins(coin): - count = 0 - for r in remainders.values(): - if r >= coin: count += int(r/coin) - return count - - coins = [] - for power in range(10): - for base in [1,2,5]: - coin = base*(10**power) - if coin > max_remainder: break - coins.append((coin,count_coins(coin))) - - if request.method == 'GET': - return render_template('wallets/issuance.html', - settings=ucoin.settings, - key=ucoin.settings['secret_keys'].get(pgp_fingerprint), - remainders=remainders, remainder=remainder, - max_remainder=max_remainder, coins=coins) - - quantities = [] - for coin, count in reversed(coins): - qte = request.form.get('coin_%d' % coin, type=int) - if qte: quantities.append((coin, qte)) - - # flash(str(quantities), 'info') - - issuances = {} - - for am in remainders: - # flash('%s %s' % (am, remainders[am]), 'info') - issuances[am] = issuance = [] - - for i in range(len(quantities)): - coin, qte = quantities[i] - if not qte: continue - - if coin <= remainders[am]: - new_qte = int(remainders[am]/coin) - if new_qte > qte: new_qte = qte - remainders[am] -= coin*new_qte - quantities[i] = (coin,qte-new_qte) - - # flash('%s x %s, remainder: %s' % (coin, new_qte, remainders[am])) - - for i in range(new_qte): - power = int(math.log10(coin)) - issuance.append('%d,%d' % (coin/10**power, power)) - - # flash(issuances) - - for am, coins in issuances.items(): - if not issue(pgp_fingerprint, am, coins): - flash(u'Issuance error', 'error') - break - - flash('The issuance was completed.', 'success') - cache.set(k, None) - - return redirect(url_for('wallet_issuance', pgp_fingerprint=pgp_fingerprint)) - -@app.route('/api') -def api(): - return render_template('api/index.html') - -@app.route('/api/pks/add', methods=['GET', 'POST']) -def pks_add(): - if request.method == 'GET': - return render_template('api/result.html', result='POST Method has to be used') - - keytext = request.form.get('keytext') - keysign = request.form.get('keysign') - - return render_template('api/result.html', result=ucoin.pks.Add().post(keytext=keytext, keysign=keysign)) - -@app.route('/api/pks/lookup') -def pks_lookup(): - search = request.args.get('search', '') - op = request.args.get('op', 'get') - - return render_template('api/result.html', result=ucoin.pks.Lookup().get(search=search, op=op)) - -@app.route('/api/pks/all') -def pks_all(): - return render_prettyprint('api/result.html', list(ucoin.pks.All().get())) - -@app.route('/api/ucg/pubkey') -def ucg_pubkey(): - return render_template('api/result.html', result=ucoin.ucg.Pubkey().get(), style='text') - -@app.route('/api/ucg/peering') -def ucg_peering(): - return render_prettyprint('api/result.html', ucoin.ucg.Peering().get()) - -@app.route('/api/ucg/peering/keys') -def ucg_peering_keys(): - return render_prettyprint('api/result.html', list(ucoin.ucg.peering.Keys().get())) - -@app.route('/api/ucg/peering/peer') -def ucg_peering_peer(): - return render_prettyprint('api/result.html', ucoin.ucg.peering.Peer().get()) - -@app.route('/api/ucg/peering/peers', methods=['GET', 'POST']) -def ucg_peering_peers(): - if request.method == 'GET': - return render_prettyprint('api/result.html', list(ucoin.ucg.peering.Peers().get())) - - entry = request.form.get('entry') - signature = request.form.get('signature') - - return render_prettyprint('api/result.html', ucoin.ucg.peering.Peers().post(entry=entry, signature=signature)) - -@app.route('/api/ucg/peering/peers/upstream') -def ucg_peering_peers_upstream(): - return render_prettyprint('api/result.html', ucoin.ucg.peering.peers.UpStream().get()) - -@app.route('/api/ucg/peering/peers/upstream/<pgp_fingerprint>') -def ucg_peering_peers_upstream_pgp(pgp_fingerprint): - return render_prettyprint('api/result.html', ucoin.ucg.peering.peers.UpStream(pgp_fingerprint).get()) - -@app.route('/api/ucg/peering/peers/downstream') -def ucg_peering_peers_downstream(): - return render_prettyprint('api/result.html', ucoin.ucg.peering.peers.DownStream().get()) - -@app.route('/api/ucg/peering/peers/downstream/<pgp_fingerprint>') -def ucg_peering_peers_downstream_pgp(pgp_fingerprint): - return render_prettyprint('api/result.html', ucoin.ucg.peering.peers.DownStream(pgp_fingerprint).get()) - -@app.route('/api/ucg/peering/forward', methods=['GET', 'POST']) -def ucg_peering_forward(): - if request.method == 'GET': - return render_template('api/result.html', result='POST Method has to be used') - - forward = request.form.get('forward') - signature = request.form.get('signature') - - return render_prettyprint('api/result.html', ucoin.ucg.peering.Forward().post(forward=forward, signature=signature)) - -@app.route('/api/ucg/peering/status', methods=['GET', 'POST']) -def ucg_peering_status(): - if request.method == 'GET': - return render_template('api/result.html', result='POST Method has to be used') - - status = request.form.get('status') - signature = request.form.get('signature') - - return render_prettyprint('api/result.html', ucoin.ucg.peering.Status().post(status=status, signature=signature)) - -@app.route('/api/ucg/tht', methods=['GET', 'POST',]) -def ucg_tht(): - if request.method == 'GET': - return render_prettyprint('api/result.html', list(ucoin.ucg.THT().get())) - - entry = request.form.get('entry') - signature = request.form.get('signature') - - return render_prettyprint('api/result.html', ucoin.ucg.THT().post(entry=entry, signature=signature)) - -@app.route('/api/ucg/tht/<pgp_fingerprint>') -def ucg_tht_pgp(pgp_fingerprint): - return render_prettyprint('api/result.html', ucoin.ucg.THT(pgp_fingerprint).get()) - -@app.route('/api/hdc/amendments/current') -def hdc_amendments_current(): - return render_prettyprint('api/result.html', ucoin.hdc.amendments.Current().get()) - -@app.route('/api/hdc/amendments/current/votes') -def hdc_amendments_current_votes(): - return render_prettyprint('api/result.html', list(ucoin.hdc.amendments.CurrentVotes().get())) - -@app.route('/api/hdc/amendments/promoted') -def hdc_amendments_promoted(): - return render_prettyprint('api/result.html', ucoin.hdc.amendments.Promoted().get()) - -@app.route('/api/hdc/amendments/promoted/<int:amendment_number>') -def hdc_amendments_promoted_am(amendment_number): - return render_prettyprint('api/result.html', ucoin.hdc.amendments.Promoted(amendment_number).get()) - -@app.route('/api/hdc/amendments/view/<amendment_id>/members') -def hdc_amendments_view_am_members(amendment_id): - return render_prettyprint('api/result.html', list(ucoin.hdc.amendments.views.Members(amendment_id).get())) - -@app.route('/api/hdc/amendments/view/<amendment_id>/self') -def hdc_amendments_view_am_self(amendment_id): - return render_prettyprint('api/result.html', ucoin.hdc.amendments.views.Self(amendment_id).get()) - -@app.route('/api/hdc/amendments/view/<amendment_id>/voters') -def hdc_amendments_view_am_voters(amendment_id): - return render_prettyprint('api/result.html', list(ucoin.hdc.amendments.views.Voters(amendment_id).get())) - -@app.route('/api/hdc/amendments/view/<amendment_id>/signatures') -def hdc_amendments_view_am_signatures(amendment_id): - return render_prettyprint('api/result.html', list(ucoin.hdc.amendments.views.Signatures(amendment_id).get())) - -@app.route('/api/hdc/amendments/votes', methods=['GET', 'POST']) -def hdc_amendments_votes(): - if request.method == 'GET': - return render_prettyprint('api/result.html', ucoin.hdc.amendments.Votes().get()) - - amendment = request.form.get('amendment') - signature = request.form.get('signature') - peer = request.form.get('peer') - - return render_prettyprint('api/result.html', ucoin.hdc.amendments.Votes().post(amendment=amendment, signature=signature, peer=peer)) - -@app.route('/api/hdc/amendments/votes/<amendment_id>') -def hdc_amendments_votes_am(amendment_id): - return render_prettyprint('api/result.html', list(ucoin.hdc.amendments.Votes(amendment_id).get())) - -@app.route('/api/hdc/coins/<pgp_fingerprint>/list') -def hdc_coins_pgp_list(pgp_fingerprint): - return render_prettyprint('api/result.html', ucoin.hdc.coins.List(pgp_fingerprint).get()) - -@app.route('/api/hdc/coins/<pgp_fingerprint>/view/<int:coin_number>') -def hdc_coins_pgp_view_coin(pgp_fingerprint): - return render_prettyprint('api/result.html', ucoin.hdc.coins.List(pgp_fingerprint, coin_number).get()) - -@app.route('/api/hdc/coins/<pgp_fingerprint>/view/<int:coin_number>/history') -def hdc_coins_pgp_view_coin_history(pgp_fingerprint): - return render_prettyprint('api/result.html', ucoin.hdc.coins.view.History(pgp_fingerprint, coin_number).get()) - -@app.route('/api/hdc/transactions/process', methods=['POST',]) -def hdc_transactions_process(): - transaction = request.form.get('transaction') - signature = request.form.get('signature') - - return render_prettyprint('api/result.html', ucoin.hdc.transactions.Process().post(transaction=transaction, signature=signature)) - -@app.route('/api/hdc/transactions/all') -def hdc_transactions_all(): - return render_prettyprint('api/result.html', list(ucoin.hdc.transactions.All().get())) - -@app.route('/api/hdc/transactions/keys') -def hdc_transactions_keys(): - return render_prettyprint('api/result.html', list(ucoin.hdc.transactions.Keys().get())) - -@app.route('/api/hdc/transactions/last') -def hdc_transactions_last(): - return render_prettyprint('api/result.html', ucoin.hdc.transactions.Last().get()) - -@app.route('/api/hdc/transactions/last/<int:count>') -def hdc_transactions_last_count(count): - return render_prettyprint('api/result.html', ucoin.hdc.transactions.Last(count).get()) - -@app.route('/api/hdc/transactions/sender/<pgp_fingerprint>') -def hdc_transactions_sender_pgp(pgp_fingerprint): - return render_prettyprint('api/result.html', list(ucoin.hdc.transactions.Sender(pgp_fingerprint).get())) - -@app.route('/api/hdc/transactions/sender/<pgp_fingerprint>/last') -def hdc_transactions_sender_pgp_last(pgp_fingerprint): - return render_prettyprint('api/result.html', ucoin.hdc.transactions.sender.Last(pgp_fingerprint).get()) - -@app.route('/api/hdc/transactions/sender/<pgp_fingerprint>/last/<int:count>') -def hdc_transactions_sender_pgp_last_count(pgp_fingerprint, count): - return render_prettyprint('api/result.html', ucoin.hdc.transactions.sender.Last(pgp_fingerprint, count).get()) - -@app.route('/api/hdc/transactions/sender/<pgp_fingerprint>/transfer') -def hdc_transactions_sender_pgp_transfer(pgp_fingerprint): - return render_prettyprint('api/result.html', list(ucoin.hdc.transactions.sender.Transfer(pgp_fingerprint).get())) - -@app.route('/api/hdc/transactions/sender/<pgp_fingerprint>/issuance') -def hdc_transactions_sender_pgp_issuance(pgp_fingerprint): - return render_prettyprint('api/result.html', list(ucoin.hdc.transactions.sender.Issuance(pgp_fingerprint).get())) - -@app.route('/api/hdc/transactions/sender/<pgp_fingerprint>/issuance/last') -def hdc_transactions_sender_pgp_issuance_last(pgp_fingerprint): - return render_prettyprint('api/result.html', ucoin.hdc.transactions.sender.issuance.Last(pgp_fingerprint).get()) - -@app.route('/api/hdc/transactions/sender/<pgp_fingerprint>/issuance/fusion') -def hdc_transactions_sender_pgp_issuance_fusion(pgp_fingerprint): - return render_prettyprint('api/result.html', list(ucoin.hdc.transactions.sender.issuance.Fusion(pgp_fingerprint).get())) - -@app.route('/api/hdc/transactions/sender/<pgp_fingerprint>/issuance/dividend') -def hdc_transactions_sender_pgp_issuance_dividend(pgp_fingerprint): - return render_prettyprint('api/result.html', list(ucoin.hdc.transactions.sender.issuance.Dividend(pgp_fingerprint).get())) - -@app.route('/api/hdc/transactions/sender/<pgp_fingerprint>/issuance/dividend/<int:amendment_number>') -def hdc_transactions_sender_pgp_issuance_dividend_am(pgp_fingerprint, amendment_number): - return render_prettyprint('api/result.html', list(ucoin.hdc.transactions.sender.issuance.Dividend(pgp_fingerprint, amendment_number).get())) - -@app.route('/api/hdc/transactions/recipient/<pgp_fingerprint>') -def hdc_transactions_recipient_pgp(pgp_fingerprint): - return render_prettyprint('api/result.html', list(ucoin.hdc.transactions.Recipient(pgp_fingerprint).get())) - -@app.route('/api/hdc/transactions/view/<transaction_id>') -def hdc_transactions_view_tx(transaction_id): - return render_prettyprint('api/result.html', ucoin.hdc.transactions.View(transaction_id).get()) - -if __name__ == '__main__': - common_options = {'formatter_class': argparse.ArgumentDefaultsHelpFormatter} - - parser = argparse.ArgumentParser(description='uCoin webclient.', **common_options) - - levels = OrderedDict([('debug', logging.DEBUG), - ('info', logging.INFO), - ('warning', logging.WARNING), - ('error', logging.ERROR), - ('quiet', logging.CRITICAL),]) - - parser.add_argument('--verbose', '-v', choices=[x for x in levels.keys()], default='error', help='set a verbosity level') - parser.add_argument('--levels', '-l', action='store_true', default=False, help='list all the verbosity levels') - parser.add_argument('--output', '-o', help='all the logging messages are redirected to the specified filename.') - parser.add_argument('--debug', '-d', action='store_const', const='debug', dest='verbose', help='Display all the messages.') - parser.add_argument('--info', '-i', action='store_const', const='info', dest='verbose', help='Display the info messages.') - parser.add_argument('--warning', '-w', action='store_const', const='warning', dest='verbose', help='Only display the warning and error messages.') - parser.add_argument('--error', '-e', action='store_const', const='error', dest='verbose', help='Only display the error messages') - parser.add_argument('--quiet', '-q', action='store_const', const='quiet', dest='verbose', help='Quiet level of verbosity only displaying the critical error messages.') - - parser.add_argument('--user', '-u', help='PGP key to use for signature') - parser.add_argument('--server', '-s', help='uCoin server to look data in', default='localhost') - parser.add_argument('--port', '-p', help='uCoin server port', type=int, default=8081) - - parser.add_argument('--config', '-c', help='set a config file', default='config.json') - - subparsers = parser.add_subparsers(help='sub-command help') - - def run(): - print('Running...') - app.secret_key = ucoin.settings['secret_key'] - if ucoin.settings['browser']: - webbrowser.open('http://localhost:5000/') - app.run(debug=True) - - sp = subparsers.add_parser('run', help='Run the webclient', **common_options) - sp.add_argument('--secret_key', '-s', help='Pass a secret key used by the server for sessions', default='some_secret') - sp.add_argument('--browser', '-b', action='store_true', help='Open it into your favorite browser', default=False) - sp.set_defaults(func=run) - - args = parser.parse_args() - - if args.levels: - print("Here's the verbose levels available:") - for keys in levels.keys(): - print("\t", keys) - sys.exit() - - if (args.output): - logging.basicConfig( - level=logging.DEBUG, - format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', - filename=args.output, filemode='a' - ) - else: - logging.basicConfig( - level=levels.get(args.verbose, logging.NOTSET), - format='%(name)-12s: %(levelname)-8s %(message)s' - ) - - ucoin.settings.update(args.__dict__) - - try: - with open(args.config) as f: - ucoin.settings.update(json.load(f)) - except FileNotFoundError: - pass - - if ucoin.settings.get('user'): - logger.debug('selected keyid: %s' % ucoin.settings['user']) - ucoin.settings['gpg'] = gpg = gnupg.GPG(options=['-u %s' % ucoin.settings['user']]) - - secret_keys = gpg.list_keys(True) - public_keys = gpg.list_keys() - - for idx, fp in enumerate(secret_keys.fingerprints): - if fp[-8:] == ucoin.settings['user']: - ucoin.settings.update(secret_keys[idx]) - break - - ucoin.settings['secret_keys'] = __secret_keys = {} - ucoin.settings['public_keys'] = __public_keys = {} - - for k in secret_keys: __secret_keys[k['fingerprint']] = k - for k in public_keys: __public_keys[k['fingerprint']] = k - else: - ucoin.settings['gpg'] = gpg = gnupg.GPG() - - ucoin.settings.update(ucoin.ucg.Peering().get()) - - logger.debug(args) - logger.debug(ucoin.settings) - - if 'func' not in args: - parser.print_help() - sys.exit() - - args.func()