-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.cpp
More file actions
executable file
·90 lines (90 loc) · 73.3 KB
/
main.cpp
File metadata and controls
executable file
·90 lines (90 loc) · 73.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#define C const
#define I i64
#define Q i32
#define ASC AbstractServerConnector
#define bM bindAndAddMethod
#define sVt serverVersion_t
#define JS JSON_STRING
#define E return
#define V virtual
#define U using namespace
#define u64 unsigned long long
#define i64 long long
#define u32 unsigned int
#define i32 int
#define u8 unsigned char
#include<cstdio>
#include<filesystem>
#include<iostream>
#include<thread>
#include<jsonrpccpp/server.h>
#include<jsonrpccpp/server/connectors/httpserver.h>
#include<ifaddrs.h>
#include<arpa/inet.h>
#include<stdint.h>
#include<algorithm>
#include<vector>
#include<unordered_map>
#include<cstring>
#include<getopt.h>
#define FOR_COL(it,arr)for(auto it=arr.begin(),end=arr.end(); it !=end;++it)
U std;U jsonrpc;U jsonrpc;U Json;
#include <stddef.h>
int ed25519_create_seed(u8*seed);void ed25519_create_keypair(u8*public_key,u8*private_key,C u8*seed);void ed25519_sign(u8*signature,C u8*message,size_t message_len,C u8*public_key,C u8*private_key);int ed25519_verify(C u8*signature,C u8*message,size_t message_len,C u8*public_key);void ed25519_add_scalar(u8*public_key,u8*private_key,C u8*scalar);void ed25519_key_exchange(u8*shared_secret,C u8*public_key,C u8*private_key);typedef Q fe[10];void fe_0(fe h);void fe_1(fe h);void fe_frombytes(fe h,C u8*s);void fe_tobytes(u8*s,C fe h);void fe_copy(fe h,C fe f);int fe_isnegative(C fe f);int fe_isnonzero(C fe f);void fe_cmov(fe f,C fe g,u32 b);void fe_cswap(fe f,fe g,u32 b);void fe_neg(fe h,C fe f);void fe_add(fe h,C fe f,C fe g);void fe_invert(fe out,C fe z);void fe_sq(fe h,C fe f);void fe_sq2(fe h,C fe f);void fe_mul(fe h,C fe f,C fe g);void fe_mul121666(fe h,fe f);void fe_pow22523(fe out,C fe z);void fe_sub(fe h,C fe f,C fe g);static u64 load_3(C u8*in){u64 result;result=(u64)in[0];result|=((u64)in[1])<<8;result|=((u64)in[2])<<16;E result;}static u64 load_4(C u8*in){u64 result;result=(u64)in[0];result|=((u64)in[1])<<8;result|=((u64)in[2])<<16;result|=((u64)in[3])<<24;E result;}void fe_0(fe h){h[0]=0;h[1]=0;h[2]=0;h[3]=0;h[4]=0;h[5]=0;h[6]=0;h[7]=0;h[8]=0;h[9]=0;}void fe_1(fe h){h[0]=1;h[1]=0;h[2]=0;h[3]=0;h[4]=0;h[5]=0;h[6]=0;h[7]=0;h[8]=0;h[9]=0;}void fe_add(fe h,C fe f,C fe g){Q f0=f[0];Q f1=f[1];Q f2=f[2];Q f3=f[3];Q f4=f[4];Q f5=f[5];Q f6=f[6];Q f7=f[7];Q f8=f[8];Q f9=f[9];Q g0=g[0];Q g1=g[1];Q g2=g[2];Q g3=g[3];Q g4=g[4];Q g5=g[5];Q g6=g[6];Q g7=g[7];Q g8=g[8];Q g9=g[9];Q h0=f0+g0;Q h1=f1+g1;Q h2=f2+g2;Q h3=f3+g3;Q h4=f4+g4;Q h5=f5+g5;Q h6=f6+g6;Q h7=f7+g7;Q h8=f8+g8;Q h9=f9+g9;h[0]=h0;h[1]=h1;h[2]=h2;h[3]=h3;h[4]=h4;h[5]=h5;h[6]=h6;h[7]=h7;h[8]=h8;h[9]=h9;}void fe_cmov(fe f,C fe g,u32 b){Q f0=f[0];Q f1=f[1];Q f2=f[2];Q f3=f[3];Q f4=f[4];Q f5=f[5];Q f6=f[6];Q f7=f[7];Q f8=f[8];Q f9=f[9];Q g0=g[0];Q g1=g[1];Q g2=g[2];Q g3=g[3];Q g4=g[4];Q g5=g[5];Q g6=g[6];Q g7=g[7];Q g8=g[8];Q g9=g[9];Q x0=f0^g0;Q x1=f1^g1;Q x2=f2^g2;Q x3=f3^g3;Q x4=f4^g4;Q x5=f5^g5;Q x6=f6^g6;Q x7=f7^g7;Q x8=f8^g8;Q x9=f9^g9;b=(u32)(-(int)b);x0 &=b;x1 &=b;x2 &=b;x3 &=b;x4 &=b;x5 &=b;x6 &=b;x7 &=b;x8 &=b;x9 &=b;f[0]=f0^x0;f[1]=f1^x1;f[2]=f2^x2;f[3]=f3^x3;f[4]=f4^x4;f[5]=f5^x5;f[6]=f6^x6;f[7]=f7^x7;f[8]=f8^x8;f[9]=f9^x9;}void fe_cswap(fe f,fe g,u32 b){Q f0=f[0];Q f1=f[1];Q f2=f[2];Q f3=f[3];Q f4=f[4];Q f5=f[5];Q f6=f[6];Q f7=f[7];Q f8=f[8];Q f9=f[9];Q g0=g[0];Q g1=g[1];Q g2=g[2];Q g3=g[3];Q g4=g[4];Q g5=g[5];Q g6=g[6];Q g7=g[7];Q g8=g[8];Q g9=g[9];Q x0=f0^g0;Q x1=f1^g1;Q x2=f2^g2;Q x3=f3^g3;Q x4=f4^g4;Q x5=f5^g5;Q x6=f6^g6;Q x7=f7^g7;Q x8=f8^g8;Q x9=f9^g9;b=(u32)(-(int)b);x0 &=b;x1 &=b;x2 &=b;x3 &=b;x4 &=b;x5 &=b;x6 &=b;x7 &=b;x8 &=b;x9 &=b;f[0]=f0^x0;f[1]=f1^x1;f[2]=f2^x2;f[3]=f3^x3;f[4]=f4^x4;f[5]=f5^x5;f[6]=f6^x6;f[7]=f7^x7;f[8]=f8^x8;f[9]=f9^x9;g[0]=g0^x0;g[1]=g1^x1;g[2]=g2^x2;g[3]=g3^x3;g[4]=g4^x4;g[5]=g5^x5;g[6]=g6^x6;g[7]=g7^x7;g[8]=g8^x8;g[9]=g9^x9;}void fe_copy(fe h,C fe f){Q f0=f[0];Q f1=f[1];Q f2=f[2];Q f3=f[3];Q f4=f[4];Q f5=f[5];Q f6=f[6];Q f7=f[7];Q f8=f[8];Q f9=f[9];h[0]=f0;h[1]=f1;h[2]=f2;h[3]=f3;h[4]=f4;h[5]=f5;h[6]=f6;h[7]=f7;h[8]=f8;h[9]=f9;}void fe_frombytes(fe h,C u8*s){I h0=load_4(s);I h1=load_3(s+4)<<6;I h2=load_3(s+7)<<5;I h3=load_3(s+10)<<3;I h4=load_3(s+13)<<2;I h5=load_4(s+16);I h6=load_3(s+20)<<7;I h7=load_3(s+23)<<5;I h8=load_3(s+26)<<4;I h9=(load_3(s+29)& 8388607)<<2;I L0;I L1;I L2;I L3;I L4;I L5;I L6;I L7;I L8;I L9;L9=(h9+(I)(1<<24))>>25;h0+=L9*19;h9-=L9<<25;L1=(h1+(I)(1<<24))>>25;h2+=L1;h1-=L1<<25;L3=(h3+(I)(1<<24))>>25;h4+=L3;h3-=L3<<25;L5=(h5+(I)(1<<24))>>25;h6+=L5;h5-=L5<<25;L7=(h7+(I)(1<<24))>>25;h8+=L7;h7-=L7<<25;L0=(h0+(I)(1<<25))>>26;h1+=L0;h0-=L0<<26;L2=(h2+(I)(1<<25))>>26;h3+=L2;h2-=L2<<26;L4=(h4+(I)(1<<25))>>26;h5+=L4;h4-=L4<<26;L6=(h6+(I)(1<<25))>>26;h7+=L6;h6-=L6<<26;L8=(h8+(I)(1<<25))>>26;h9+=L8;h8-=L8<<26;h[0]=(Q)h0;h[1]=(Q)h1;h[2]=(Q)h2;h[3]=(Q)h3;h[4]=(Q)h4;h[5]=(Q)h5;h[6]=(Q)h6;h[7]=(Q)h7;h[8]=(Q)h8;h[9]=(Q)h9;}void fe_invert(fe out,C fe z){fe t0;fe t1;fe t2;fe t3;int i;fe_sq(t0,z);for(i=1;i < 1;++i){fe_sq(t0,t0);}fe_sq(t1,t0);for(i=1;i < 2;++i){fe_sq(t1,t1);}fe_mul(t1,z,t1);fe_mul(t0,t0,t1);fe_sq(t2,t0);for(i=1;i < 1;++i){fe_sq(t2,t2);}fe_mul(t1,t1,t2);fe_sq(t2,t1);for(i=1;i < 5;++i){fe_sq(t2,t2);}fe_mul(t1,t2,t1);fe_sq(t2,t1);for(i=1;i < 10;++i){fe_sq(t2,t2);}fe_mul(t2,t2,t1);fe_sq(t3,t2);for(i=1;i < 20;++i){fe_sq(t3,t3);}fe_mul(t2,t3,t2);fe_sq(t2,t2);for(i=1;i < 10;++i){fe_sq(t2,t2);}fe_mul(t1,t2,t1);fe_sq(t2,t1);for(i=1;i < 50;++i){fe_sq(t2,t2);}fe_mul(t2,t2,t1);fe_sq(t3,t2);for(i=1;i < 100;++i){fe_sq(t3,t3);}fe_mul(t2,t3,t2);fe_sq(t2,t2);for(i=1;i < 50;++i){fe_sq(t2,t2);}fe_mul(t1,t2,t1);fe_sq(t1,t1);for(i=1;i < 5;++i){fe_sq(t1,t1);}fe_mul(out,t1,t0);}int fe_isnegative(C fe f){u8 s[32];fe_tobytes(s,f);E s[0] & 1;}int fe_isnonzero(C fe f){u8 s[32];u8 r;fe_tobytes(s,f);r=s[0];
#define F(i)r|=s[i]
F(1);F(2);F(3);F(4);F(5);F(6);F(7);F(8);F(9);F(10);F(11);F(12);F(13);F(14);F(15);F(16);F(17);F(18);F(19);F(20);F(21);F(22);F(23);F(24);F(25);F(26);F(27);F(28);F(29);F(30);F(31);
#undef F
E r !=0;}void fe_mul(fe h,C fe f,C fe g){Q f0=f[0];Q f1=f[1];Q f2=f[2];Q f3=f[3];Q f4=f[4];Q f5=f[5];Q f6=f[6];Q f7=f[7];Q f8=f[8];Q f9=f[9];Q g0=g[0];Q g1=g[1];Q g2=g[2];Q g3=g[3];Q g4=g[4];Q g5=g[5];Q g6=g[6];Q g7=g[7];Q g8=g[8];Q g9=g[9];Q g1_19=19*g1;Q g2_19=19*g2;Q g3_19=19*g3;Q g4_19=19*g4;Q g5_19=19*g5;Q g6_19=19*g6;Q g7_19=19*g7;Q g8_19=19*g8;Q g9_19=19*g9;Q f1_2=2*f1;Q f3_2=2*f3;Q f5_2=2*f5;Q f7_2=2*f7;Q f9_2=2*f9;I f0g0=f0*(I)g0;I f0g1=f0*(I)g1;I f0g2=f0*(I)g2;I f0g3=f0*(I)g3;I f0g4=f0*(I)g4;I f0g5=f0*(I)g5;I f0g6=f0*(I)g6;I f0g7=f0*(I)g7;I f0g8=f0*(I)g8;I f0g9=f0*(I)g9;I f1g0=f1*(I)g0;I f1g1_2=f1_2*(I)g1;I f1g2=f1*(I)g2;I f1g3_2=f1_2*(I)g3;I f1g4=f1*(I)g4;I f1g5_2=f1_2*(I)g5;I f1g6=f1*(I)g6;I f1g7_2=f1_2*(I)g7;I f1g8=f1*(I)g8;I f1g9_38=f1_2*(I)g9_19;I f2g0=f2*(I)g0;I f2g1=f2*(I)g1;I f2g2=f2*(I)g2;I f2g3=f2*(I)g3;I f2g4=f2*(I)g4;I f2g5=f2*(I)g5;I f2g6=f2*(I)g6;I f2g7=f2*(I)g7;I f2g8_19=f2*(I)g8_19;I f2g9_19=f2*(I)g9_19;I f3g0=f3*(I)g0;I f3g1_2=f3_2*(I)g1;I f3g2=f3*(I)g2;I f3g3_2=f3_2*(I)g3;I f3g4=f3*(I)g4;I f3g5_2=f3_2*(I)g5;I f3g6=f3*(I)g6;I f3g7_38=f3_2*(I)g7_19;I f3g8_19=f3*(I)g8_19;I f3g9_38=f3_2*(I)g9_19;I f4g0=f4*(I)g0;I f4g1=f4*(I)g1;I f4g2=f4*(I)g2;I f4g3=f4*(I)g3;I f4g4=f4*(I)g4;I f4g5=f4*(I)g5;I f4g6_19=f4*(I)g6_19;I f4g7_19=f4*(I)g7_19;I f4g8_19=f4*(I)g8_19;I f4g9_19=f4*(I)g9_19;I f5g0=f5*(I)g0;I f5g1_2=f5_2*(I)g1;I f5g2=f5*(I)g2;I f5g3_2=f5_2*(I)g3;I f5g4=f5*(I)g4;I f5g5_38=f5_2*(I)g5_19;I f5g6_19=f5*(I)g6_19;I f5g7_38=f5_2*(I)g7_19;I f5g8_19=f5*(I)g8_19;I f5g9_38=f5_2*(I)g9_19;I f6g0=f6*(I)g0;I f6g1=f6*(I)g1;I f6g2=f6*(I)g2;I f6g3=f6*(I)g3;I f6g4_19=f6*(I)g4_19;I f6g5_19=f6*(I)g5_19;I f6g6_19=f6*(I)g6_19;I f6g7_19=f6*(I)g7_19;I f6g8_19=f6*(I)g8_19;I f6g9_19=f6*(I)g9_19;I f7g0=f7*(I)g0;I f7g1_2=f7_2*(I)g1;I f7g2=f7*(I)g2;I f7g3_38=f7_2*(I)g3_19;I f7g4_19=f7*(I)g4_19;I f7g5_38=f7_2*(I)g5_19;I f7g6_19=f7*(I)g6_19;I f7g7_38=f7_2*(I)g7_19;I f7g8_19=f7*(I)g8_19;I f7g9_38=f7_2*(I)g9_19;I f8g0=f8*(I)g0;I f8g1=f8*(I)g1;I f8g2_19=f8*(I)g2_19;I f8g3_19=f8*(I)g3_19;I f8g4_19=f8*(I)g4_19;I f8g5_19=f8*(I)g5_19;I f8g6_19=f8*(I)g6_19;I f8g7_19=f8*(I)g7_19;I f8g8_19=f8*(I)g8_19;I f8g9_19=f8*(I)g9_19;I f9g0=f9*(I)g0;I f9g1_38=f9_2*(I)g1_19;I f9g2_19=f9*(I)g2_19;I f9g3_38=f9_2*(I)g3_19;I f9g4_19=f9*(I)g4_19;I f9g5_38=f9_2*(I)g5_19;I f9g6_19=f9*(I)g6_19;I f9g7_38=f9_2*(I)g7_19;I f9g8_19=f9*(I)g8_19;I f9g9_38=f9_2*(I)g9_19;I h0=f0g0+f1g9_38+f2g8_19+f3g7_38+f4g6_19+f5g5_38+f6g4_19+f7g3_38+f8g2_19+f9g1_38;I h1=f0g1+f1g0+f2g9_19+f3g8_19+f4g7_19+f5g6_19+f6g5_19+f7g4_19+f8g3_19+f9g2_19;I h2=f0g2+f1g1_2+f2g0+f3g9_38+f4g8_19+f5g7_38+f6g6_19+f7g5_38+f8g4_19+f9g3_38;I h3=f0g3+f1g2+f2g1+f3g0+f4g9_19+f5g8_19+f6g7_19+f7g6_19+f8g5_19+f9g4_19;I h4=f0g4+f1g3_2+f2g2+f3g1_2+f4g0+f5g9_38+f6g8_19+f7g7_38+f8g6_19+f9g5_38;I h5=f0g5+f1g4+f2g3+f3g2+f4g1+f5g0+f6g9_19+f7g8_19+f8g7_19+f9g6_19;I h6=f0g6+f1g5_2+f2g4+f3g3_2+f4g2+f5g1_2+f6g0+f7g9_38+f8g8_19+f9g7_38;I h7=f0g7+f1g6+f2g5+f3g4+f4g3+f5g2+f6g1+f7g0+f8g9_19+f9g8_19;I h8=f0g8+f1g7_2+f2g6+f3g5_2+f4g4+f5g3_2+f6g2+f7g1_2+f8g0+f9g9_38;I h9=f0g9+f1g8+f2g7+f3g6+f4g5+f5g4+f6g3+f7g2+f8g1+f9g0;I L0;I L1;I L2;I L3;I L4;I L5;I L6;I L7;I L8;I L9;L0=(h0+(I)(1<<25))>>26;h1+=L0;h0-=L0<<26;L4=(h4+(I)(1<<25))>>26;h5+=L4;h4-=L4<<26;L1=(h1+(I)(1<<24))>>25;h2+=L1;h1-=L1<<25;L5=(h5+(I)(1<<24))>>25;h6+=L5;h5-=L5<<25;L2=(h2+(I)(1<<25))>>26;h3+=L2;h2-=L2<<26;L6=(h6+(I)(1<<25))>>26;h7+=L6;h6-=L6<<26;L3=(h3+(I)(1<<24))>>25;h4+=L3;h3-=L3<<25;L7=(h7+(I)(1<<24))>>25;h8+=L7;h7-=L7<<25;L4=(h4+(I)(1<<25))>>26;h5+=L4;h4-=L4<<26;L8=(h8+(I)(1<<25))>>26;h9+=L8;h8-=L8<<26;L9=(h9+(I)(1<<24))>>25;h0+=L9*19;h9-=L9<<25;L0=(h0+(I)(1<<25))>>26;h1+=L0;h0-=L0<<26;h[0]=(Q)h0;h[1]=(Q)h1;h[2]=(Q)h2;h[3]=(Q)h3;h[4]=(Q)h4;h[5]=(Q)h5;h[6]=(Q)h6;h[7]=(Q)h7;h[8]=(Q)h8;h[9]=(Q)h9;}void fe_mul121666(fe h,fe f){Q f0=f[0];Q f1=f[1];Q f2=f[2];Q f3=f[3];Q f4=f[4];Q f5=f[5];Q f6=f[6];Q f7=f[7];Q f8=f[8];Q f9=f[9];I h0=f0*(I)121666;I h1=f1*(I)121666;I h2=f2*(I)121666;I h3=f3*(I)121666;I h4=f4*(I)121666;I h5=f5*(I)121666;I h6=f6*(I)121666;I h7=f7*(I)121666;I h8=f8*(I)121666;I h9=f9*(I)121666;I L0;I L1;I L2;I L3;I L4;I L5;I L6;I L7;I L8;I L9;L9=(h9+(I)(1<<24))>>25;h0+=L9*19;h9-=L9<<25;L1=(h1+(I)(1<<24))>>25;h2+=L1;h1-=L1<<25;L3=(h3+(I)(1<<24))>>25;h4+=L3;h3-=L3<<25;L5=(h5+(I)(1<<24))>>25;h6+=L5;h5-=L5<<25;L7=(h7+(I)(1<<24))>>25;h8+=L7;h7-=L7<<25;L0=(h0+(I)(1<<25))>>26;h1+=L0;h0-=L0<<26;L2=(h2+(I)(1<<25))>>26;h3+=L2;h2-=L2<<26;L4=(h4+(I)(1<<25))>>26;h5+=L4;h4-=L4<<26;L6=(h6+(I)(1<<25))>>26;h7+=L6;h6-=L6<<26;L8=(h8+(I)(1<<25))>>26;h9+=L8;h8-=L8<<26;h[0]=(Q)h0;h[1]=(Q)h1;h[2]=(Q)h2;h[3]=(Q)h3;h[4]=(Q)h4;h[5]=(Q)h5;h[6]=(Q)h6;h[7]=(Q)h7;h[8]=(Q)h8;h[9]=(Q)h9;}void fe_neg(fe h,C fe f){Q f0=f[0];Q f1=f[1];Q f2=f[2];Q f3=f[3];Q f4=f[4];Q f5=f[5];Q f6=f[6];Q f7=f[7];Q f8=f[8];Q f9=f[9];Q h0=-f0;Q h1=-f1;Q h2=-f2;Q h3=-f3;Q h4=-f4;Q h5=-f5;Q h6=-f6;Q h7=-f7;Q h8=-f8;Q h9=-f9;h[0]=h0;h[1]=h1;h[2]=h2;h[3]=h3;h[4]=h4;h[5]=h5;h[6]=h6;h[7]=h7;h[8]=h8;h[9]=h9;}void fe_pow22523(fe out,C fe z){fe t0;fe t1;fe t2;int i;fe_sq(t0,z);for(i=1;i < 1;++i){fe_sq(t0,t0);}fe_sq(t1,t0);for(i=1;i < 2;++i){fe_sq(t1,t1);}fe_mul(t1,z,t1);fe_mul(t0,t0,t1);fe_sq(t0,t0);for(i=1;i < 1;++i){fe_sq(t0,t0);}fe_mul(t0,t1,t0);fe_sq(t1,t0);for(i=1;i < 5;++i){fe_sq(t1,t1);}fe_mul(t0,t1,t0);fe_sq(t1,t0);for(i=1;i < 10;++i){fe_sq(t1,t1);}fe_mul(t1,t1,t0);fe_sq(t2,t1);for(i=1;i < 20;++i){fe_sq(t2,t2);}fe_mul(t1,t2,t1);fe_sq(t1,t1);for(i=1;i < 10;++i){fe_sq(t1,t1);}fe_mul(t0,t1,t0);fe_sq(t1,t0);for(i=1;i < 50;++i){fe_sq(t1,t1);}fe_mul(t1,t1,t0);fe_sq(t2,t1);for(i=1;i < 100;++i){fe_sq(t2,t2);}fe_mul(t1,t2,t1);fe_sq(t1,t1);for(i=1;i < 50;++i){fe_sq(t1,t1);}fe_mul(t0,t1,t0);fe_sq(t0,t0);for(i=1;i < 2;++i){fe_sq(t0,t0);}fe_mul(out,t0,z);E;}void fe_sq(fe h,C fe f){Q f0=f[0];Q f1=f[1];Q f2=f[2];Q f3=f[3];Q f4=f[4];Q f5=f[5];Q f6=f[6];Q f7=f[7];Q f8=f[8];Q f9=f[9];Q f0_2=2*f0;Q f1_2=2*f1;Q f2_2=2*f2;Q f3_2=2*f3;Q f4_2=2*f4;Q f5_2=2*f5;Q f6_2=2*f6;Q f7_2=2*f7;Q f5_38=38*f5;Q f6_19=19*f6;Q f7_38=38*f7;Q f8_19=19*f8;Q f9_38=38*f9;I f0f0=f0*(I)f0;I f0f1_2=f0_2*(I)f1;I f0f2_2=f0_2*(I)f2;I f0f3_2=f0_2*(I)f3;I f0f4_2=f0_2*(I)f4;I f0f5_2=f0_2*(I)f5;I f0f6_2=f0_2*(I)f6;I f0f7_2=f0_2*(I)f7;I f0f8_2=f0_2*(I)f8;I f0f9_2=f0_2*(I)f9;I f1f1_2=f1_2*(I)f1;I f1f2_2=f1_2*(I)f2;I f1f3_4=f1_2*(I)f3_2;I f1f4_2=f1_2*(I)f4;I f1f5_4=f1_2*(I)f5_2;I f1f6_2=f1_2*(I)f6;I f1f7_4=f1_2*(I)f7_2;I f1f8_2=f1_2*(I)f8;I f1f9_76=f1_2*(I)f9_38;I f2f2=f2*(I)f2;I f2f3_2=f2_2*(I)f3;I f2f4_2=f2_2*(I)f4;I f2f5_2=f2_2*(I)f5;I f2f6_2=f2_2*(I)f6;I f2f7_2=f2_2*(I)f7;I f2f8_38=f2_2*(I)f8_19;I f2f9_38=f2*(I)f9_38;I f3f3_2=f3_2*(I)f3;I f3f4_2=f3_2*(I)f4;I f3f5_4=f3_2*(I)f5_2;I f3f6_2=f3_2*(I)f6;I f3f7_76=f3_2*(I)f7_38;I f3f8_38=f3_2*(I)f8_19;I f3f9_76=f3_2*(I)f9_38;I f4f4=f4*(I)f4;I f4f5_2=f4_2*(I)f5;I f4f6_38=f4_2*(I)f6_19;I f4f7_38=f4*(I)f7_38;I f4f8_38=f4_2*(I)f8_19;I f4f9_38=f4*(I)f9_38;I f5f5_38=f5*(I)f5_38;I f5f6_38=f5_2*(I)f6_19;I f5f7_76=f5_2*(I)f7_38;I f5f8_38=f5_2*(I)f8_19;I f5f9_76=f5_2*(I)f9_38;I f6f6_19=f6*(I)f6_19;I f6f7_38=f6*(I)f7_38;I f6f8_38=f6_2*(I)f8_19;I f6f9_38=f6*(I)f9_38;I f7f7_38=f7*(I)f7_38;I f7f8_38=f7_2*(I)f8_19;I f7f9_76=f7_2*(I)f9_38;I f8f8_19=f8*(I)f8_19;I f8f9_38=f8*(I)f9_38;I f9f9_38=f9*(I)f9_38;I h0=f0f0+f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38;I h1=f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38;I h2=f0f2_2+f1f1_2+f3f9_76+f4f8_38+f5f7_76+f6f6_19;I h3=f0f3_2+f1f2_2+f4f9_38+f5f8_38+f6f7_38;I h4=f0f4_2+f1f3_4+f2f2+f5f9_76+f6f8_38+f7f7_38;I h5=f0f5_2+f1f4_2+f2f3_2+f6f9_38+f7f8_38;I h6=f0f6_2+f1f5_4+f2f4_2+f3f3_2+f7f9_76+f8f8_19;I h7=f0f7_2+f1f6_2+f2f5_2+f3f4_2+f8f9_38;I h8=f0f8_2+f1f7_4+f2f6_2+f3f5_4+f4f4+f9f9_38;I h9=f0f9_2+f1f8_2+f2f7_2+f3f6_2+f4f5_2;I L0;I L1;I L2;I L3;I L4;I L5;I L6;I L7;I L8;I L9;L0=(h0+(I)(1<<25))>>26;h1+=L0;h0-=L0<<26;L4=(h4+(I)(1<<25))>>26;h5+=L4;h4-=L4<<26;L1=(h1+(I)(1<<24))>>25;h2+=L1;h1-=L1<<25;L5=(h5+(I)(1<<24))>>25;h6+=L5;h5-=L5<<25;L2=(h2+(I)(1<<25))>>26;h3+=L2;h2-=L2<<26;L6=(h6+(I)(1<<25))>>26;h7+=L6;h6-=L6<<26;L3=(h3+(I)(1<<24))>>25;h4+=L3;h3-=L3<<25;L7=(h7+(I)(1<<24))>>25;h8+=L7;h7-=L7<<25;L4=(h4+(I)(1<<25))>>26;h5+=L4;h4-=L4<<26;L8=(h8+(I)(1<<25))>>26;h9+=L8;h8-=L8<<26;L9=(h9+(I)(1<<24))>>25;h0+=L9*19;h9-=L9<<25;L0=(h0+(I)(1<<25))>>26;h1+=L0;h0-=L0<<26;h[0]=(Q)h0;h[1]=(Q)h1;h[2]=(Q)h2;h[3]=(Q)h3;h[4]=(Q)h4;h[5]=(Q)h5;h[6]=(Q)h6;h[7]=(Q)h7;h[8]=(Q)h8;h[9]=(Q)h9;}void fe_sq2(fe h,C fe f){Q f0=f[0];Q f1=f[1];Q f2=f[2];Q f3=f[3];Q f4=f[4];Q f5=f[5];Q f6=f[6];Q f7=f[7];Q f8=f[8];Q f9=f[9];Q f0_2=2*f0;Q f1_2=2*f1;Q f2_2=2*f2;Q f3_2=2*f3;Q f4_2=2*f4;Q f5_2=2*f5;Q f6_2=2*f6;Q f7_2=2*f7;Q f5_38=38*f5;Q f6_19=19*f6;Q f7_38=38*f7;Q f8_19=19*f8;Q f9_38=38*f9;I f0f0=f0*(I)f0;I f0f1_2=f0_2*(I)f1;I f0f2_2=f0_2*(I)f2;I f0f3_2=f0_2*(I)f3;I f0f4_2=f0_2*(I)f4;I f0f5_2=f0_2*(I)f5;I f0f6_2=f0_2*(I)f6;I f0f7_2=f0_2*(I)f7;I f0f8_2=f0_2*(I)f8;I f0f9_2=f0_2*(I)f9;I f1f1_2=f1_2*(I)f1;I f1f2_2=f1_2*(I)f2;I f1f3_4=f1_2*(I)f3_2;I f1f4_2=f1_2*(I)f4;I f1f5_4=f1_2*(I)f5_2;I f1f6_2=f1_2*(I)f6;I f1f7_4=f1_2*(I)f7_2;I f1f8_2=f1_2*(I)f8;I f1f9_76=f1_2*(I)f9_38;I f2f2=f2*(I)f2;I f2f3_2=f2_2*(I)f3;I f2f4_2=f2_2*(I)f4;I f2f5_2=f2_2*(I)f5;I f2f6_2=f2_2*(I)f6;I f2f7_2=f2_2*(I)f7;I f2f8_38=f2_2*(I)f8_19;I f2f9_38=f2*(I)f9_38;I f3f3_2=f3_2*(I)f3;I f3f4_2=f3_2*(I)f4;I f3f5_4=f3_2*(I)f5_2;I f3f6_2=f3_2*(I)f6;I f3f7_76=f3_2*(I)f7_38;I f3f8_38=f3_2*(I)f8_19;I f3f9_76=f3_2*(I)f9_38;I f4f4=f4*(I)f4;I f4f5_2=f4_2*(I)f5;I f4f6_38=f4_2*(I)f6_19;I f4f7_38=f4*(I)f7_38;I f4f8_38=f4_2*(I)f8_19;I f4f9_38=f4*(I)f9_38;I f5f5_38=f5*(I)f5_38;I f5f6_38=f5_2*(I)f6_19;I f5f7_76=f5_2*(I)f7_38;I f5f8_38=f5_2*(I)f8_19;I f5f9_76=f5_2*(I)f9_38;I f6f6_19=f6*(I)f6_19;I f6f7_38=f6*(I)f7_38;I f6f8_38=f6_2*(I)f8_19;I f6f9_38=f6*(I)f9_38;I f7f7_38=f7*(I)f7_38;I f7f8_38=f7_2*(I)f8_19;I f7f9_76=f7_2*(I)f9_38;I f8f8_19=f8*(I)f8_19;I f8f9_38=f8*(I)f9_38;I f9f9_38=f9*(I)f9_38;I h0=f0f0+f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38;I h1=f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38;I h2=f0f2_2+f1f1_2+f3f9_76+f4f8_38+f5f7_76+f6f6_19;I h3=f0f3_2+f1f2_2+f4f9_38+f5f8_38+f6f7_38;I h4=f0f4_2+f1f3_4+f2f2+f5f9_76+f6f8_38+f7f7_38;I h5=f0f5_2+f1f4_2+f2f3_2+f6f9_38+f7f8_38;I h6=f0f6_2+f1f5_4+f2f4_2+f3f3_2+f7f9_76+f8f8_19;I h7=f0f7_2+f1f6_2+f2f5_2+f3f4_2+f8f9_38;I h8=f0f8_2+f1f7_4+f2f6_2+f3f5_4+f4f4+f9f9_38;I h9=f0f9_2+f1f8_2+f2f7_2+f3f6_2+f4f5_2;I L0;I L1;I L2;I L3;I L4;I L5;I L6;I L7;I L8;I L9;h0+=h0;h1+=h1;h2+=h2;h3+=h3;h4+=h4;h5+=h5;h6+=h6;h7+=h7;h8+=h8;h9+=h9;L0=(h0+(I)(1<<25))>>26;h1+=L0;h0-=L0<<26;L4=(h4+(I)(1<<25))>>26;h5+=L4;h4-=L4<<26;L1=(h1+(I)(1<<24))>>25;h2+=L1;h1-=L1<<25;L5=(h5+(I)(1<<24))>>25;h6+=L5;h5-=L5<<25;L2=(h2+(I)(1<<25))>>26;h3+=L2;h2-=L2<<26;L6=(h6+(I)(1<<25))>>26;h7+=L6;h6-=L6<<26;L3=(h3+(I)(1<<24))>>25;h4+=L3;h3-=L3<<25;L7=(h7+(I)(1<<24))>>25;h8+=L7;h7-=L7<<25;L4=(h4+(I)(1<<25))>>26;h5+=L4;h4-=L4<<26;L8=(h8+(I)(1<<25))>>26;h9+=L8;h8-=L8<<26;L9=(h9+(I)(1<<24))>>25;h0+=L9*19;h9-=L9<<25;L0=(h0+(I)(1<<25))>>26;h1+=L0;h0-=L0<<26;h[0]=(Q)h0;h[1]=(Q)h1;h[2]=(Q)h2;h[3]=(Q)h3;h[4]=(Q)h4;h[5]=(Q)h5;h[6]=(Q)h6;h[7]=(Q)h7;h[8]=(Q)h8;h[9]=(Q)h9;}void fe_sub(fe h,C fe f,C fe g){Q f0=f[0];Q f1=f[1];Q f2=f[2];Q f3=f[3];Q f4=f[4];Q f5=f[5];Q f6=f[6];Q f7=f[7];Q f8=f[8];Q f9=f[9];Q g0=g[0];Q g1=g[1];Q g2=g[2];Q g3=g[3];Q g4=g[4];Q g5=g[5];Q g6=g[6];Q g7=g[7];Q g8=g[8];Q g9=g[9];Q h0=f0-g0;Q h1=f1-g1;Q h2=f2-g2;Q h3=f3-g3;Q h4=f4-g4;Q h5=f5-g5;Q h6=f6-g6;Q h7=f7-g7;Q h8=f8-g8;Q h9=f9-g9;h[0]=h0;h[1]=h1;h[2]=h2;h[3]=h3;h[4]=h4;h[5]=h5;h[6]=h6;h[7]=h7;h[8]=h8;h[9]=h9;}void fe_tobytes(u8*s,C fe h){Q h0=h[0];Q h1=h[1];Q h2=h[2];Q h3=h[3];Q h4=h[4];Q h5=h[5];Q h6=h[6];Q h7=h[7];Q h8=h[8];Q h9=h[9];Q q;Q L0;Q L1;Q L2;Q L3;Q L4;Q L5;Q L6;Q L7;Q L8;Q L9;q=(19*h9+(((Q)1)<<24))>>25;q=(h0+q)>>26;q=(h1+q)>>25;q=(h2+q)>>26;q=(h3+q)>>25;q=(h4+q)>>26;q=(h5+q)>>25;q=(h6+q)>>26;q=(h7+q)>>25;q=(h8+q)>>26;q=(h9+q)>>25;h0+=19*q;L0=h0>>26;h1+=L0;h0-=L0<<26;L1=h1>>25;h2+=L1;h1-=L1<<25;L2=h2>>26;h3+=L2;h2-=L2<<26;L3=h3>>25;h4+=L3;h3-=L3<<25;L4=h4>>26;h5+=L4;h4-=L4<<26;L5=h5>>25;h6+=L5;h5-=L5<<25;L6=h6>>26;h7+=L6;h6-=L6<<26;L7=h7>>25;h8+=L7;h7-=L7<<25;L8=h8>>26;h9+=L8;h8-=L8<<26;L9=h9>>25;h9-=L9<<25;s[0]=(u8)(h0>>0);s[1]=(u8)(h0>>8);s[2]=(u8)(h0>>16);s[3]=(u8)((h0>>24)|(h1<<2));s[4]=(u8)(h1>>6);s[5]=(u8)(h1>>14);s[6]=(u8)((h1>>22)|(h2<<3));s[7]=(u8)(h2>>5);s[8]=(u8)(h2>>13);s[9]=(u8)((h2>>21)|(h3<<5));s[10]=(u8)(h3>>3);s[11]=(u8)(h3>>11);s[12]=(u8)((h3>>19)|(h4<<6));s[13]=(u8)(h4>>2);s[14]=(u8)(h4>>10);s[15]=(u8)(h4>>18);s[16]=(u8)(h5>>0);s[17]=(u8)(h5>>8);s[18]=(u8)(h5>>16);s[19]=(u8)((h5>>24)|(h6<<1));s[20]=(u8)(h6>>7);s[21]=(u8)(h6>>15);s[22]=(u8)((h6>>23)|(h7<<3));s[23]=(u8)(h7>>5);s[24]=(u8)(h7>>13);s[25]=(u8)((h7>>21)|(h8<<4));s[26]=(u8)(h8>>4);s[27]=(u8)(h8>>12);s[28]=(u8)((h8>>20)|(h9<<6));s[29]=(u8)(h9>>2);s[30]=(u8)(h9>>10);s[31]=(u8)(h9>>18);}typedef struct{fe X;fe Y;fe Z;}ge_p2;typedef struct{fe X;fe Y;fe Z;fe T;}ge_p3;typedef struct{fe X;fe Y;fe Z;fe T;}ge_p1p1;typedef struct{fe yplusx;fe yminusx;fe xy2d;}ge_precomp;typedef struct{fe YplusX;fe YminusX;fe Z;fe T2d;}ge_cached;void ge_p3_tobytes(u8*s,C ge_p3*h);void ge_tobytes(u8*s,C ge_p2*h);int ge_frombytes_negate_vartime(ge_p3*h,C u8*s);void ge_add(ge_p1p1*r,C ge_p3*p,C ge_cached*q);void ge_sub(ge_p1p1*r,C ge_p3*p,C ge_cached*q);void ge_double_scalarmult_vartime(ge_p2*r,C u8*a,C ge_p3*A,C u8*b);void ge_madd(ge_p1p1*r,C ge_p3*p,C ge_precomp*q);void ge_msub(ge_p1p1*r,C ge_p3*p,C ge_precomp*q);void ge_scalarmult_base(ge_p3*h,C u8*a);void ge_p1p1_to_p2(ge_p2*r,C ge_p1p1*p);void ge_p1p1_to_p3(ge_p3*r,C ge_p1p1*p);void ge_p2_0(ge_p2*h);void ge_p2_dbl(ge_p1p1*r,C ge_p2*p);void ge_p3_0(ge_p3*h);void ge_p3_dbl(ge_p1p1*r,C ge_p3*p);void ge_p3_to_cached(ge_cached*r,C ge_p3*p);void ge_p3_to_p2(ge_p2*r,C ge_p3*p);static C ge_precomp Bi[8]={{{25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605},{-12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378},{-8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546},},{{15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024},{16568933,4717097,-11556148,-1102322,15682896,-11807043,16354577,-11775962,7689662,11199574},{30464156,-5976125,-11779434,-15670865,23220365,15915852,7512774,10017326,-17749093,-9920357},},{{10861363,11473154,27284546,1981175,-30064349,12577861,32867885,14515107,-15438304,10819380},{4708026,6336745,20377586,9066809,-11272109,6594696,-25653668,12483688,-12668491,5581306},{19563160,16186464,-29386857,4097519,10237984,-4348115,28542350,13850243,-23678021,-15815942},},{{5153746,9909285,1723747,-2777874,30523605,5516873,19480852,5230134,-23952439,-15175766},{-30269007,-3463509,7665486,10083793,28475525,1649722,20654025,16520125,30598449,7715701},{28881845,14381568,9657904,3680757,-20181635,7843316,-31400660,1370708,29794553,-1409300},},{{-22518993,-6692182,14201702,-8745502,-23510406,8844726,18474211,-1361450,-13062696,13821877},{-6455177,-7839871,3374702,-4740862,-27098617,-10571707,31655028,-7212327,18853322,-14220951},{4566830,-12963868,-28974889,-12240689,-7602672,-2830569,-8514358,-10431137,2207753,-3209784},},{{-25154831,-4185821,29681144,7868801,-6854661,-9423865,-12437364,-663000,-31111463,-16132436},{25576264,-2703214,7349804,-11814844,16472782,9300885,3844789,15725684,171356,6466918},{23103977,13316479,9739013,-16149481,817875,-15038942,8965339,-14088058,-30714912,16193877},},{{-33521811,3180713,-2394130,14003687,-16903474,-16270840,17238398,4729455,-18074513,9256800},{-25182317,-4174131,32336398,5036987,-21236817,11360617,22616405,9761698,-19827198,630305},{-13720693,2639453,-24237460,-7406481,9494427,-5774029,-6554551,-15960994,-2449256,-14291300},},{{-3151181,-5046075,9282714,6866145,-31907062,-863023,-18940575,15033784,25105118,-7894876},{-24326370,15950226,-31801215,-14592823,-11662737,-5090925,1573892,-2625887,2198790,-15804619},{-3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683},},};// didn't find full solution yet
static ge_precomp base[32][8];static int active_row;void cached_to_precomp(ge_precomp*preComp,ge_cached*cached){fe inverse;fe_invert(inverse,cached->Z);fe_mul(preComp->yminusx,cached->YminusX,inverse);fe_mul(preComp->yplusx,cached->YplusX,inverse);fe_mul(preComp->xy2d,cached->T2d,inverse);}void compute_row(ge_cached*b){ge_precomp result;ge_p3 p3;ge_p3_0(&p3);int j;for(j=0;j < 8;j++){ge_p1p1 p1p1;ge_cached cached;ge_add(&p1p1,& p3,b);ge_p1p1_to_p3(& p3,& p1p1);ge_p3_to_cached(& cached,& p3);cached_to_precomp(&result,&cached);base[active_row][j]=result;}}void compute_lookup_table(ge_cached*b){ge_p3 p3;ge_p2 p2;ge_p1p1 p1p1;ge_cached cached;ge_p3_0(&p3);ge_add(&p1p1,&p3,b);ge_p1p1_to_p3(&p3,&p1p1);int i,k;for(i=0;i < 32;i++){active_row=i;ge_p3_to_cached(&cached,&p3);compute_row(&cached);ge_p3_to_p2(&p2,&p3);for(k=0;k < 7;k++){ge_p2_dbl(&p1p1,&p2);ge_p1p1_to_p2(&p2,&p1p1);}ge_p2_dbl(& p1p1,& p2);ge_p1p1_to_p3(& p3,& p1p1);}}void LOOKT_write_lookup_table_to_flash(void){fe ypx={25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605};fe ymx={-12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378};fe T2d={-8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546};fe Z;fe_1(Z);ge_cached Bi0;int p;for(p=0;p < 10;p++){Bi0.YplusX[p]=ypx[p];Bi0.YminusX[p]=ymx[p];Bi0.T2d[p]=T2d[p];Bi0.Z[p]=Z[p];}compute_lookup_table(&Bi0);}void ge_add(ge_p1p1*r,C ge_p3*p,C ge_cached*q){fe t0;fe_add(r->X,p->Y,p->X);fe_sub(r->Y,p->Y,p->X);fe_mul(r->Z,r->X,q->YplusX);fe_mul(r->Y,r->Y,q->YminusX);fe_mul(r->T,q->T2d,p->T);fe_mul(r->X,p->Z,q->Z);fe_add(t0,r->X,r->X);fe_sub(r->X,r->Z,r->Y);fe_add(r->Y,r->Z,r->Y);fe_add(r->Z,t0,r->T);fe_sub(r->T,t0,r->T);}static void slide(signed char*r,C u8*a){int i;int b;int k;for(i=0;i < 256;++i){r[i]=1 &(a[i>>3]>>(i & 7));}for(i=0;i < 256;++i)if(r[i]){for(b=1;b <=6 && i+b < 256;++b){if(r[i+b]){if(r[i]+(r[i+b]<<b)<=15){r[i]+=r[i+b]<<b;r[i+b]=0;}else if(r[i]-(r[i+b]<<b)>=-15){r[i]-=r[i+b]<<b;for(k=i+b;k < 256;++k){if(!r[k]){r[k]=1;break;}r[k]=0;}}else{break;}}}}}void ge_double_scalarmult_vartime(ge_p2*r,C u8*a,C ge_p3*A,C u8*b){signed char aslide[256];signed char bslide[256];ge_cached Ai[8];ge_p1p1 t;ge_p3 u;ge_p3 A2;int i;slide(aslide,a);slide(bslide,b);ge_p3_to_cached(&Ai[0],A);ge_p3_dbl(&t,A);ge_p1p1_to_p3(&A2,&t);ge_add(&t,&A2,&Ai[0]);ge_p1p1_to_p3(&u,&t);ge_p3_to_cached(&Ai[1],&u);ge_add(&t,&A2,&Ai[1]);ge_p1p1_to_p3(&u,&t);ge_p3_to_cached(&Ai[2],&u);ge_add(&t,&A2,&Ai[2]);ge_p1p1_to_p3(&u,&t);ge_p3_to_cached(&Ai[3],&u);ge_add(&t,&A2,&Ai[3]);ge_p1p1_to_p3(&u,&t);ge_p3_to_cached(&Ai[4],&u);ge_add(&t,&A2,&Ai[4]);ge_p1p1_to_p3(&u,&t);ge_p3_to_cached(&Ai[5],&u);ge_add(&t,&A2,&Ai[5]);ge_p1p1_to_p3(&u,&t);ge_p3_to_cached(&Ai[6],&u);ge_add(&t,&A2,&Ai[6]);ge_p1p1_to_p3(&u,&t);ge_p3_to_cached(&Ai[7],&u);ge_p2_0(r);for(i=255;i >=0;--i){if(aslide[i]||bslide[i]){break;}}for(;i >=0;--i){ge_p2_dbl(&t,r);if(aslide[i] > 0){ge_p1p1_to_p3(&u,&t);ge_add(&t,&u,&Ai[aslide[i] / 2]);}else if(aslide[i] < 0){ge_p1p1_to_p3(&u,&t);ge_sub(&t,&u,&Ai[(-aslide[i])/ 2]);}if(bslide[i] > 0){ge_p1p1_to_p3(&u,&t);ge_madd(&t,&u,&Bi[bslide[i] / 2]);}else if(bslide[i] < 0){ge_p1p1_to_p3(&u,&t);ge_msub(&t,&u,&Bi[(-bslide[i])/ 2]);}ge_p1p1_to_p2(r,&t);}}static C fe d={-10913610,13857413,-15372611,6949391,114729,-8787816,-6275908,-3247719,-18696448,-12055116};static C fe sqrtm1={-32595792,-7943725,9377950,3500415,12389472,-272473,-25146209,-2005654,326686,11406482};int ge_frombytes_negate_vartime(ge_p3*h,C u8*s){fe u;fe v;fe v3;fe vxx;fe check;fe_frombytes(h->Y,s);fe_1(h->Z);fe_sq(u,h->Y);fe_mul(v,u,d);fe_sub(u,u,h->Z);fe_add(v,v,h->Z);fe_sq(v3,v);fe_mul(v3,v3,v);fe_sq(h->X,v3);fe_mul(h->X,h->X,v);fe_mul(h->X,h->X,u);fe_pow22523(h->X,h->X);fe_mul(h->X,h->X,v3);fe_mul(h->X,h->X,u);fe_sq(vxx,h->X);fe_mul(vxx,vxx,v);fe_sub(check,vxx,u);if(fe_isnonzero(check)){fe_add(check,vxx,u);if(fe_isnonzero(check)){E-1;}fe_mul(h->X,h->X,sqrtm1);}if(fe_isnegative(h->X)==(s[31]>>7)){fe_neg(h->X,h->X);}fe_mul(h->T,h->X,h->Y);E 0;}void ge_madd(ge_p1p1*r,C ge_p3*p,C ge_precomp*q){fe t0;fe_add(r->X,p->Y,p->X);fe_sub(r->Y,p->Y,p->X);fe_mul(r->Z,r->X,q->yplusx);fe_mul(r->Y,r->Y,q->yminusx);fe_mul(r->T,q->xy2d,p->T);fe_add(t0,p->Z,p->Z);fe_sub(r->X,r->Z,r->Y);fe_add(r->Y,r->Z,r->Y);fe_add(r->Z,t0,r->T);fe_sub(r->T,t0,r->T);}void ge_msub(ge_p1p1*r,C ge_p3*p,C ge_precomp*q){fe t0;fe_add(r->X,p->Y,p->X);fe_sub(r->Y,p->Y,p->X);fe_mul(r->Z,r->X,q->yminusx);fe_mul(r->Y,r->Y,q->yplusx);fe_mul(r->T,q->xy2d,p->T);fe_add(t0,p->Z,p->Z);fe_sub(r->X,r->Z,r->Y);fe_add(r->Y,r->Z,r->Y);fe_sub(r->Z,t0,r->T);fe_add(r->T,t0,r->T);}void ge_p1p1_to_p2(ge_p2*r,C ge_p1p1*p){fe_mul(r->X,p->X,p->T);fe_mul(r->Y,p->Y,p->Z);fe_mul(r->Z,p->Z,p->T);}void ge_p1p1_to_p3(ge_p3*r,C ge_p1p1*p){fe_mul(r->X,p->X,p->T);fe_mul(r->Y,p->Y,p->Z);fe_mul(r->Z,p->Z,p->T);fe_mul(r->T,p->X,p->Y);}void ge_p2_0(ge_p2*h){fe_0(h->X);fe_1(h->Y);fe_1(h->Z);}void ge_p2_dbl(ge_p1p1*r,C ge_p2*p){fe t0;fe_sq(r->X,p->X);fe_sq(r->Z,p->Y);fe_sq2(r->T,p->Z);fe_add(r->Y,p->X,p->Y);fe_sq(t0,r->Y);fe_add(r->Y,r->Z,r->X);fe_sub(r->Z,r->Z,r->X);fe_sub(r->X,t0,r->Y);fe_sub(r->T,r->T,r->Z);}void ge_p3_0(ge_p3*h){fe_0(h->X);fe_1(h->Y);fe_1(h->Z);fe_0(h->T);}void ge_p3_dbl(ge_p1p1*r,C ge_p3*p){ge_p2 q;ge_p3_to_p2(&q,p);ge_p2_dbl(r,&q);}static C fe d2={-21827239,-5839606,-30745221,13898782,229458,15978800,-12551817,-6495438,29715968,9444199};void ge_p3_to_cached(ge_cached*r,C ge_p3*p){fe_add(r->YplusX,p->Y,p->X);fe_sub(r->YminusX,p->Y,p->X);fe_copy(r->Z,p->Z);fe_mul(r->T2d,p->T,d2);}void ge_p3_to_p2(ge_p2*r,C ge_p3*p){fe_copy(r->X,p->X);fe_copy(r->Y,p->Y);fe_copy(r->Z,p->Z);}void ge_p3_tobytes(u8*s,C ge_p3*h){fe recip;fe x;fe y;fe_invert(recip,h->Z);fe_mul(x,h->X,recip);fe_mul(y,h->Y,recip);fe_tobytes(s,y);s[31]^=fe_isnegative(x)<<7;}static u8 equal(signed char b,signed char c){u8 ub=b;u8 uc=c;u8 x=ub^uc;u64 y=x;y-=1;y>>=63;E(u8)y;}static u8 negative(signed char b){u64 x=b;x>>=63;E(u8)x;}static void cmov(ge_precomp*t,C ge_precomp*u,u8 b){fe_cmov(t->yplusx,u->yplusx,b);fe_cmov(t->yminusx,u->yminusx,b);fe_cmov(t->xy2d,u->xy2d,b);}static void select(ge_precomp*t,int pos,signed char b){ge_precomp minust;u8 bnegative=negative(b);u8 babs=b-(((-bnegative)& b)<<1);fe_1(t->yplusx);fe_1(t->yminusx);fe_0(t->xy2d);cmov(t,&base[pos][0],equal(babs,1));cmov(t,&base[pos][1],equal(babs,2));cmov(t,&base[pos][2],equal(babs,3));cmov(t,&base[pos][3],equal(babs,4));cmov(t,&base[pos][4],equal(babs,5));cmov(t,&base[pos][5],equal(babs,6));cmov(t,&base[pos][6],equal(babs,7));cmov(t,&base[pos][7],equal(babs,8));fe_copy(minust.yplusx,t->yminusx);fe_copy(minust.yminusx,t->yplusx);fe_neg(minust.xy2d,t->xy2d);cmov(t,&minust,bnegative);}void ge_scalarmult_base(ge_p3*h,C u8*a){signed char e[64];signed char L;ge_p1p1 r;ge_p2 s;ge_precomp t;int i;for(i=0;i < 32;++i){e[2*i+0]=(a[i]>>0)& 15;e[2*i+1]=(a[i]>>4)& 15;}L=0;for(i=0;i < 63;++i){e[i]+=L;L=e[i]+8;L>>=4;e[i]-=L<<4;}e[63]+=L;ge_p3_0(h);for(i=1;i < 64;i+=2){select(&t,i / 2,e[i]);ge_madd(&r,h,&t);ge_p1p1_to_p3(h,&r);}ge_p3_dbl(&r,h);ge_p1p1_to_p2(&s,&r);ge_p2_dbl(&r,&s);ge_p1p1_to_p2(&s,&r);ge_p2_dbl(&r,&s);ge_p1p1_to_p2(&s,&r);ge_p2_dbl(&r,&s);ge_p1p1_to_p3(h,&r);for(i=0;i < 64;i+=2){select(&t,i / 2,e[i]);ge_madd(&r,h,&t);ge_p1p1_to_p3(h,&r);}}void ge_sub(ge_p1p1*r,C ge_p3*p,C ge_cached*q){fe t0;fe_add(r->X,p->Y,p->X);fe_sub(r->Y,p->Y,p->X);fe_mul(r->Z,r->X,q->YminusX);fe_mul(r->Y,r->Y,q->YplusX);fe_mul(r->T,q->T2d,p->T);fe_mul(r->X,p->Z,q->Z);fe_add(t0,r->X,r->X);fe_sub(r->X,r->Z,r->Y);fe_add(r->Y,r->Z,r->Y);fe_sub(r->Z,t0,r->T);fe_add(r->T,t0,r->T);}void ge_tobytes(u8*s,C ge_p2*h){fe recip;fe x;fe y;fe_invert(recip,h->Z);fe_mul(x,h->X,recip);fe_mul(y,h->Y,recip);fe_tobytes(s,y);s[31]^=fe_isnegative(x)<<7;}void sc_reduce(u8*s);void sc_muladd(u8*s,C u8*a,C u8*b,C u8*c);void sc_reduce(u8*s){I s0=2097151 & load_3(s);I s1=2097151 &(load_4(s+2)>>5);I s2=2097151 &(load_3(s+5)>>2);I s3=2097151 &(load_4(s+7)>>7);I s4=2097151 &(load_4(s+10)>>4);I s5=2097151 &(load_3(s+13)>>1);I s6=2097151 &(load_4(s+15)>>6);I s7=2097151 &(load_3(s+18)>>3);I s8=2097151 & load_3(s+21);I s9=2097151 &(load_4(s+23)>>5);I s10=2097151 &(load_3(s+26)>>2);I s11=2097151 &(load_4(s+28)>>7);I s12=2097151 &(load_4(s+31)>>4);I s13=2097151 &(load_3(s+34)>>1);I s14=2097151 &(load_4(s+36)>>6);I s15=2097151 &(load_3(s+39)>>3);I s16=2097151 & load_3(s+42);I s17=2097151 &(load_4(s+44)>>5);I s18=2097151 &(load_3(s+47)>>2);I s19=2097151 &(load_4(s+49)>>7);I s20=2097151 &(load_4(s+52)>>4);I s21=2097151 &(load_3(s+55)>>1);I s22=2097151 &(load_4(s+57)>>6);I s23=(load_4(s+60)>>3);I L0;I L1;I L2;I L3;I L4;I L5;I L6;I L7;I L8;I L9;I L10;I L11;I L12;I L13;I L14;I L15;I L16;s11+=s23*666643;s12+=s23*470296;s13+=s23*654183;s14-=s23*997805;s15+=s23*136657;s16-=s23*683901;s23=0;s10+=s22*666643;s11+=s22*470296;s12+=s22*654183;s13-=s22*997805;s14+=s22*136657;s15-=s22*683901;s22=0;s9+=s21*666643;s10+=s21*470296;s11+=s21*654183;s12-=s21*997805;s13+=s21*136657;s14-=s21*683901;s21=0;s8+=s20*666643;s9+=s20*470296;s10+=s20*654183;s11-=s20*997805;s12+=s20*136657;s13-=s20*683901;s20=0;s7+=s19*666643;s8+=s19*470296;s9+=s19*654183;s10-=s19*997805;s11+=s19*136657;s12-=s19*683901;s19=0;s6+=s18*666643;s7+=s18*470296;s8+=s18*654183;s9-=s18*997805;s10+=s18*136657;s11-=s18*683901;s18=0;L6=(s6+(1<<20))>>21;s7+=L6;s6-=L6<<21;L8=(s8+(1<<20))>>21;s9+=L8;s8-=L8<<21;L10=(s10+(1<<20))>>21;s11+=L10;s10-=L10<<21;L12=(s12+(1<<20))>>21;s13+=L12;s12-=L12<<21;L14=(s14+(1<<20))>>21;s15+=L14;s14-=L14<<21;L16=(s16+(1<<20))>>21;s17+=L16;s16-=L16<<21;L7=(s7+(1<<20))>>21;s8+=L7;s7-=L7<<21;L9=(s9+(1<<20))>>21;s10+=L9;s9-=L9<<21;L11=(s11+(1<<20))>>21;s12+=L11;s11-=L11<<21;L13=(s13+(1<<20))>>21;s14+=L13;s13-=L13<<21;L15=(s15+(1<<20))>>21;s16+=L15;s15-=L15<<21;s5+=s17*666643;s6+=s17*470296;s7+=s17*654183;s8-=s17*997805;s9+=s17*136657;s10-=s17*683901;s17=0;s4+=s16*666643;s5+=s16*470296;s6+=s16*654183;s7-=s16*997805;s8+=s16*136657;s9-=s16*683901;s16=0;s3+=s15*666643;s4+=s15*470296;s5+=s15*654183;s6-=s15*997805;s7+=s15*136657;s8-=s15*683901;s15=0;s2+=s14*666643;s3+=s14*470296;s4+=s14*654183;s5-=s14*997805;s6+=s14*136657;s7-=s14*683901;s14=0;s1+=s13*666643;s2+=s13*470296;s3+=s13*654183;s4-=s13*997805;s5+=s13*136657;s6-=s13*683901;s13=0;s0+=s12*666643;s1+=s12*470296;s2+=s12*654183;s3-=s12*997805;s4+=s12*136657;s5-=s12*683901;s12=0;L0=(s0+(1<<20))>>21;s1+=L0;s0-=L0<<21;L2=(s2+(1<<20))>>21;s3+=L2;s2-=L2<<21;L4=(s4+(1<<20))>>21;s5+=L4;s4-=L4<<21;L6=(s6+(1<<20))>>21;s7+=L6;s6-=L6<<21;L8=(s8+(1<<20))>>21;s9+=L8;s8-=L8<<21;L10=(s10+(1<<20))>>21;s11+=L10;s10-=L10<<21;L1=(s1+(1<<20))>>21;s2+=L1;s1-=L1<<21;L3=(s3+(1<<20))>>21;s4+=L3;s3-=L3<<21;L5=(s5+(1<<20))>>21;s6+=L5;s5-=L5<<21;L7=(s7+(1<<20))>>21;s8+=L7;s7-=L7<<21;L9=(s9+(1<<20))>>21;s10+=L9;s9-=L9<<21;L11=(s11+(1<<20))>>21;s12+=L11;s11-=L11<<21;s0+=s12*666643;s1+=s12*470296;s2+=s12*654183;s3-=s12*997805;s4+=s12*136657;s5-=s12*683901;s12=0;L0=s0>>21;s1+=L0;s0-=L0<<21;L1=s1>>21;s2+=L1;s1-=L1<<21;L2=s2>>21;s3+=L2;s2-=L2<<21;L3=s3>>21;s4+=L3;s3-=L3<<21;L4=s4>>21;s5+=L4;s4-=L4<<21;L5=s5>>21;s6+=L5;s5-=L5<<21;L6=s6>>21;s7+=L6;s6-=L6<<21;L7=s7>>21;s8+=L7;s7-=L7<<21;L8=s8>>21;s9+=L8;s8-=L8<<21;L9=s9>>21;s10+=L9;s9-=L9<<21;L10=s10>>21;s11+=L10;s10-=L10<<21;L11=s11>>21;s12+=L11;s11-=L11<<21;s0+=s12*666643;s1+=s12*470296;s2+=s12*654183;s3-=s12*997805;s4+=s12*136657;s5-=s12*683901;s12=0;L0=s0>>21;s1+=L0;s0-=L0<<21;L1=s1>>21;s2+=L1;s1-=L1<<21;L2=s2>>21;s3+=L2;s2-=L2<<21;L3=s3>>21;s4+=L3;s3-=L3<<21;L4=s4>>21;s5+=L4;s4-=L4<<21;L5=s5>>21;s6+=L5;s5-=L5<<21;L6=s6>>21;s7+=L6;s6-=L6<<21;L7=s7>>21;s8+=L7;s7-=L7<<21;L8=s8>>21;s9+=L8;s8-=L8<<21;L9=s9>>21;s10+=L9;s9-=L9<<21;L10=s10>>21;s11+=L10;s10-=L10<<21;s[0]=(u8)(s0>>0);s[1]=(u8)(s0>>8);s[2]=(u8)((s0>>16)|(s1<<5));s[3]=(u8)(s1>>3);s[4]=(u8)(s1>>11);s[5]=(u8)((s1>>19)|(s2<<2));s[6]=(u8)(s2>>6);s[7]=(u8)((s2>>14)|(s3<<7));s[8]=(u8)(s3>>1);s[9]=(u8)(s3>>9);s[10]=(u8)((s3>>17)|(s4<<4));s[11]=(u8)(s4>>4);s[12]=(u8)(s4>>12);s[13]=(u8)((s4>>20)|(s5<<1));s[14]=(u8)(s5>>7);s[15]=(u8)((s5>>15)|(s6<<6));s[16]=(u8)(s6>>2);s[17]=(u8)(s6>>10);s[18]=(u8)((s6>>18)|(s7<<3));s[19]=(u8)(s7>>5);s[20]=(u8)(s7>>13);s[21]=(u8)(s8>>0);s[22]=(u8)(s8>>8);s[23]=(u8)((s8>>16)|(s9<<5));s[24]=(u8)(s9>>3);s[25]=(u8)(s9>>11);s[26]=(u8)((s9>>19)|(s10<<2));s[27]=(u8)(s10>>6);s[28]=(u8)((s10>>14)|(s11<<7));s[29]=(u8)(s11>>1);s[30]=(u8)(s11>>9);s[31]=(u8)(s11>>17);}void sc_muladd(u8*s,C u8*a,C u8*b,C u8*c){I a0=2097151 & load_3(a);I a1=2097151 &(load_4(a+2)>>5);I a2=2097151 &(load_3(a+5)>>2);I a3=2097151 &(load_4(a+7)>>7);I a4=2097151 &(load_4(a+10)>>4);I a5=2097151 &(load_3(a+13)>>1);I a6=2097151 &(load_4(a+15)>>6);I a7=2097151 &(load_3(a+18)>>3);I a8=2097151 & load_3(a+21);I a9=2097151 &(load_4(a+23)>>5);I a10=2097151 &(load_3(a+26)>>2);I a11=(load_4(a+28)>>7);I b0=2097151 & load_3(b);I b1=2097151 &(load_4(b+2)>>5);I b2=2097151 &(load_3(b+5)>>2);I b3=2097151 &(load_4(b+7)>>7);I b4=2097151 &(load_4(b+10)>>4);I b5=2097151 &(load_3(b+13)>>1);I b6=2097151 &(load_4(b+15)>>6);I b7=2097151 &(load_3(b+18)>>3);I b8=2097151 & load_3(b+21);I b9=2097151 &(load_4(b+23)>>5);I b10=2097151 &(load_3(b+26)>>2);I b11=(load_4(b+28)>>7);I c0=2097151 & load_3(c);I c1=2097151 &(load_4(c+2)>>5);I c2=2097151 &(load_3(c+5)>>2);I c3=2097151 &(load_4(c+7)>>7);I c4=2097151 &(load_4(c+10)>>4);I c5=2097151 &(load_3(c+13)>>1);I c6=2097151 &(load_4(c+15)>>6);I c7=2097151 &(load_3(c+18)>>3);I c8=2097151 & load_3(c+21);I c9=2097151 &(load_4(c+23)>>5);I c10=2097151 &(load_3(c+26)>>2);I c11=(load_4(c+28)>>7);I s0;I s1;I s2;I s3;I s4;I s5;I s6;I s7;I s8;I s9;I s10;I s11;I s12;I s13;I s14;I s15;I s16;I s17;I s18;I s19;I s20;I s21;I s22;I s23;I L0;I L1;I L2;I L3;I L4;I L5;I L6;I L7;I L8;I L9;I L10;I L11;I L12;I L13;I L14;I L15;I L16;I L17;I L18;I L19;I L20;I L21;I L22;s0=c0+a0*b0;s1=c1+a0*b1+a1*b0;s2=c2+a0*b2+a1*b1+a2*b0;s3=c3+a0*b3+a1*b2+a2*b1+a3*b0;s4=c4+a0*b4+a1*b3+a2*b2+a3*b1+a4*b0;s5=c5+a0*b5+a1*b4+a2*b3+a3*b2+a4*b1+a5*b0;s6=c6+a0*b6+a1*b5+a2*b4+a3*b3+a4*b2+a5*b1+a6*b0;s7=c7+a0*b7+a1*b6+a2*b5+a3*b4+a4*b3+a5*b2+a6*b1+a7*b0;s8=c8+a0*b8+a1*b7+a2*b6+a3*b5+a4*b4+a5*b3+a6*b2+a7*b1+a8*b0;s9=c9+a0*b9+a1*b8+a2*b7+a3*b6+a4*b5+a5*b4+a6*b3+a7*b2+a8*b1+a9*b0;s10=c10+a0*b10+a1*b9+a2*b8+a3*b7+a4*b6+a5*b5+a6*b4+a7*b3+a8*b2+a9*b1+a10*b0;s11=c11+a0*b11+a1*b10+a2*b9+a3*b8+a4*b7+a5*b6+a6*b5+a7*b4+a8*b3+a9*b2+a10*b1+a11*b0;s12=a1*b11+a2*b10+a3*b9+a4*b8+a5*b7+a6*b6+a7*b5+a8*b4+a9*b3+a10*b2+a11*b1;s13=a2*b11+a3*b10+a4*b9+a5*b8+a6*b7+a7*b6+a8*b5+a9*b4+a10*b3+a11*b2;s14=a3*b11+a4*b10+a5*b9+a6*b8+a7*b7+a8*b6+a9*b5+a10*b4+a11*b3;s15=a4*b11+a5*b10+a6*b9+a7*b8+a8*b7+a9*b6+a10*b5+a11*b4;s16=a5*b11+a6*b10+a7*b9+a8*b8+a9*b7+a10*b6+a11*b5;s17=a6*b11+a7*b10+a8*b9+a9*b8+a10*b7+a11*b6;s18=a7*b11+a8*b10+a9*b9+a10*b8+a11*b7;s19=a8*b11+a9*b10+a10*b9+a11*b8;s20=a9*b11+a10*b10+a11*b9;s21=a10*b11+a11*b10;s22=a11*b11;s23=0;L0=(s0+(1<<20))>>21;s1+=L0;s0-=L0<<21;L2=(s2+(1<<20))>>21;s3+=L2;s2-=L2<<21;L4=(s4+(1<<20))>>21;s5+=L4;s4-=L4<<21;L6=(s6+(1<<20))>>21;s7+=L6;s6-=L6<<21;L8=(s8+(1<<20))>>21;s9+=L8;s8-=L8<<21;L10=(s10+(1<<20))>>21;s11+=L10;s10-=L10<<21;L12=(s12+(1<<20))>>21;s13+=L12;s12-=L12<<21;L14=(s14+(1<<20))>>21;s15+=L14;s14-=L14<<21;L16=(s16+(1<<20))>>21;s17+=L16;s16-=L16<<21;L18=(s18+(1<<20))>>21;s19+=L18;s18-=L18<<21;L20=(s20+(1<<20))>>21;s21+=L20;s20-=L20<<21;L22=(s22+(1<<20))>>21;s23+=L22;s22-=L22<<21;L1=(s1+(1<<20))>>21;s2+=L1;s1-=L1<<21;L3=(s3+(1<<20))>>21;s4+=L3;s3-=L3<<21;L5=(s5+(1<<20))>>21;s6+=L5;s5-=L5<<21;L7=(s7+(1<<20))>>21;s8+=L7;s7-=L7<<21;L9=(s9+(1<<20))>>21;s10+=L9;s9-=L9<<21;L11=(s11+(1<<20))>>21;s12+=L11;s11-=L11<<21;L13=(s13+(1<<20))>>21;s14+=L13;s13-=L13<<21;L15=(s15+(1<<20))>>21;s16+=L15;s15-=L15<<21;L17=(s17+(1<<20))>>21;s18+=L17;s17-=L17<<21;L19=(s19+(1<<20))>>21;s20+=L19;s19-=L19<<21;L21=(s21+(1<<20))>>21;s22+=L21;s21-=L21<<21;s11+=s23*666643;s12+=s23*470296;s13+=s23*654183;s14-=s23*997805;s15+=s23*136657;s16-=s23*683901;s23=0;s10+=s22*666643;s11+=s22*470296;s12+=s22*654183;s13-=s22*997805;s14+=s22*136657;s15-=s22*683901;s22=0;s9+=s21*666643;s10+=s21*470296;s11+=s21*654183;s12-=s21*997805;s13+=s21*136657;s14-=s21*683901;s21=0;s8+=s20*666643;s9+=s20*470296;s10+=s20*654183;s11-=s20*997805;s12+=s20*136657;s13-=s20*683901;s20=0;s7+=s19*666643;s8+=s19*470296;s9+=s19*654183;s10-=s19*997805;s11+=s19*136657;s12-=s19*683901;s19=0;s6+=s18*666643;s7+=s18*470296;s8+=s18*654183;s9-=s18*997805;s10+=s18*136657;s11-=s18*683901;s18=0;L6=(s6+(1<<20))>>21;s7+=L6;s6-=L6<<21;L8=(s8+(1<<20))>>21;s9+=L8;s8-=L8<<21;L10=(s10+(1<<20))>>21;s11+=L10;s10-=L10<<21;L12=(s12+(1<<20))>>21;s13+=L12;s12-=L12<<21;L14=(s14+(1<<20))>>21;s15+=L14;s14-=L14<<21;L16=(s16+(1<<20))>>21;s17+=L16;s16-=L16<<21;L7=(s7+(1<<20))>>21;s8+=L7;s7-=L7<<21;L9=(s9+(1<<20))>>21;s10+=L9;s9-=L9<<21;L11=(s11+(1<<20))>>21;s12+=L11;s11-=L11<<21;L13=(s13+(1<<20))>>21;s14+=L13;s13-=L13<<21;L15=(s15+(1<<20))>>21;s16+=L15;s15-=L15<<21;s5+=s17*666643;s6+=s17*470296;s7+=s17*654183;s8-=s17*997805;s9+=s17*136657;s10-=s17*683901;s17=0;s4+=s16*666643;s5+=s16*470296;s6+=s16*654183;s7-=s16*997805;s8+=s16*136657;s9-=s16*683901;s16=0;s3+=s15*666643;s4+=s15*470296;s5+=s15*654183;s6-=s15*997805;s7+=s15*136657;s8-=s15*683901;s15=0;s2+=s14*666643;s3+=s14*470296;s4+=s14*654183;s5-=s14*997805;s6+=s14*136657;s7-=s14*683901;s14=0;s1+=s13*666643;s2+=s13*470296;s3+=s13*654183;s4-=s13*997805;s5+=s13*136657;s6-=s13*683901;s13=0;s0+=s12*666643;s1+=s12*470296;s2+=s12*654183;s3-=s12*997805;s4+=s12*136657;s5-=s12*683901;s12=0;L0=(s0+(1<<20))>>21;s1+=L0;s0-=L0<<21;L2=(s2+(1<<20))>>21;s3+=L2;s2-=L2<<21;L4=(s4+(1<<20))>>21;s5+=L4;s4-=L4<<21;L6=(s6+(1<<20))>>21;s7+=L6;s6-=L6<<21;L8=(s8+(1<<20))>>21;s9+=L8;s8-=L8<<21;L10=(s10+(1<<20))>>21;s11+=L10;s10-=L10<<21;L1=(s1+(1<<20))>>21;s2+=L1;s1-=L1<<21;L3=(s3+(1<<20))>>21;s4+=L3;s3-=L3<<21;L5=(s5+(1<<20))>>21;s6+=L5;s5-=L5<<21;L7=(s7+(1<<20))>>21;s8+=L7;s7-=L7<<21;L9=(s9+(1<<20))>>21;s10+=L9;s9-=L9<<21;L11=(s11+(1<<20))>>21;s12+=L11;s11-=L11<<21;s0+=s12*666643;s1+=s12*470296;s2+=s12*654183;s3-=s12*997805;s4+=s12*136657;s5-=s12*683901;s12=0;L0=s0>>21;s1+=L0;s0-=L0<<21;L1=s1>>21;s2+=L1;s1-=L1<<21;L2=s2>>21;s3+=L2;s2-=L2<<21;L3=s3>>21;s4+=L3;s3-=L3<<21;L4=s4>>21;s5+=L4;s4-=L4<<21;L5=s5>>21;s6+=L5;s5-=L5<<21;L6=s6>>21;s7+=L6;s6-=L6<<21;L7=s7>>21;s8+=L7;s7-=L7<<21;L8=s8>>21;s9+=L8;s8-=L8<<21;L9=s9>>21;s10+=L9;s9-=L9<<21;L10=s10>>21;s11+=L10;s10-=L10<<21;L11=s11>>21;s12+=L11;s11-=L11<<21;s0+=s12*666643;s1+=s12*470296;s2+=s12*654183;s3-=s12*997805;s4+=s12*136657;s5-=s12*683901;s12=0;L0=s0>>21;s1+=L0;s0-=L0<<21;L1=s1>>21;s2+=L1;s1-=L1<<21;L2=s2>>21;s3+=L2;s2-=L2<<21;L3=s3>>21;s4+=L3;s3-=L3<<21;L4=s4>>21;s5+=L4;s4-=L4<<21;L5=s5>>21;s6+=L5;s5-=L5<<21;L6=s6>>21;s7+=L6;s6-=L6<<21;L7=s7>>21;s8+=L7;s7-=L7<<21;L8=s8>>21;s9+=L8;s8-=L8<<21;L9=s9>>21;s10+=L9;s9-=L9<<21;L10=s10>>21;s11+=L10;s10-=L10<<21;s[0]=(u8)(s0>>0);s[1]=(u8)(s0>>8);s[2]=(u8)((s0>>16)|(s1<<5));s[3]=(u8)(s1>>3);s[4]=(u8)(s1>>11);s[5]=(u8)((s1>>19)|(s2<<2));s[6]=(u8)(s2>>6);s[7]=(u8)((s2>>14)|(s3<<7));s[8]=(u8)(s3>>1);s[9]=(u8)(s3>>9);s[10]=(u8)((s3>>17)|(s4<<4));s[11]=(u8)(s4>>4);s[12]=(u8)(s4>>12);s[13]=(u8)((s4>>20)|(s5<<1));s[14]=(u8)(s5>>7);s[15]=(u8)((s5>>15)|(s6<<6));s[16]=(u8)(s6>>2);s[17]=(u8)(s6>>10);s[18]=(u8)((s6>>18)|(s7<<3));s[19]=(u8)(s7>>5);s[20]=(u8)(s7>>13);s[21]=(u8)(s8>>0);s[22]=(u8)(s8>>8);s[23]=(u8)((s8>>16)|(s9<<5));s[24]=(u8)(s9>>3);s[25]=(u8)(s9>>11);s[26]=(u8)((s9>>19)|(s10<<2));s[27]=(u8)(s10>>6);s[28]=(u8)((s10>>14)|(s11<<7));s[29]=(u8)(s11>>1);s[30]=(u8)(s11>>9);s[31]=(u8)(s11>>17);}
#include <stddef.h>
typedef struct sha512_context_{u64 length,state[8];size_t curlen;u8 buf[128];}sha512_context;int sha512_init(sha512_context*md);int sha512_final(sha512_context*md,u8*out);int sha512_update(sha512_context*md,C u8*in,size_t inlen);int sha512(C u8*message,size_t message_len,u8*out);void ed25519_create_keypair(u8*public_key,u8*private_key,C u8*seed){ge_p3 A;sha512(seed,32,private_key);private_key[0] &=248;private_key[31] &=63;private_key[31]|=64;ge_scalarmult_base(&A,private_key);ge_p3_tobytes(public_key,&A);}void ed25519_key_exchange(u8*shared_secret,C u8*public_key,C u8*private_key){u8 e[32];u32 i;fe x1;fe x2;fe z2;fe x3;fe z3;fe tmp0;fe tmp1;int pos;u32 swap;u32 b;for(i=0;i < 32;++i){e[i]=private_key[i];}e[0] &=248;e[31] &=63;e[31]|=64;fe_frombytes(x1,public_key);fe_1(tmp1);fe_add(tmp0,x1,tmp1);fe_sub(tmp1,tmp1,x1);fe_invert(tmp1,tmp1);fe_mul(x1,tmp0,tmp1);fe_1(x2);fe_0(z2);fe_copy(x3,x1);fe_1(z3);swap=0;for(pos=254;pos >=0;--pos){b=e[pos / 8]>>(pos & 7);b &=1;swap^=b;fe_cswap(x2,x3,swap);fe_cswap(z2,z3,swap);swap=b;fe_sub(tmp0,x3,z3);fe_sub(tmp1,x2,z2);fe_add(x2,x2,z2);fe_add(z2,x3,z3);fe_mul(z3,tmp0,x2);fe_mul(z2,z2,tmp1);fe_sq(tmp0,tmp1);fe_sq(tmp1,x2);fe_add(x3,z3,z2);fe_sub(z2,z3,z2);fe_mul(x2,tmp1,tmp0);fe_sub(tmp1,tmp1,tmp0);fe_sq(z2,z2);fe_mul121666(z3,tmp1);fe_sq(x3,x3);fe_add(tmp0,tmp0,z3);fe_mul(z3,x1,z2);fe_mul(z2,tmp1,tmp0);}fe_cswap(x2,x3,swap);fe_cswap(z2,z3,swap);fe_invert(z2,z2);fe_mul(x2,x2,z2);fe_tobytes(shared_secret,x2);}
#include <stdio.h>
int ed25519_create_seed(u8*seed){FILE*f=fopen("/dev/urandom","rb");if(f==0){E 1;}fread(seed,1,32,f);fclose(f);E 0;}void ed25519_sign(u8*signature,C u8*message,size_t message_len,C u8*public_key,C u8*private_key){sha512_context hash;u8 hram[64];u8 r[64];ge_p3 R;sha512_init(&hash);sha512_update(&hash,private_key+32,32);sha512_update(&hash,message,message_len);sha512_final(&hash,r);sc_reduce(r);ge_scalarmult_base(&R,r);ge_p3_tobytes(signature,&R);sha512_init(&hash);sha512_update(&hash,signature,32);sha512_update(&hash,public_key,32);sha512_update(&hash,message,message_len);sha512_final(&hash,hram);sc_reduce(hram);sc_muladd(signature+32,hram,private_key,r);}static int consttime_equal(C u8*x,C u8*y){u8 r=0;r=x[0]^y[0];
#define F(i)r|=x[i]^y[i]
F(1);F(2);F(3);F(4);F(5);F(6);F(7);F(8);F(9);F(10);F(11);F(12);F(13);F(14);F(15);F(16);F(17);F(18);F(19);F(20);F(21);F(22);F(23);F(24);F(25);F(26);F(27);F(28);F(29);F(30);F(31);
#undef F
E !r;}int ed25519_verify(C u8*signature,C u8*message,size_t message_len,C u8*public_key){u8 h[64];u8 checker[32];sha512_context hash;ge_p3 A;ge_p2 R;if(signature[63] & 224){E 0;}if(ge_frombytes_negate_vartime(&A,public_key)!=0){E 0;}sha512_init(&hash);sha512_update(&hash,signature,32);sha512_update(&hash,public_key,32);sha512_update(&hash,message,message_len);sha512_final(&hash,h);sc_reduce(h);ge_double_scalarmult_vartime(&R,h,&A,signature+32);ge_tobytes(checker,&R);if(!consttime_equal(checker,signature)){E 0;}E 1;}
#define Y UINT64_C
static C u64 K[80]={Y(0x428a2f98d728ae22),Y(0x7137449123ef65cd),Y(0xb5c0fbcfec4d3b2f),Y(0xe9b5dba58189dbbc),Y(0x3956c25bf348b538),Y(0x59f111f1b605d019),Y(0x923f82a4af194f9b),Y(0xab1c5ed5da6d8118),Y(0xd807aa98a3030242),Y(0x12835b0145706fbe),Y(0x243185be4ee4b28c),Y(0x550c7dc3d5ffb4e2),Y(0x72be5d74f27b896f),Y(0x80deb1fe3b1696b1),Y(0x9bdc06a725c71235),Y(0xc19bf174cf692694),Y(0xe49b69c19ef14ad2),Y(0xefbe4786384f25e3),Y(0x0fc19dc68b8cd5b5),Y(0x240ca1cc77ac9c65),Y(0x2de92c6f592b0275),Y(0x4a7484aa6ea6e483),Y(0x5cb0a9dcbd41fbd4),Y(0x76f988da831153b5),Y(0x983e5152ee66dfab),Y(0xa831c66d2db43210),Y(0xb00327c898fb213f),Y(0xbf597fc7beef0ee4),Y(0xc6e00bf33da88fc2),Y(0xd5a79147930aa725),Y(0x06ca6351e003826f),Y(0x142929670a0e6e70),Y(0x27b70a8546d22ffc),Y(0x2e1b21385c26c926),Y(0x4d2c6dfc5ac42aed),Y(0x53380d139d95b3df),Y(0x650a73548baf63de),Y(0x766a0abb3c77b2a8),Y(0x81c2c92e47edaee6),Y(0x92722c851482353b),Y(0xa2bfe8a14cf10364),Y(0xa81a664bbc423001),Y(0xc24b8b70d0f89791),Y(0xc76c51a30654be30),Y(0xd192e819d6ef5218),Y(0xd69906245565a910),Y(0xf40e35855771202a),Y(0x106aa07032bbd1b8),Y(0x19a4c116b8d2d0c8),Y(0x1e376c085141ab53),Y(0x2748774cdf8eeb99),Y(0x34b0bcb5e19b48a8),Y(0x391c0cb3c5c95a63),Y(0x4ed8aa4ae3418acb),Y(0x5b9cca4f7763e373),Y(0x682e6ff3d6b2b8a3),Y(0x748f82ee5defb2fc),Y(0x78a5636f43172f60),Y(0x84c87814a1f0ab72),Y(0x8cc702081a6439ec),Y(0x90befffa23631e28),Y(0xa4506cebde82bde9),Y(0xbef9a3f7b2c67915),Y(0xc67178f2e372532b),Y(0xca273eceea26619c),Y(0xd186b8c721c0c207),Y(0xeada7dd6cde0eb1e),Y(0xf57d4f7fee6ed178),Y(0x06f067aa72176fba),Y(0x0a637dc5a2c898a6),Y(0x113f9804bef90dae),Y(0x1b710b35131c471b),Y(0x28db77f523047d84),Y(0x32caab7b40c72493),Y(0x3c9ebe0a15c9bebc),Y(0x431d67c49c100d4c),Y(0x4cc5d4becb3e42b6),Y(0x597f299cfc657e2a),Y(0x5fcb6fab3ad6faec),Y(0x6c44198c4a475817)};
#define ROR64c(x,y)(((((x)&Y(0xFFFFFFFFFFFFFFFF))>>((u64)(y)&Y(63)))|((x)<<((u64)(64-((y)&Y(63))))))& Y(0xFFFFFFFFFFFFFFFF))
#define STORE64H(x,y){(y)[0]=(u8)(((x)>>56)&255);(y)[1]=(u8)(((x)>>48)&255);(y)[2]=(u8)(((x)>>40)&255);(y)[3]=(u8)(((x)>>32)&255);(y)[4]=(u8)(((x)>>24)&255);(y)[5]=(u8)(((x)>>16)&255);(y)[6]=(u8)(((x)>>8)&255);(y)[7]=(u8)((x)&255);}
#define LOAD64H(x,y){x=(((u64)((y)[0] & 255))<<56)|(((u64)((y)[1] & 255))<<48)|(((u64)((y)[2] & 255))<<40)|(((u64)((y)[3] & 255))<<32)|(((u64)((y)[4] & 255))<<24)|(((u64)((y)[5] & 255))<<16)|(((u64)((y)[6] & 255))<<8)|(((u64)((y)[7] & 255)));}
#define Ch(x,y,z)(z^(x &(y^z)))
#define Maj(x,y,z)(((x|y)& z)|(x & y))
#define S(x,n)ROR64c(x,n)
#define R(x,n)(((x)&Y(0xFFFFFFFFFFFFFFFF))>>((u64)n))
#define Sigma0(x)(S(x,28)^S(x,34)^S(x,39))
#define Sigma1(x)(S(x,14)^S(x,18)^S(x,41))
#define Gamma0(x)(S(x,1)^S(x,8)^R(x,7))
#define Gamma1(x)(S(x,19)^S(x,61)^R(x,6))
static int sha512_compress(sha512_context*md,u8*buf){u64 S[8],W[80],t0,t1;int i;for(i=0;i < 8;i++){S[i]=md->state[i];}for(i=0;i < 16;i++){LOAD64H(W[i],buf+(8*i));}for(i=16;i < 80;i++){W[i]=Gamma1(W[i-2])+W[i-7]+Gamma0(W[i-15])+W[i-16];}
#define RND(a,b,c,d,e,f,g,h,i)t0=h+Sigma1(e)+Ch(e,f,g)+K[i]+W[i]; t1=Sigma0(a)+Maj(a,b,c); d+=t0; h=t0+t1;
for(i=0;i < 80;i+=8){RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);}
#undef RND
for(i=0;i < 8;i++){md->state[i]=md->state[i]+S[i];}E 0;}int sha512_init(sha512_context*md){if(md==0)E 1;md->curlen=0;md->length=0;md->state[0]=Y(0x6a09e667f3bcc908);md->state[1]=Y(0xbb67ae8584caa73b);md->state[2]=Y(0x3c6ef372fe94f82b);md->state[3]=Y(0xa54ff53a5f1d36f1);md->state[4]=Y(0x510e527fade682d1);md->state[5]=Y(0x9b05688c2b3e6c1f);md->state[6]=Y(0x1f83d9abfb41bd6b);md->state[7]=Y(0x5be0cd19137e2179);E 0;}int sha512_update(sha512_context*md,C u8*in,size_t inlen){size_t n;size_t i;int err;if(md==0)E 1;if(in==0)E 1;if(md->curlen > sizeof(md->buf)){E 1;}while(inlen > 0){if(md->curlen==0 && inlen >=128){if((err=sha512_compress(md,(u8*)in))!=0){E err;}md->length+=128*8;in+=128;inlen-=128;}else{n=min(inlen,(128-md->curlen));for(i=0;i < n;i++){md->buf[i+md->curlen]=in[i];}md->curlen+=n;in+=n;inlen-=n;if(md->curlen==128){if((err=sha512_compress(md,md->buf))!=0){E err;}md->length+=8*128;md->curlen=0;}}}E 0;}int sha512_final(sha512_context*md,u8*out){int i;if(md==0)E 1;if(out==0)E 1;if(md->curlen >=sizeof(md->buf)){E 1;}md->length+=md->curlen*Y(8);md->buf[md->curlen++]=(u8)0x80;if(md->curlen > 112){while(md->curlen < 128){md->buf[md->curlen++]=(u8)0;}sha512_compress(md,md->buf);md->curlen=0;}while(md->curlen < 120){md->buf[md->curlen++]=(u8)0;}STORE64H(md->length,md->buf+120);sha512_compress(md,md->buf);for(i=0;i < 8;i++){STORE64H(md->state[i],out+(8*i));}E 0;}int sha512(C u8*message,size_t message_len,u8*out){sha512_context ctx;int ret;if((ret=sha512_init(&ctx)))E ret;if((ret=sha512_update(&ctx,message,message_len)))E ret;if((ret=sha512_final(&ctx,out)))E ret;E 0;}
#include <sys/stat.h>
bool file_exists(string& name){struct stat buffer;E(stat(name.c_str(),&buffer)==0);}bool file_save(string& path,u8*buf,u32 len){FILE*fh=fopen(path.c_str(),"wb");if(!fh)E 0;fwrite(buf,1,len,fh);if(ferror(fh))E 0;fclose(fh);if(ferror(fh))E 0;E true;}bool file_load(string& path,u8*buf,u32 len){FILE*fh=fopen(path.c_str(),"rb");if(!fh)E 0;fread(buf,1,len,fh);if(ferror(fh))E 0;fclose(fh);if(ferror(fh))E 0;E true;}bool address_json_parse(Value t,u32 &res){C char*tmp=t.asString().c_str();char*tmp_p;C char*end=tmp+strlen(tmp);res=strtol(tmp,&tmp_p,10);E tmp_p==end;}
#define T_ARR(name,size_)const u32 name##_size=size_; typedef u8 name##_buf[size_]; struct name{u8 b[size_]={0};}; bool operator!=(const name& a,const name& b){return memcmp(a.b,b.b,sizeof(a.b));}bool operator<(const name& a,const name& b){return memcmp(a.b,b.b,sizeof(a.b)<0);}bool operator>(const name& a,const name& b){return memcmp(a.b,b.b,sizeof(a.b)>0);}bool str2##name(const string &str,name &key){const u32 L=2*size_; if(str.size()!=L){return false;}for(int i=0;i<L;i++){char ch=str[i]; if('0' <=ch && ch <='9')continue; if('a' <=ch && ch <='f')continue; if('A' <=ch && ch <='A')continue; return false;}char tmp[3]={0}; char*tmp_p; u32 dst=0; for(int i=0;i<L;){tmp[0]=str[i++]; tmp[1]=str[i++]; key.b[dst++]=strtol((char*)&tmp,&tmp_p,16);}return true;}string name##2str(name &t){string res=""; char buf[10]={0}; for(int i=0;i<name##_size;i++){sprintf(buf,"%02x",t.b[i]); res+=buf;}return res;}void name##_print(const char*prefix_str,name &t){printf("%s%s\n",prefix_str,name##2str(t).c_str());}
T_ARR(t_hash,64)T_ARR(t_sign,64)T_ARR(t_pub_key,32)T_ARR(t_prv_key,64)struct Block_header{u32 id=0;u32 version=0;t_hash prev_hash;t_hash merkle_tree;u32 issuer_addr=0;t_pub_key issuer_pub_key;u32 nonce=0;t_hash hash;t_sign sign;u64 weight=0;};struct Tx{u32 type=0;u32 amount=0;u32 send_addr=0;u32 recv_addr=0;t_pub_key bind_pub_key={0};u32 nonce=0;t_hash hash;t_sign sign;u64 weight=0;};struct Block{struct Block_header header;vector<Tx> tx_list;u64 weight=0;};C u32 tx_fee=10;C u32 mining_reward=10;C u32 hot_potato_penalty=1;string pub_key_path="./pub.key";string prv_key_path="./prv.key";bool i_am_seed_node=0;struct Acc_weight_pair{u32 account;u64 weight;};struct MemState{bool ready=0;u32 target_bc_height=0;u32 main_chain_block_offset=0;vector<Block> main_chain_block_list;vector<Tx> tx_list;bool is_proposal_valid=0;Block proposed_block;unordered_map<string,Tx> done_tx_hash;vector<t_pub_key> a2pk;vector<u32> B;vector<Acc_weight_pair*> w_weak_list;vector<Acc_weight_pair> aw_sort_list;}gms;u32 my_primary_address;t_pub_key my_pub_key;t_prv_key my_prv_key;bool tx_mining_mode=0;void gms_account_new(t_pub_key &pub_key){gms.a2pk.push_back(pub_key);gms.B.push_back(0);gms.w_weak_list.push_back(0);}u32 bc_height(){E gms.main_chain_block_offset+gms.main_chain_block_list.size();}bool key_gen(t_pub_key &pub_key,t_prv_key &prv_key){u8 seed[32];if(ed25519_create_seed(seed)){E 0;}ed25519_create_keypair(pub_key.b,prv_key.b,seed);E true;}u32 RPC_PRV_PORT=10002;u32 RPC_PUB_PORT=10001;string seed_ip_port="http://192.168.2.3:10001";struct NetNode{bool is_self=0;string ip_port;bool is_proposal_valid=0;Block proposed_block;};struct NetState{u32 ask_offset=0;u32 broadcast_offset=0;vector<NetNode> node_list;}gns;void block_broadcast();u64 hash2weight(t_hash &hash){u64 res=0;for(int i=0;i<t_hash_size;i++){u32 loc=__builtin_clz(hash.b[i]);res+=loc;if(loc !=32)break;}E res;}
#define SL1 const int len=(sizeof(u32)+sizeof(u32)+sizeof(t_hash)+sizeof(t_hash)+sizeof(u32)+sizeof(t_pub_key)+sizeof(u32)); u8 buffer[len]; u8*buf_ptr=(u8*)&buffer; u32 s=0; memcpy(buf_ptr,&header.id,s=sizeof(header.id));buf_ptr+=s; memcpy(buf_ptr,&header.version,s=sizeof(header.version));buf_ptr+=s; memcpy(buf_ptr,&header.prev_hash,s=sizeof(header.prev_hash));buf_ptr+=s; memcpy(buf_ptr,&header.merkle_tree,s=sizeof(header.merkle_tree));buf_ptr+=s; memcpy(buf_ptr,&header.issuer_addr,s=sizeof(header.issuer_addr));buf_ptr+=s; memcpy(buf_ptr,&header.issuer_pub_key.b,s=sizeof(header.issuer_pub_key.b));buf_ptr+=s; memcpy(buf_ptr,&header.nonce,s=sizeof(header.nonce));/*buf_ptr+=s;*/ sha512_context ctx; sha512_init(&ctx); sha512_update(&ctx,(u8*)&buffer,len);
void block_header_sign(Block_header &header,t_pub_key &pub_key,t_prv_key &prv_key){SL1
sha512_final(&ctx,(u8*)&header.hash);ed25519_sign(header.sign.b,(u8*)&buffer,len,pub_key.b,prv_key.b);}bool block_header_validate(Block_header &header){if(gms.main_chain_block_list.size()){if(header.id-1 !=gms.main_chain_block_list.back().header.id)E 0;}if(header.issuer_addr >=gms.a2pk.size())E 0;if(header.issuer_pub_key !=gms.a2pk[header.issuer_addr])E 0;SL1
t_hash cmp_hash;sha512_final(&ctx,(u8*)&cmp_hash);if(cmp_hash !=header.hash)E 0;E ed25519_verify(header.sign.b,(u8*)&buffer,len,header.issuer_pub_key.b);}void block_header_to_json(Block_header &header,Value &value){value["id"]=header.id;value["version"]=header.version;value["prev_hash"]=t_hash2str(header.prev_hash);value["merkle_tree"]=t_hash2str(header.merkle_tree);value["issuer_addr"]=header.issuer_addr;value["issuer_pub_key"]=t_pub_key2str(header.issuer_pub_key);value["nonce"]=header.nonce;value["hash"]=t_hash2str(header.hash);value["sign"]=t_sign2str(header.sign);value["weight"]=header.weight;}bool json_to_block_header(C Value &value,Block_header &header){bool res=true;header.id=value["id"].asInt();header.version=value["version"].asInt();res &=str2t_hash(value["prev_hash" ].asString(),header.prev_hash);res &=str2t_hash(value["merkle_tree"].asString(),header.merkle_tree);header.issuer_addr=value["issuer_addr"].asInt();res &=str2t_pub_key(value["issuer_pub_key"].asString(),header.issuer_pub_key);header.nonce=value["nonce"].asInt();res &=str2t_hash(value["hash" ].asString(),header.hash);res &=str2t_sign(value["sign" ].asString(),header.sign);header.weight=value["weight"].asInt();E res;}
#define SL2 const int len=(sizeof(u32)+sizeof(u32)+sizeof(u32)+sizeof(u32)+sizeof(u32)); u8 buffer[len]; u8*buf_ptr=(u8*)&buffer; u32 s=0; memcpy(buf_ptr,&tx.type,s=sizeof(u32));buf_ptr+=s; memcpy(buf_ptr,&tx.amount,s=sizeof(u32));buf_ptr+=s; memcpy(buf_ptr,&tx.send_addr,s=sizeof(u32));buf_ptr+=s; memcpy(buf_ptr,&tx.recv_addr,s=sizeof(u32));buf_ptr+=s; memcpy(buf_ptr,&tx.bind_pub_key.b,s=sizeof(t_pub_key_size));buf_ptr+=s; memcpy(buf_ptr,&tx.nonce,s=sizeof(u32));/*buf_ptr+=s;*/ sha512_context ctx; sha512_init(&ctx); sha512_update(&ctx,(u8*)&buffer,len);
void tx_sign(Tx &tx,t_pub_key &pub_key,t_prv_key &prv_key){SL2
sha512_final(&ctx,(u8*)&tx.hash);ed25519_sign(tx.sign.b,(u8*)&buffer,len,pub_key.b,prv_key.b);}int tx_validate_reason=0;
#define RET(x){tx_validate_reason=x;return false;}
bool tx_validate(Tx &tx){int L=gms.a2pk.size();if(tx.send_addr >=L)RET(1)if(tx.recv_addr >=L)RET(2)auto send_pub_key=gms.a2pk[tx.send_addr];switch(tx.type){case 1:// transfer
if(gms.B[tx.send_addr] < max(tx.amount,tx.amount+tx_fee))RET(10)break;case 2:// address_transfer
if(gms.B[tx.send_addr] < tx_fee)RET(20)if(tx.recv_addr >=L)RET(21)if(send_pub_key !=gms.a2pk[tx.recv_addr])RET(22)break;default:RET(30)}SL2
t_hash cmp_hash;sha512_final(&ctx,(u8*)&cmp_hash);if(cmp_hash !=tx.hash)RET(3)if(gms.done_tx_hash.find(string((char*)&tx.hash.b))!=gms.done_tx_hash.end())RET(4)if(!ed25519_verify(tx.sign.b,(u8*)&buffer,len,send_pub_key.b))RET(5)E true;}void tx_apply(Tx &tx){switch(tx.type){case 1:// transfer
gms.B[tx.send_addr]-=tx.amount+tx_fee;gms.B[tx.recv_addr]+=tx.amount;break;case 2:// address_transfer
gms.B[tx.send_addr]-=tx_fee;gms.a2pk[tx.recv_addr]=tx.bind_pub_key;break;}gms.done_tx_hash[string((char*)&tx.hash.b)]=tx;}void tx_to_json(Tx &tx,Value &value){value["type"]=tx.type;value["amount"]=tx.amount;value["send_addr"]=tx.send_addr;value["recv_addr"]=tx.recv_addr;value["bind_pub_key"]=t_pub_key2str(tx.bind_pub_key);value["nonce"]=tx.nonce;}bool json_to_tx(C Value &value,Tx &tx){bool res=true;tx.type=value["type"].asInt();tx.amount=value["amount"].asInt();tx.send_addr=value["send_addr"].asInt();tx.recv_addr=value["recv_addr"].asInt();res &=str2t_pub_key(value["bind_pub_key"].asString(),tx.bind_pub_key);tx.nonce=value["nonce"].asInt();E res;}void merkle_tree_calc(vector<Tx> &tx_list,t_hash &res){memset(res.b,0,sizeof(t_hash));FOR_COL(it,tx_list){sha512_context ctx;sha512_init(&ctx);sha512_update(&ctx,res.b,sizeof(res.b));sha512_update(&ctx,it->sign.b,sizeof(res.b));sha512_final(&ctx,(u8*)&res.b);}}bool block_validate(Block &block){block_header_validate(block.header);FOR_COL(it,block.tx_list){if(!tx_validate(*it))E 0;}t_hash merkle_tree;merkle_tree_calc(block.tx_list,merkle_tree);if(merkle_tree !=block.header.merkle_tree)E 0;E true;}void block_sign(Block &block,t_pub_key &pub_key,t_prv_key &prv_key){merkle_tree_calc(block.tx_list,block.header.merkle_tree);block_header_sign(block.header,pub_key,prv_key);}void block_apply(Block &block){FOR_COL(it,block.tx_list){tx_apply(*it);}gms.B[block.header.issuer_addr]+=mining_reward+tx_fee*block.tx_list.size();FOR_COL(it,gms.B){if(*it==0)continue;// do not write optimisation
if(*it > hot_potato_penalty){*it-=hot_potato_penalty;}else{*it=0;}}gms_account_new(block.header.issuer_pub_key);gms.main_chain_block_list.push_back(block);FOR_COL(it,gns.node_list){it->is_proposal_valid=0;}}void block_weight_calc(Block &block){u32 weight=0;FOR_COL(it,block.tx_list){weight+=it->weight=hash2weight(it->hash);}weight+=block.header.weight=hash2weight(block.header.hash);block.weight=weight;}void block_to_json(Block &block,Value &value){Value header;block_header_to_json(block.header,header);Value tx_list;FOR_COL(it,block.tx_list){Value tx;tx_to_json(*it,tx);tx_list.append(tx);}value["header"]=header;value["tx_list"]=tx_list;value["weight"]=block.weight;}bool json_to_block(C Value &value,Block &block){bool res=true;res &=json_to_block_header(value["header"],block.header);Value tx_list=value["tx_list"];u32 i=0,len=tx_list.size();block.tx_list.resize(len);for(;i<len;i++){res &=json_to_tx(tx_list[i],block.tx_list[i]);}block.weight=value["weight"].asInt();E res;}int block_pack_size(Block &block){int res=0;E res;}void block_pack(Block &block){}void block_unpack(Block &block){}void gms_init(){gms_account_new(my_pub_key);gms.B[0]=1e6;Block block;block.header.id=0;block.header.version=1;block.header.issuer_addr=0;block.header.issuer_pub_key=my_pub_key;block.header.nonce=0;block_sign(block,my_pub_key,my_prv_key);block_weight_calc(block);if(!block_validate(block)){throw new Exception("block validation failed for our own block");}block_apply(block);gms.ready=true;}void proposed_block_replace(Block &block){if(!gms.is_proposal_valid||gms.proposed_block.header.hash > block.header.hash){gms.is_proposal_valid=true;gms.proposed_block=block;block_broadcast();}}void block_propose(){if(!gms.ready)E;auto last=gms.main_chain_block_list.back();Block block;block.header.id=last.header.id+1;block.header.version=1;block.header.prev_hash=last.header.hash;block.header.issuer_addr=my_primary_address;block.header.issuer_pub_key=my_pub_key;block.header.nonce=0;block.tx_list=gms.tx_list;gms.tx_list.clear();block_sign(block,my_pub_key,my_prv_key);block_weight_calc(block);if(!block_validate(block)){throw new Exception("block validation failed for our own block");}proposed_block_replace(block);}void rpc_bc_height(C Value &rq,Value &rs){rs=bc_height();}void rpc_get_node_list(C Value &rq,Value &rs){FOR_COL(it,gns.node_list){Value node;node["is_self"]=it->is_self;node["ip_port"]=it->ip_port;rs.append(node);}}void rpc_get_block_number(C Value &rq,Value &rs){I id=rq["id"].asInt();if(id < 0){rs="fail";E;}if(id >=gms.main_chain_block_list.size()){rs="fail";E;}block_to_json(gms.main_chain_block_list[id],rs);}void rpc_tx_push(C Value &rq,Value &rs){Tx tx;tx.type=rq["type"].asInt();tx.amount=rq["amount"].asInt();if(!address_json_parse(rq["send_addr"],tx.send_addr)){rs="fail";E;}if(!address_json_parse(rq["recv_addr"],tx.recv_addr)){rs="fail";E;}if(!str2t_pub_key(rq["bind_pub_key"].asString(),tx.bind_pub_key)){rs="fail";E;}tx.nonce=rq["nonce"].asInt();if(!str2t_hash(rq["hash"].asString(),tx.hash)){rs="fail";E;}if(!str2t_sign(rq["sign"].asString(),tx.sign)){rs="fail";E;}if(!tx_validate(tx)){rs="fail";E;}gms.tx_list.push_back(tx);}class LS:public AbstractServer<LS>{public:bool work=true;LS(ASC &c,sVt type=JSONRPC_SERVER_V2):AbstractServer<LS>(c,type){bM(Procedure("bc_height",PARAMS_BY_NAME,JSON_INTEGER,0),&LS::bc_heightI);bM(Procedure("get_node_list",PARAMS_BY_NAME,JSON_ARRAY,0),&LS::get_node_listI);bM(Procedure("get_balance",PARAMS_BY_NAME,JSON_INTEGER,"address",JS,0),&LS::B);bM(Procedure("transfer",PARAMS_BY_NAME,JS,"amount",JSON_INTEGER,"from_address",JS,"to_address",JS,0),&LS::transferI);bM(Procedure("address_transfer",PARAMS_BY_NAME,JS,"address",JS,"pub_key",JS,0),&LS::address_transferI);bM(Procedure("shutdown",PARAMS_BY_NAME,JS,0),&LS::shutdownI);bM(Procedure("set_tx_mining_mode",PARAMS_BY_NAME,JS,"enabled",JSON_INTEGER,0),&LS::set_tx_mining_modeI);bM(Procedure("get_tx_mining_mode",PARAMS_BY_NAME,JSON_INTEGER,0),&LS::get_tx_mining_modeI);bM(Procedure("get_my_weight",PARAMS_BY_NAME,JSON_INTEGER,0),&LS::get_my_weightI);bM(Procedure("debug_set_key",PARAMS_BY_NAME,JS,"address",JS,"pub_key",JS,"prv_key",JS,0),&LS::debug_set_keyI);bM(Procedure("debug_key_gen",PARAMS_BY_NAME,JS,0),&LS::debug_key_genI);}void bc_heightI(C Value &rq,Value &rs){rpc_bc_height(rq,rs);}void get_node_listI(C Value &rq,Value &rs){rpc_get_node_list(rq,rs);}void B(C Value &rq,Value &rs){u32 A;if(!address_json_parse(rq["address"],A)){rs=0;E;}if(A >=gms.B.size()){rs=0;E;}rs=gms.B[A];}void shutdownI(C Value &rq,Value &rs){printf("shutdown scheduled\n");work=0;rs="ok";}void set_tx_mining_modeI(C Value &rq,Value &rs){tx_mining_mode=rq["enabled"].asInt();rs="ok";}void get_tx_mining_modeI(C Value &rq,Value &rs){rs=tx_mining_mode;}void get_my_weightI(C Value &rq,Value &rs){FOR_COL(it,gms.aw_sort_list){if(it->account==my_primary_address){rs=it->weight;E;}}rs=0;}void transferI(C Value &rq,Value &rs){u32 amount=rq["amount"].asInt();u32 fA;if(!address_json_parse(rq["from_address"],fA)){rs="fail";E;}if(fA >=gms.B.size()){rs="fail";E;}u32 tA;if(!address_json_parse(rq["to_address"],tA)){rs="fail";E;}if(tA >=gms.B.size()){rs="fail";E;}if(gms.a2pk[fA] !=my_pub_key){rs="fail";E;}if(gms.B[fA] < max(amount,amount+tx_fee)){rs="fail";E;}Tx tx;tx.type=1;tx.amount=amount;tx.send_addr=fA;tx.recv_addr=tA;tx.nonce=0;tx_sign(tx,my_pub_key,my_prv_key);if(!tx_validate(tx)){printf("tx_validate_reason=%d\n",tx_validate_reason);rs="fail";E;}printf("tx transfer %d coin %d-> %d\n",amount,fA,tA);gms.tx_list.push_back(tx);rs="ok";}void address_transferI(C Value &rq,Value &rs){u32 A;if(!address_json_parse(rq["address"],A)){rs="fail";E;}if(A >=gms.a2pk.size()){rs="fail";E;}if(gms.a2pk[A] !=my_pub_key){printf("you don't own address %d\n",A);t_pub_key_print("my_pub_key=",my_pub_key);t_pub_key_print("gms.a2pk[address]=",gms.a2pk[A]);rs="fail";E;}string hex_pub_key=rq["pub_key"].asString();if(hex_pub_key.size()!=2*t_pub_key_size){rs="fail";E;}for(int i=0;i<2*t_pub_key_size;i++){char ch=hex_pub_key[i];if('0' <=ch && ch <='9')continue;if('a' <=ch && ch <='f')continue;if('A' <=ch && ch <='A')continue;rs="fail";E;}Tx tx;tx.type=2;tx.amount=0;tx.send_addr=my_primary_address;tx.recv_addr=A;str2t_pub_key(hex_pub_key,tx.bind_pub_key);tx.nonce=0;tx_sign(tx,my_pub_key,my_prv_key);if(!tx_validate(tx)){printf("tx_validate_reason=%d\n",tx_validate_reason);rs="fail";E;}printf("address transfer owner=%d address=%d pub_key=%s\n",my_primary_address,A,hex_pub_key.c_str());gms.tx_list.push_back(tx);rs="ok";}void debug_set_keyI(C Value &rq,Value &rs){u32 A;if(!address_json_parse(rq["address"],A)){rs="fail";E;}if(A >=gms.B.size()){rs="fail";E;}string hex_pub_key=rq["pub_key"].asString();if(hex_pub_key.size()!=2*t_pub_key_size){rs="fail";E;}for(int i=0;i<2*t_pub_key_size;i++){char ch=hex_pub_key[i];if('0' <=ch && ch <='9')continue;if('a' <=ch && ch <='f')continue;if('A' <=ch && ch <='A')continue;rs="fail";E;}string hex_prv_key=rq["prv_key"].asString();if(hex_prv_key.size()!=2*t_prv_key_size){rs="fail";E;}for(int i=0;i<2*t_prv_key_size;i++){char ch=hex_prv_key[i];if('0' <=ch && ch <='9')continue;if('a' <=ch && ch <='f')continue;if('A' <=ch && ch <='A')continue;rs="fail";E;}t_pub_key pub_key;t_prv_key prv_key;str2t_pub_key(hex_pub_key,pub_key);str2t_prv_key(hex_prv_key,prv_key);if(gms.a2pk[A] !=pub_key){printf("debug_set_keyI %d\n",A);t_pub_key_print("pub_key=",pub_key);t_pub_key_print("gms.a2pk[address]=",gms.a2pk[A]);rs="fail";E;}my_primary_address=A;my_pub_key=pub_key;my_prv_key=prv_key;t_pub_key_print("my_pub_key=",my_pub_key);t_prv_key_print("my_prv_key=",my_prv_key);rs="ok";}void debug_key_genI(C Value &rq,Value &rs){t_pub_key pub_key;t_prv_key prv_key;if(!key_gen(pub_key,prv_key)){rs="fail";E;}t_pub_key_print("pub_key=",pub_key);t_prv_key_print("prv_key=",prv_key);rs["pub_key"]=t_pub_key2str(pub_key);rs["prv_key"]=t_prv_key2str(prv_key);}};class GS:public AbstractServer<GS>{public:bool work=true;GS(ASC &c,sVt type=JSONRPC_SERVER_V2):AbstractServer<GS>(c,type){bM(Procedure("bc_height",PARAMS_BY_NAME,JSON_INTEGER,0),&GS::bc_heightI);bM(Procedure("get_node_list",PARAMS_BY_NAME,JSON_ARRAY,0),&GS::get_node_listI);bM(Procedure("get_block_number",PARAMS_BY_NAME,JSON_OBJECT,0),&GS::get_block_numberI);bM(Procedure("tx_push",PARAMS_BY_NAME,JSON_OBJECT,"type",JSON_INTEGER,"amount",JSON_INTEGER,"send_addr",JS,"recv_addr",JS,"bind_pub_key",JS,"tx_epoch",JSON_INTEGER,"nonce",JSON_INTEGER,"hash",JS,"sign",JS,0),&GS::tx_pushI);bM(Procedure("handshake",PARAMS_BY_NAME,JS,"rev_ip_port",JS,0),&GS::handshakeI);bM(Procedure("get_proposed_block",PARAMS_BY_NAME,JSON_OBJECT,0),&GS::get_proposed_blockI);bM(Procedure("proposed_block_push",PARAMS_BY_NAME,JS,"header",JSON_OBJECT,"tx_list",JSON_ARRAY,"hash",JS,"sign",JS,0),&GS::proposed_block_pushI);bM(Procedure("get_balance",PARAMS_BY_NAME,JSON_INTEGER,"address",JS,0),&GS::B);bM(Procedure("transfer",PARAMS_BY_NAME,JS,"amount",JSON_INTEGER,"from_address",JS,"to_address",JS,0),&GS::transferI);bM(Procedure("address_transfer",PARAMS_BY_NAME,JS,"address",JS,"pub_key",JS,0),&GS::address_transferI);}void bc_heightI(C Value &rq,Value &rs){rpc_bc_height(rq,rs);}void get_node_listI(C Value &rq,Value &rs){rpc_get_node_list(rq,rs);}void get_block_numberI(C Value &rq,Value &rs){rpc_get_block_number(rq,rs);}void tx_pushI(C Value &rq,Value &rs){rpc_tx_push(rq,rs);}void handshakeI(C Value &rq,Value &rs){string rev_ip_port=rq["rev_ip_port"].asString();if(rev_ip_port.size()> 100){rs="fail";E;}auto end=gns.node_list.end();bool found=0;FOR_COL(it,gns.node_list){if(it->ip_port==rev_ip_port){found=true;break;}}if(!found){NetNode node;node.ip_port=rev_ip_port;gns.node_list.push_back(node);}rs="ok";}void get_proposed_blockI(C Value &rq,Value &rs){block_to_json(gms.proposed_block,rs);}void proposed_block_pushI(C Value &rq,Value &rs){Block block;if(!json_to_block(rq,block)){rs="fail";E;}proposed_block_replace(block);rs="ok";}void B(C Value &rq,Value &rs){u32 A;if(!address_json_parse(rq["address"],A)){rs=0;E;}if(A >=gms.B.size()){rs=0;E;}rs=gms.B[A];}void transferI(C Value &rq,Value &rs){u32 amount=rq["amount"].asInt();u32 fA;if(!address_json_parse(rq["from_address"],fA)){rs="fail";E;}if(fA >=gms.B.size()){rs="fail";E;}u32 tA;if(!address_json_parse(rq["to_address"],tA)){rs="fail";E;}if(tA >=gms.B.size()){rs="fail";E;}if(gms.a2pk[fA] !=my_pub_key){rs="fail";E;}if(gms.B[fA] < max(amount,amount+tx_fee)){rs="fail";E;}Tx tx;tx.type=1;tx.amount=amount;tx.send_addr=fA;tx.recv_addr=tA;tx.nonce=0;tx_sign(tx,my_pub_key,my_prv_key);if(!tx_validate(tx)){printf("tx_validate_reason=%d\n",tx_validate_reason);rs="fail";E;}printf("tx transfer %d coin %d-> %d\n",amount,fA,tA);gms.tx_list.push_back(tx);rs="ok";}void address_transferI(C Value &rq,Value &rs){u32 A;if(!address_json_parse(rq["address"],A)){rs="fail";E;}if(A >=gms.a2pk.size()){rs="fail";E;}if(gms.a2pk[A] !=my_pub_key){printf("you don't own address %d\n",A);t_pub_key_print("my_pub_key=",my_pub_key);t_pub_key_print("gms.a2pk[address]=",gms.a2pk[A]);rs="fail";E;}Tx tx;tx.type=2;tx.amount=0;tx.send_addr=my_primary_address;tx.recv_addr=A;string pub_key=rq["pub_key"].asString();if(!str2t_pub_key(pub_key,tx.bind_pub_key)){rs="fail";E;}tx.nonce=0;tx_sign(tx,my_pub_key,my_prv_key);if(!tx_validate(tx)){printf("tx_validate_reason=%d\n",tx_validate_reason);rs="fail";E;}printf("address transfer owner=%d address=%d pub_key=%s\n",my_primary_address,A,pub_key.c_str());gms.tx_list.push_back(tx);rs="ok";}};
#define throw(...)
#include <jsonrpccpp/client.h>
#include <jsonrpccpp/client/connectors/httpclient.h>
#undef throw
u32 pseudo_broadcast_limit=1;// DEBUG
void net_ask_con(NetNode &node){try{HttpClient c1(node.ip_port);Client c(c1);Value params;params["rev_ip_port"]=gns.node_list[0].ip_port;c.CallMethod("handshake",params);Value res=c.CallMethod("get_node_list",nullValue);for(u32 i=0,len=res.size();i<len;i++){NetNode node;Value val=res[i];node.ip_port=val["ip_port"].asString();bool found=0;FOR_COL(it,gns.node_list){if(it->ip_port==node.ip_port){found=true;break;}}if(!found){gns.node_list.push_back(node);}}u32 remote_bc_height=c.CallMethod("bc_height",nullValue).asInt();u32 bh=bc_height();u32 limit=40;if(!gms.ready && remote_bc_height==bh){gms.ready=true;}else{while(remote_bc_height > bh && limit--){gms.target_bc_height=remote_bc_height;Value param;param["id"]=bh;Value json_block=c.CallMethod("get_block_number",param);Block tmp;if(!json_to_block(json_block,tmp))E;if(!block_validate(tmp))E;if(bh==0){gms_account_new(tmp.header.issuer_pub_key);gms.B[0]=1e6;}block_apply(tmp);bh++;}E;}{Value json_block=c.CallMethod("get_proposed_block",nullValue);Block tmp;if(!json_to_block(json_block,tmp)){node.is_proposal_valid=0;E;}node.is_proposal_valid=block_validate(tmp);if(!node.is_proposal_valid){E;}proposed_block_replace(tmp);}}catch(...){}}void net_broadcast_con(NetNode &node){try{HttpClient c1(node.ip_port);Client c(c1);Value json_block;c.CallMethod("block_push",json_block);}catch(...){}}void block_broadcast(){for(int i=0;i<pseudo_broadcast_limit;i++){gns.broadcast_offset=(gns.broadcast_offset+1)%gns.node_list.size();u32 idx=0;FOR_COL(it,gns.node_list){if(it->is_self)continue;if(idx++==gns.broadcast_offset){net_broadcast_con(*it);break;}}}}void net_tick(){for(int i=0;i<pseudo_broadcast_limit;i++){gns.ask_offset=(gns.ask_offset+1)%gns.node_list.size();u32 idx=0;FOR_COL(it,gns.node_list){if(it->is_self)continue;if(idx++==gns.ask_offset){net_ask_con(*it);break;}}}}int main(int argc,char**argv){LOOKT_write_lookup_table_to_flash();int option_index=0;static struct option long_options[]={{"rpc_pub_port",1,0,0},{"rpc_prv_port",1,0,0},{"seed_ip_port",1,0,0},{"pub_key_path",1,0,0},{"prv_key_path",1,0,0},{"drop_keys",0,0,0},{0,0,0,0}};bool drop_keys=0;while(1){int c=getopt_long(argc,argv,"",long_options,&option_index);if(c==-1)break;switch(option_index){case 0:RPC_PUB_PORT=atoi(optarg);break;case 1:RPC_PRV_PORT=atoi(optarg);break;case 2:seed_ip_port=optarg;break;case 3:pub_key_path=optarg;break;case 4:prv_key_path=optarg;break;case 5:drop_keys=true;break;}}if(drop_keys){printf("drop keys\n");remove(pub_key_path.c_str());remove(prv_key_path.c_str());}{struct ifaddrs*ifAddrStruct=0;struct ifaddrs*ifa=0;void*tmpAddrPtr=0;getifaddrs(&ifAddrStruct);for(ifa=ifAddrStruct;ifa !=0;ifa=ifa->ifa_next){if(!ifa->ifa_addr){continue;}if(ifa->ifa_addr->sa_family==AF_INET){// check it is IP4
tmpAddrPtr=&((struct sockaddr_in*)ifa->ifa_addr)->sin_addr;char addressBuffer[INET_ADDRSTRLEN];inet_ntop(AF_INET,tmpAddrPtr,addressBuffer,INET_ADDRSTRLEN);if(!strcmp(addressBuffer,"127.0.0.1"))continue;printf("%s IP Address %s\n",ifa->ifa_name,addressBuffer);string addr_port="http://";addr_port+=addressBuffer;addr_port+=":";addr_port+=to_string(RPC_PUB_PORT);NetNode node;node.is_self=true;node.ip_port=addr_port;gns.node_list.push_back(node);}}if(ifAddrStruct!=0)freeifaddrs(ifAddrStruct);}FOR_COL(it,gns.node_list){if(it->ip_port==seed_ip_port){i_am_seed_node=true;}}bool pub_exists=file_exists(pub_key_path);bool prv_exists=file_exists(prv_key_path);if(pub_exists && prv_exists){printf("load keys\n");if(!file_load(pub_key_path,my_pub_key.b,t_pub_key_size)){printf("failed to load pub key\n");E 1;}if(!file_load(prv_key_path,my_prv_key.b,t_prv_key_size)){printf("failed to load prv key\n");E 1;}}else if(!pub_exists && !prv_exists){printf("generate keys\n");if(!key_gen(my_pub_key,my_prv_key)){printf("error while generating keypair");E 1;}printf("save keys\n");if(!file_save(pub_key_path,my_pub_key.b,t_pub_key_size)){printf("failed to save pub key\n");E 1;}if(!file_save(prv_key_path,my_prv_key.b,t_prv_key_size)){printf("failed to save prv key\n");E 1;}}else{printf("invalid situation\n");printf("pub_key %s\n",pub_exists?"present":"missing");printf("prv_key %s\n",prv_exists?"present":"missing");E 1;}if(i_am_seed_node){gms_init();}else{NetNode node;node.ip_port=seed_ip_port;gns.node_list.push_back(node);}HttpServer hs1(RPC_PRV_PORT);LS s1(hs1,JSONRPC_SERVER_V1V2);HttpServer hs2(RPC_PUB_PORT);GS s2(hs2,JSONRPC_SERVER_V1V2);s1.StartListening();s2.StartListening();printf("pub server port %d\n",RPC_PUB_PORT);printf("prv server port %d\n",RPC_PRV_PORT);printf("seed_ip_port___ %s\n",seed_ip_port.c_str());printf("i_am_seed_node_ %d\n",i_am_seed_node);printf("welcome to UTON HACK!\n");u32 last_bc=0;while(s1.work){net_tick();if(!gms.ready){u32 new_bc=bc_height();if(last_bc==new_bc){this_thread::sleep_for(chrono::milliseconds(1000));}else{last_bc=new_bc;this_thread::sleep_for(chrono::milliseconds(1));}printf("node is not ready bc_height=%d / %d\n",bc_height(),gms.target_bc_height);}else{block_propose();for(int i=0;i<5;i++){net_tick();this_thread::sleep_for(chrono::milliseconds(20));}printf("new block %d\n",gms.proposed_block.header.id);if(!gms.is_proposal_valid){throw new Exception("bad assert gms.is_proposal_valid");}block_apply(gms.proposed_block);gms.is_proposal_valid=0;}}s1.StopListening();s2.StopListening();E 0;}