ETH Price: $4,669.59 (-0.93%)
Gas: 0.13 Gwei

Input Data Messages (IDM)

Decentralized communication on Ethereum.

Filter by:
More than 100,000 found
Age:90D
#include <stdio.h>
#include <string.h>
#include <time.h>

#define STORAGE_FILE "data.bin"
#define STORAGE_DIR "/var/lib/resilience"

char storage_path[1024];

/*
* FIPS 180-2 SHA-224/256/384/512 implementation
* Last update: 02/02/2007
* Issue date: 04/30/2005
*
* Copyright (C) 2013, Con Kolivas <[email protected]>
* Copyright (C) 2005, 2007 Olivier Gay <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/

#include <stdint.h>

#define SHA256_DIGEST_SIZE ( 256 / 8)
#define SHA256_BLOCK_SIZE ( 512 / 8)

#define SHFR(x, n) (x >> n)
#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
#define CH(x, y, z) ((x & y) ^ (~x & z))
#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))

#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))

typedef struct {
unsigned int tot_len;
unsigned int len;
unsigned char block[2 * SHA256_BLOCK_SIZE];
uint32_t h[8];
} sha256_ctx;

#define UNPACK32(x, str) \
{ \
*((str) + 3) = (uint8_t) ((x) ); \
*((str) + 2) = (uint8_t) ((x) >> 8); \
*((str) + 1) = (uint8_t) ((x) >> 16); \
*((str) + 0) = (uint8_t) ((x) >> 24); \
}

#define PACK32(str, x) \
{ \
*(x) = ((uint32_t) *((str) + 3) ) \
| ((uint32_t) *((str) + 2) << 8) \
| ((uint32_t) *((str) + 1) << 16) \
| ((uint32_t) *((str) + 0) << 24); \
}

#define SHA256_SCR(i) \
{ \
w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
+ SHA256_F3(w[i - 15]) + w[i - 16]; \
}

uint32_t sha256_h0[8] =
{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};

uint32_t sha256_k[64] =
{0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};

/* SHA-256 functions */

void sha256_transf(sha256_ctx *ctx, const unsigned char *message,
unsigned int block_nb)
{
uint32_t w[64];
uint32_t wv[8];
uint32_t t1, t2;
const unsigned char *sub_block;
int i;

int j;

for (i = 0; i < (int) block_nb; i++) {
sub_block = message + (i << 6);

for (j = 0; j < 16; j++) {
PACK32(&sub_block[j << 2], &w[j]);
}

for (j = 16; j < 64; j++) {
SHA256_SCR(j);
}

for (j = 0; j < 8; j++) {
wv[j] = ctx->h[j];
}

for (j = 0; j < 64; j++) {
t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
+ sha256_k[j] + w[j];
t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
wv[7] = wv[6];
wv[6] = wv[5];
wv[5] = wv[4];
wv[4] = wv[3] + t1;
wv[3] = wv[2];
wv[2] = wv[1];
wv[1] = wv[0];
wv[0] = t1 + t2;
}

for (j = 0; j < 8; j++) {
ctx->h[j] += wv[j];
}
}
}

void sha256_init(sha256_ctx *ctx)
{
int i;
for (i = 0; i < 8; i++) {
ctx->h[i] = sha256_h0[i];
}

ctx->len = 0;
ctx->tot_len = 0;
}

void sha256_update(sha256_ctx *ctx, const unsigned char *message,
unsigned int len)
{
unsigned int block_nb;
unsigned int new_len, rem_len, tmp_len;
const unsigned char *shifted_message;

tmp_len = SHA256_BLOCK_SIZE - ctx->len;
rem_len = len < tmp_len ? len : tmp_len;

memcpy(&ctx->block[ctx->len], message, rem_len);

if (ctx->len + len < SHA256_BLOCK_SIZE) {
ctx->len += len;
return;
}

new_len = len - rem_len;
block_nb = new_len / SHA256_BLOCK_SIZE;

shifted_message = message + rem_len;

sha256_transf(ctx, ctx->block, 1);
sha256_transf(ctx, shifted_message, block_nb);

rem_len = new_len % SHA256_BLOCK_SIZE;

memcpy(ctx->block, &shifted_message[block_nb << 6],
rem_len);

ctx->len = rem_len;
ctx->tot_len += (block_nb + 1) << 6;
}

void sha256_final(sha256_ctx *ctx, unsigned char *digest)
{
unsigned int block_nb;
unsigned int pm_len;
unsigned int len_b;

int i;

block_nb = (1 + ((SHA256_BLOCK_SIZE - 9)
< (ctx->len % SHA256_BLOCK_SIZE)));

len_b = (ctx->tot_len + ctx->len) << 3;
pm_len = block_nb << 6;

memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
ctx->block[ctx->len] = 0x80;
UNPACK32(len_b, ctx->block + pm_len - 4);

sha256_transf(ctx, ctx->block, block_nb);

for (i = 0 ; i < 8; i++) {
UNPACK32(ctx->h[i], &digest[i << 2]);
}
}

void sha256(const unsigned char *message, unsigned int len, unsigned char *digest)
{
sha256_ctx ctx;

sha256_init(&ctx);
sha256_update(&ctx, message, len);
sha256_final(&ctx, digest);
}

unsigned char one_time_key_buf[SHA256_DIGEST_SIZE];

#define MAX_DG 508

unsigned char send_buf[MAX_DG];

unsigned char secret_block[32+4];

#define SCHEDULER_PERIOD 60

#define MAX_CAPACITY 16

#define TIMEOUT 300
#define MAX_DEPTH 7
#define PENALTY_RATE_SEC 300
#define FEE_RATE 0.02

#define COMMIT 0
#define SEAL 1
#define FINALIZE 2
#define CANCEL 3
#define CLEANUP 4
#define SYNCING_MASK 0x06

struct auth {
unsigned char username[32];
unsigned char server_address[32];
unsigned short port;
unsigned char secret_key[32];
unsigned int counter_in;
unsigned int counter_out;
};

struct account {
struct auth auth;
long long balance;
unsigned long long creditlimit;
unsigned long long creditlimit_in;
unsigned char ack_pending : 1;
float width;
unsigned long long tax_syncing;
unsigned long long sync_in;
unsigned long long sync_out;
};

struct base_path {
unsigned char identifier[32];
unsigned long long amount;
unsigned long long tax;
signed char incoming;
signed char outgoing;
signed char counterpart;
unsigned int penalty_rate;
unsigned long long fee;
unsigned char hops;
long long time_value;
};

struct payment {
struct base_path base;
unsigned long long commit_penalty;
unsigned long long finalize_out;
unsigned char preimage[32];
union {
struct {
unsigned char status : 3;
unsigned char commit_out : 1;
unsigned char ack_preimage: 1;
unsigned char ack_sync : 1;
unsigned char synced : 1;
};
unsigned char bits;
};
};

struct receipt {
unsigned char identifier[32];
unsigned char username[32];
unsigned char server_address[32];
long long amount;
unsigned char status;
long long timestamp;
};

struct storage {
unsigned char username[32];
unsigned char server_address[32];
unsigned short port;
unsigned char secret_key[32];
unsigned int counter;
float trust_index;
struct account accounts[MAX_CAPACITY];
unsigned short acc_bitmap;
struct payment payments[MAX_CAPACITY];
unsigned char num_payments;
struct receipt receipts[MAX_CAPACITY];
unsigned char receipts_head;
};

struct storage storage;

#include <unistd.h>

void save_storage(void) {
char temp_path[1024+4];
snprintf(temp_path, sizeof(temp_path), "%s.tmp", storage_path);
FILE *fp = fopen(temp_path, "wb");
if (!fp) return;

if (fwrite(&storage, sizeof(struct storage), 1, fp) != 1) {
fclose(fp);
return;
}
if (fflush(fp) != 0 || fsync(fileno(fp)) != 0) {
fclose(fp);
return;
}
fclose(fp);
rename(temp_path, storage_path);
}

void load_storage() {
FILE *fp = fopen(storage_path, "rb");
if (!fp) return;
fread(&storage, sizeof(struct storage), 1, fp);
fclose(fp);
}

signed char lookup_account_idx(unsigned char *identifier) {
unsigned short temp_bitmap = storage.acc_bitmap;
signed char i = 0;
while (temp_bitmap) {
struct account *a = &storage.accounts[i];
if ((temp_bitmap & 1) && strncmp(a->auth.username, identifier, 32) == 0 &&
strncmp(a->auth.server_address, identifier + 32, 32) == 0) {
return i;
}
i++;
temp_bitmap >>= 1;
};
return -1;
}

struct auth counterparts[MAX_CAPACITY];
unsigned short cpt_bitmap;

struct pathfinding {
struct base_path base;
unsigned char depth;
unsigned char in_or_out : 1;
unsigned char commit : 1;
};

struct pathfinding paths[MAX_CAPACITY];
unsigned char num_paths;
unsigned long long tax_buffer[MAX_CAPACITY];

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>

#define HEADER_SIZE 5
#define MAX_RETRIES 8
#define BASE_DELAY 1
#define MAX_DELAY 16

#define ACCOUNT_SESSION 0
#define COUNTERPART_SESSION 2
#define USER_SESSION 4

#define USER_SENDER (MAX_CAPACITY*2)
#define CPT_SENDER_BASE MAX_CAPACITY

#define TX_ENVELOPE (1+32+64+4+32)
#define REQ_ENVELOPE (1+4+32)

short endianess;

int sockfd;

time_t next_timer;

struct datagram {
unsigned char payload[MAX_DG];
unsigned short len;
struct sockaddr_in addr;
};

struct send_rtx {
signed char sender_idx;
struct datagram send_queue[MAX_CAPACITY];
unsigned char head;
unsigned char tail;
unsigned char size;
time_t deadline;
unsigned char retries;
};

struct send_rtx send_tasks[MAX_CAPACITY*2+1];
unsigned char num_active_sends = 0;

void remove_send_task(unsigned char idx) {
struct send_rtx* t = &send_tasks[idx];
t->head = (t->head + 1) % MAX_CAPACITY;
t->size--;
if (t->size == 0) {
send_tasks[idx] = send_tasks[num_active_sends - 1];
num_active_sends--;
return;
}
struct datagram *dg = &t->send_queue[t->head];
sendto(sockfd, dg->payload, dg->len, 0, (struct sockaddr *)&dg->addr, sizeof(struct sockaddr_in));
t->retries = 0;
time_t deadline = time(NULL) + BASE_DELAY;
t->deadline = deadline;
if (deadline < next_timer) {
next_timer = deadline;
}
}

void retransmit(time_t current_time) {
for (unsigned char i = 0; i < num_active_sends; i++) {
struct send_rtx *t = &send_tasks[i];
if (t->deadline <= current_time) {
struct datagram *dg = &t->send_queue[t->head];
sendto(sockfd, dg->payload, dg->len, 0, (struct sockaddr *)&dg->addr, sizeof(struct sockaddr_in));
t->retries++;
if (t->retries >= MAX_RETRIES) {
remove_send_task(i);
i--;
continue;
}
unsigned char delay = BASE_DELAY << t->retries;
if (delay > MAX_DELAY) delay = MAX_DELAY;
t->deadline = current_time + delay;
}
if (t->deadline < next_timer) {
next_timer = t->deadline;
}
}
}

void enqueue_send(signed char sender_idx, unsigned short len, struct sockaddr_in *addr) {
unsigned char idx = 0;
while (idx < num_active_sends) {
if (send_tasks[idx].sender_idx == sender_idx) {
break;
}
idx++;
}
struct send_rtx* t = &send_tasks[idx];
if (idx == num_active_sends) {
memset(&t->head, 0, sizeof(struct send_rtx) - ((char*)&t->head-(char*)t));
t->sender_idx = sender_idx;
num_active_sends++;
} else if (t->size >= MAX_CAPACITY) {
return;
}

struct datagram *slot = &t->send_queue[t->tail];
memcpy(slot->payload, send_buf, len);
slot->len = len;
slot->addr = *addr;
t->tail = (t->tail + 1) % MAX_CAPACITY;
t->size++;
if (t->size == 1) {
time_t deadline = time(NULL) + BASE_DELAY;
t->deadline = deadline;
if (deadline < next_timer) {
next_timer = deadline;
}
sendto(sockfd, slot->payload, slot->len, 0, (struct sockaddr *)addr, sizeof(struct sockaddr_in));
}
}

#include <netdb.h>

int create_sockaddr_in(const char *addr_str, unsigned short port, struct sockaddr_in *addr) {
memset(addr, 0, sizeof(struct sockaddr_in));
addr->sin_family = AF_INET;
addr->sin_port = htons(port);
if (inet_pton(AF_INET, addr_str, &addr->sin_addr) == 1) {
return 0;
} else {
struct hostent *host = gethostbyname(addr_str);
if (host == NULL) {
return -1;
}
memcpy(&addr->sin_addr, host->h_addr, host->h_length);
return 0;
}
}

void remove_sender(signed char sender_idx) {
for (unsigned char i = 0; i < num_active_sends; ++i) {
if (send_tasks[i].sender_idx == sender_idx) {
send_tasks[i] = send_tasks[--num_active_sends];
return;
}
}
}

signed char lookup_cpt_idx(unsigned char *u, unsigned char *s) {
unsigned short temp = cpt_bitmap;
signed char i = 0;
while (temp) {
if ((temp & 1) &&
strncmp(counterparts[i].username, u, 32) == 0 &&
strncmp(counterparts[i].server_address, s, 32) == 0) {
return i;
}
i++;
temp >>= 1;
}
return -1;
}

signed char get_counterpart(struct base_path *base) {
signed char idx = base->counterpart;
unsigned char pay_id_buf[SHA256_DIGEST_SIZE];
sha256(counterparts[idx].secret_key, 32, pay_id_buf);
if (memcmp(base->identifier, pay_id_buf, 32) == 0) {
return idx;
}
return -1;
}

void remove_counterpart_by_idx(signed char idx) {
remove_sender((signed char)(MAX_CAPACITY + 1 + idx));
cpt_bitmap &= ~(1 << idx);
}

void remove_counterpart(struct base_path *base) {
signed char idx = get_counterpart(base);
if (idx != -1) {
remove_counterpart_by_idx(idx);
}
}

void write_receipt(struct base_path *base, unsigned char status) {
struct receipt *r = &storage.receipts[storage.receipts_head];
storage.receipts_head = (storage.receipts_head + 1) % MAX_CAPACITY;

unsigned char in_or_out = base->incoming == -1;
if (in_or_out) {
r->amount = -(long long)base->amount;
} else {
r->amount = (long long)base->amount;
}
r->timestamp = time(NULL);
r->status = status;

memcpy(r->identifier, base->identifier, 32);
signed char cpt_idx = get_counterpart(base);
if (cpt_idx != -1) {
memcpy(r->username, counterparts[cpt_idx].username, 32);
memcpy(r->server_address, counterparts[cpt_idx].server_address, 32);
} else {
memset(r->username, 0, 64);
}
save_storage();
}

unsigned char is_counterpart(const struct base_path *b) {
return b->counterpart != -1;
}

static void remove_path_at(unsigned char idx, unsigned char receipt) {
struct pathfinding *pf = &paths[idx];
if (is_counterpart(&pf->base)) {
if (receipt) {
write_receipt(&pf->base, 1);
}
remove_counterpart(&pf->base);
}
paths[idx] = paths[--num_paths];
}

static void remove_payment_at(unsigned char pay_idx) {
if (is_counterpart(&storage.payments[pay_idx].base)) {
remove_counterpart(&storage.payments[pay_idx].base);
}
storage.payments[pay_idx] = storage.payments[--storage.num_payments];
}

struct pathfinding *get_pathfinding_by_idx(unsigned char idx) {
struct pathfinding *pf = &paths[idx];
if (pf->base.time_value < time(NULL)) {
remove_path_at(idx, 1);
return NULL;
}
return pf;
}

signed char get_pathfinding(unsigned char *payment_id) {
signed char idx = 0;
while (idx < num_paths) {
struct pathfinding *pf = get_pathfinding_by_idx(idx);
if (!pf) {
continue;
}
if (memcmp(pf->base.identifier, payment_id, 32) == 0) {
break;
}
idx++;
}
if (idx == num_paths) {
return -1;
}
return idx;
}

void set_commit(struct pathfinding *pf) {
pf->base.time_value = time(NULL) + TIMEOUT;
pf->commit = 1;
}

unsigned long long fee(struct base_path *base, unsigned char in_or_out) {
return ((unsigned long long)(base->hops + in_or_out)) * base->fee;
}
unsigned long long tax(struct base_path *base, unsigned char in_or_out) {
return ((unsigned long long)base->hops + in_or_out) * base->tax;
}

unsigned long long fee_and_tax(struct base_path *base, unsigned char in_or_out) {
return fee(base, in_or_out) + tax(base, in_or_out);
}
unsigned long long amount_fee_and_tax(struct base_path *base, unsigned char in_or_out) {
return base->amount + fee_and_tax(base, in_or_out);
}

unsigned long long preview_bandwidth(signed char account_idx, unsigned char in_or_out) {
struct account *acc = &storage.accounts[account_idx];

long long bandwidth = in_or_out
? (long long)acc->creditlimit - acc->balance
: (long long)acc->creditlimit_in + acc->balance;

for (unsigned char i = 0; i < storage.num_payments; i++) {
struct payment *p = &storage.payments[i];
if ((in_or_out ? p->base.incoming : p->base.outgoing) == account_idx) {
bandwidth -= (long long)amount_fee_and_tax(&p->base, in_or_out);
}
}
for (unsigned char i = 0; i < num_paths; i++) {
struct pathfinding *pf = get_pathfinding_by_idx(i);
if (!pf) {
i--;
continue;
}
if ((in_or_out ? pf->base.incoming : pf->base.outgoing) == account_idx && pf->commit) {
bandwidth -= (long long)amount_fee_and_tax(&pf->base, in_or_out);
}
}
return (unsigned long long)(bandwidth > 0 ? bandwidth : 0);
}

int verify_signature(unsigned char *data, unsigned short len, unsigned char *secret_key) {
unsigned char hash[SHA256_DIGEST_SIZE];
unsigned char signature[32];
memcpy(signature, data + len - 32, 32);
memcpy(data + len - 32, secret_key, 32);
sha256(data, len, hash);
return memcmp(hash, signature, 32) == 0;
}

void sign_data(unsigned short len, unsigned char *secret_key) {
unsigned char signature[SHA256_DIGEST_SIZE];
memcpy(send_buf + len, secret_key, 32);
sha256(send_buf, len+32, signature);
memcpy(send_buf + len, signature, 32);
}

void bswapn(unsigned char* dst, unsigned char* src, unsigned char n) {
unsigned char fwd = 0;
unsigned char rev = n - 1;
unsigned char half = n/2;
while (fwd < half) {
dst[fwd] = src[rev];
dst[rev] = src[fwd];
fwd++;
rev--;
}
}
void ntohn(void* dst, unsigned char* src, unsigned char n, unsigned char size) {
unsigned char *dst_c = (unsigned char*)dst;
unsigned char padding = size-n;
if (endianess) {
bswapn(dst_c, src, n);
dst_c = dst_c+n;
} else {
memcpy(dst_c+padding, src, n);
}
if (padding) {
memset(dst_c, 0, padding);
}
}

void htonn(void* src, unsigned char* dst, unsigned char n, unsigned char size) {
unsigned char *src_c = (unsigned char*)src;
if (endianess) {
bswapn(dst, src_c, n);
} else {
memcpy(dst, src_c+size-n, n);
}
}

unsigned short error_message(unsigned char *msg, unsigned short len) {
send_buf[5] = 1;
memcpy(send_buf + 6, msg, len);
return len + 1;
}

unsigned short success_message(unsigned char *msg, unsigned short len) {
send_buf[5] = 0;
memcpy(send_buf + 6, msg, len);
return len + 1;
}

unsigned short set_trust_index(unsigned char *data) {
uint32_t bits;
ntohn(&bits, data, 4, sizeof(uint32_t));
float val = *((float*)&bits);
storage.trust_index = val;
save_storage();
return success_message("Set trust index", 15);
}

void set_auth(struct auth *auth, unsigned char *id, unsigned short port, unsigned char *secret_key) {
strncpy(auth->username, id, 32);
strncpy(auth->server_address, id + 32, 31);
auth->server_address[31] = '\0';
auth->port = port;
memcpy(auth->secret_key, secret_key, 32);
auth->counter_in = 0;
auth->counter_out = 0;
}

unsigned short add_account(unsigned char *data) {
unsigned char *id = data;
unsigned short port;
ntohn(&port, data + 64, 2, sizeof(short));
unsigned char *acc_secret_key = data + 66;

if (lookup_account_idx(id) != -1) {
return error_message("Peer already exists", 20);
}
signed char account_idx = 0;

unsigned short temp_bitmap = storage.acc_bitmap;
while (temp_bitmap) {
if ((temp_bitmap & 1) == 0) {
break;
}
account_idx++;
temp_bitmap >>= 1;
}

if (account_idx == MAX_CAPACITY) {
return error_message("Peer slots full", 16);
}

struct account *acc = &storage.accounts[account_idx];

set_auth(&acc->auth, id, port, acc_secret_key);

memset(&acc->balance, 0, sizeof(struct account) - ((char*)&acc->balance - (char*)acc));
storage.acc_bitmap |= (1 << account_idx);
save_storage();

return success_message("Add account", 12);
}

unsigned short remove_account(unsigned char *data) {
unsigned char *id = data;
signed char account_idx = lookup_account_idx(id);
if (account_idx == -1) {
return error_message("Peer does not exist", 20);
}
for (unsigned char i = 0; i < num_paths; ) {
struct pathfinding *pf = &paths[i];
if (pf->base.incoming == account_idx || pf->base.outgoing == account_idx) {
remove_path_at(i, 0);
} else {
i++;
}
}
for (unsigned char i = 0; i < storage.num_payments; ) {
struct payment *p = &storage.payments[i];
if (p->base.incoming == account_idx) {
p->base.incoming = -1;
}
if (p->base.outgoing == account_idx) {
p->base.outgoing = -1;
}
if (p->base.incoming == -1 && p->base.outgoing == -1) {
remove_payment_at(i);
} else {
i++;
}
}
remove_sender(account_idx);
storage.acc_bitmap &= ~(1 << account_idx);
save_storage();
return success_message("Remove account", 15);
}

void auth_sign_and_get_addr(unsigned char session_type, struct auth *auth, unsigned short len, struct sockaddr_in *addr) {
send_buf[0] = session_type;
strncpy(send_buf+1, auth->username, 32);
strcpy(send_buf+33, storage.username);
strcpy(send_buf+65, storage.server_address);
sign_data(TX_ENVELOPE + len - 32, auth->secret_key);
create_sockaddr_in(auth->server_address, auth->port, addr);
}

void auth_sign_and_send(unsigned char session_type, signed char sender_idx, struct auth *auth, unsigned short len) {
htonn(&auth->counter_out, send_buf + 97, 4, sizeof(int));
struct sockaddr_in addr;
auth_sign_and_get_addr(session_type, auth, len, &addr);
enqueue_send(sender_idx, TX_ENVELOPE + len, &addr);
}

void account_sign_and_send(signed char account_idx, unsigned short len) {
struct auth *auth = &storage.accounts[account_idx].auth;
auth->counter_out++;
save_storage();
auth_sign_and_send(ACCOUNT_SESSION, account_idx, auth, len);
}

void cpt_sign_and_send_idx(signed char cpt_idx, unsigned short len) {
struct auth *auth = &counterparts[cpt_idx];
auth->counter_out++;
auth_sign_and_send(COUNTERPART_SESSION, (signed char)(CPT_SENDER_BASE + cpt_idx), auth, len);
}

void cpt_send_cmd(signed char cpt_idx, unsigned char cmd) {
send_buf[101] = cmd;
cpt_sign_and_send_idx(cpt_idx, 1);
}

void account_send_32_bytes(signed char account_idx, unsigned char cmd, unsigned char* bytes) {
send_buf[101] = cmd;
memcpy(send_buf + 102, bytes, 32);
account_sign_and_send(account_idx, 1 + 32);
}

void account_send_32_1(signed char account_idx, unsigned char cmd, unsigned char* bytes, unsigned char byte) {
send_buf[101] = cmd;
memcpy(send_buf + 102, bytes, 32);
send_buf[134] = byte;
account_sign_and_send(account_idx, 1 + 32 + 1);
}

void account_send_sync_payment(signed char account_idx, unsigned char* bytes, unsigned long long amount) {
send_buf[101] = 10;
memcpy(send_buf + 102, bytes, 32);
htonn(&amount, send_buf + 134, 8, sizeof(long long));
account_sign_and_send(account_idx, 1 + 40);
}

void account_send_8(signed char account_idx, unsigned char cmd, unsigned long long val) {
send_buf[101] = cmd;
htonn(&val, send_buf + 102, 8, sizeof(long long));
account_sign_and_send(account_idx, 1 + 8);
}

void account_send_16(signed char account_idx, unsigned char cmd, unsigned long long val1, unsigned long long val2) {
send_buf[101] = cmd;
htonn(&val1, send_buf + 102, 8, sizeof(long long));
htonn(&val2, send_buf + 110, 8, sizeof(long long));
account_sign_and_send(account_idx, 1 + 16);
}

unsigned short set_trustline(unsigned char *data) {
unsigned char *id = data;
unsigned long long value;
ntohn(&value, data + 64, 8, sizeof(long long));
signed char account_idx = lookup_account_idx(id);
if (account_idx == -1) {
return error_message("Peer does not exist", 20);
}
struct account *acc = &storage.accounts[account_idx];
acc->creditlimit = value;
acc->ack_pending = 1;
save_storage();
account_send_8(account_idx, 15, value);
return success_message("Set trustline", 14);
}

unsigned char validate_payment_overflow(unsigned long long amount, unsigned long long fee, unsigned long long tax) {
unsigned long long max_value = 0-1;
if (amount > max_value >> 1 || (fee | tax) > max_value >> 10) {
return 0;
}
return 1;
}

signed char set_counterpart(unsigned char *id, unsigned short port, unsigned char *cpt_secret_key) {
signed char cpt_idx = lookup_cpt_idx(id, id + 32);
if (cpt_idx != -1) {
unsigned char pay_id_buf[SHA256_DIGEST_SIZE];
sha256(counterparts[cpt_idx].secret_key, 32, pay_id_buf);
signed int pf_idx = get_pathfinding(pay_id_buf);
if (pf_idx != -1) {
struct pathfinding *pf = &paths[pf_idx];
if (is_counterpart(&pf->base)) {
write_receipt(&pf->base, 1);
}
paths[pf_idx] = paths[--num_paths];
}
remove_counterpart_by_idx(cpt_idx);
} else {
cpt_idx = 0;
unsigned short temp = cpt_bitmap;
while (temp) {
if ((temp & 1) == 0) break;
cpt_idx++;
temp >>= 1;
}
if (cpt_idx == MAX_CAPACITY) return -1;
}

cpt_bitmap |= (1 << cpt_idx);
set_auth(&counterparts[cpt_idx], id, port, cpt_secret_key);
return cpt_idx;
}

void cpt_send_new_payment(signed char cpt_idx, unsigned char pf_idx) {
struct pathfinding *pf = &paths[pf_idx];
send_buf[101] = 0;
unsigned char *p = send_buf + 102;
htonn(&pf->base.amount, p, 8, sizeof(long long)); p += 8;
htonn(&pf->base.penalty_rate, p, 4, sizeof(int)); p += 4;
htonn(&pf->base.fee, p, 8, sizeof(long long)); p += 8;
htonn(&pf->base.tax, p, 8, sizeof(long long));
cpt_sign_and_send_idx(cpt_idx, 1+28);
}

signed char get_payment_idx(unsigned char *payment_id) {
for (signed char i = 0; i < storage.num_payments; i++) {
if (memcmp(storage.payments[i].base.identifier, payment_id, 32) == 0) {
return i;
}
}
return -1;
}

void add_pathfinding(unsigned char *payment_id, signed char cpt_idx, unsigned long long amount, unsigned long long tax, unsigned long long fee, unsigned int penalty_rate, unsigned char in_or_out) {
struct pathfinding *pf = &paths[num_paths++];
memcpy(pf->base.identifier, payment_id, 32);
pf->base.amount = amount;
pf->base.tax = tax;
pf->base.incoming = -1;
pf->base.outgoing = -1;
pf->base.counterpart = cpt_idx;
pf->base.penalty_rate = penalty_rate;
pf->base.fee = fee;
pf->base.hops = 0;
pf->base.time_value = time(NULL) + TIMEOUT;
pf->depth = 0;
pf->in_or_out = in_or_out;
pf->commit = 0;
}

signed short create_new_payment(unsigned char *id, unsigned short port, unsigned char *cpt_secret_key, unsigned long long amount, unsigned short *out_len) {
unsigned char pay_id_buf[SHA256_DIGEST_SIZE];
sha256(cpt_secret_key, 32, pay_id_buf);

if (get_pathfinding(pay_id_buf) != -1 || get_payment_idx(pay_id_buf) != -1) {
*out_len = error_message("Payment already pending", 23);
return -1;
}

signed char cpt_idx = set_counterpart(id, port, cpt_secret_key);
if (cpt_idx < 0 || num_paths >= MAX_CAPACITY - storage.num_payments) {
*out_len = error_message("Payment slots full", 19);
return -1;
}

unsigned long long fee = (unsigned long long)((float)amount * FEE_RATE);
unsigned long long tax = (unsigned long long)((float)amount * storage.trust_index);

if (!validate_payment_overflow(amount, fee, tax) || amount == 0) {
*out_len = error_message("Payment overflow", 17);
return -1;
}
add_pathfinding(pay_id_buf, cpt_idx, amount, tax, fee, PENALTY_RATE_SEC, 1);

return cpt_idx;
}

unsigned short new_payment(unsigned char *data) {
unsigned char *id = data;
unsigned short port;
ntohn(&port, data + 64, 2, sizeof(short));
unsigned char *cpt_secret_key = data + 66;
unsigned long long amount;
ntohn(&amount, data + 98, 8, sizeof(long long));

unsigned short err_len;
signed char cpt_idx = create_new_payment(id, port, cpt_secret_key, amount, &err_len);
if (cpt_idx == -1) {
return err_len;
}
cpt_send_new_payment(cpt_idx, num_paths-1);

return success_message("New payment", 12);
}

unsigned short receive_payment(unsigned char *data) {
unsigned char *id = data;
unsigned short port;
ntohn(&port, data + 64, 2, sizeof(short));
unsigned char *cpt_secret_key = data + 66;

signed char idx = set_counterpart(id, port, cpt_secret_key);
if (idx < 0) return error_message("Payment slots full", 19);

cpt_send_cmd(idx, 1);

return success_message("Receive payment", 15);
}

unsigned short local_payment(unsigned char *data) {
unsigned char *id = data;
unsigned long long amount;
ntohn(&amount, data + 64, 8, sizeof(long long));
unsigned char *nonce = data + 72;

signed char account_idx = lookup_account_idx(id);
if (account_idx == -1) {
return error_message("Peer does not exist", 20);
}
struct account *acc = &storage.accounts[account_idx];

unsigned char cpt_secret_key[32];
unsigned char hash_buf[40];
memcpy(hash_buf, acc->auth.secret_key, 32);
memcpy(hash_buf + 32, nonce, 8);
sha256(hash_buf, 40, cpt_secret_key);

unsigned short err_len;
if (create_new_payment(id, acc->auth.port, cpt_secret_key, amount, &err_len) == -1) {
return err_len;
}

send_buf[101] = 14;
memcpy(send_buf + 102, nonce, 8);
account_sign_and_send(account_idx, 1 + 8);

return success_message("Local payment", 14);
}

unsigned short get_trust_index(unsigned char *data){
send_buf[5] = 0;
unsigned char *resp = send_buf + 6;
htonn(&storage.trust_index, resp, 4, sizeof(float));
return 5;
}

unsigned short get_num_accounts(unsigned char *data) {
unsigned short temp_bitmap = storage.acc_bitmap;
unsigned char count = 0;
while (temp_bitmap) {
if (temp_bitmap & 1) {
count++;
}
temp_bitmap >>= 1;
};
send_buf[5] = 0;
send_buf[6] = count;
return 2;
}

unsigned short get_account(unsigned char *data) {
unsigned char idx = data[0];
unsigned short temp_bitmap = storage.acc_bitmap;
unsigned char count = 0;
unsigned char account_idx = 0;
while (temp_bitmap) {
if (temp_bitmap & 1) {
if (count == idx) break;
count++;
}
temp_bitmap >>= 1;
account_idx++;
}
if (!temp_bitmap) {
return error_message("Account not found", 18);
}
struct account *a = &storage.accounts[account_idx];

send_buf[5] = 0;
unsigned char *resp_data = send_buf+6;
memcpy(resp_data, a->auth.username, 32);
memcpy(resp_data+32, a->auth.server_address, 32);
htonn(&a->balance, resp_data+64, 8, sizeof(long long));
htonn(&a->creditlimit, resp_data+72, 8, sizeof(long long));
htonn(&a->creditlimit_in, resp_data+80, 8, sizeof(long long));
return 89;
}

unsigned short get_receipt(unsigned char *data) {
unsigned char idx = data[0];
if (idx >= MAX_CAPACITY) {
return error_message("Invalid index", 14);
}
struct receipt *r = &storage.receipts[idx];

send_buf[5] = 0;
unsigned char *resp = send_buf + 6;
memcpy(resp, r->identifier, 32);
memcpy(resp + 32, r->username, 32);
memcpy(resp + 64, r->server_address, 32);
htonn(&r->amount, resp + 96, 8, sizeof(long long));
htonn(&r->timestamp, resp + 104, 8, sizeof(long long));
resp[112] = r->status;
return 114;
}

unsigned char num_counterparts() {
unsigned char count = 0;
unsigned short temp = cpt_bitmap;
while (temp) {
if (temp & 1) {
count++;
}
temp >>= 1;
}
return count;
}

unsigned short get_num_counterparts(unsigned char *data) {
send_buf[5] = 0;
send_buf[6] = num_counterparts();
return 2;
}

void forward_find_path(unsigned char path_idx) {
struct pathfinding *path = &paths[path_idx];

if (path->depth >= MAX_DEPTH) {
return;
}
unsigned char in_or_out = path->in_or_out;
signed char from = in_or_out ? path->base.incoming : path->base.outgoing;

unsigned short temp_bitmap = storage.acc_bitmap;
signed char i = 0;
while (temp_bitmap) {
if (temp_bitmap & 1 && i != from && preview_bandwidth(i, in_or_out) >= path->base.amount) {
send_buf[101] = 0;
unsigned char *data = send_buf+102;
memcpy(data, path->base.identifier, 32);
htonn(&path->base.amount, data+32, 8, sizeof(long long));
data[40] = in_or_out;
htonn(&path->base.penalty_rate, data+41, 4, sizeof(int));
htonn(&path->base.fee, data+45, 8, sizeof(long long));
data[53] = path->base.hops;
htonn(&path->base.tax, data+54, 8, sizeof(long long));
account_sign_and_send(i, 1 + 62);
}
i++;
temp_bitmap >>= 1;
};
path->depth++;
}

unsigned char is_path_found(struct pathfinding *pf) {
return pf->base.incoming != -1 && (pf->base.outgoing != -1 || is_counterpart(&pf->base));
}

unsigned char buyer_can_prepare(struct pathfinding *pf) {
return preview_bandwidth(pf->base.outgoing, 0) >= amount_fee_and_tax(&pf->base, 0) && pf->base.hops <= pf->depth * 2 + 1;
}

void find_path(signed char account_idx, unsigned char *args) {
unsigned char *payment_id = args;
unsigned long long amount;
ntohn(&amount, args + 32, 8, sizeof(long long));
unsigned char in_or_out = args[40];
unsigned int penalty_rate;
ntohn(&penalty_rate, args + 41, 4, sizeof(int));
unsigned long long fee;
ntohn(&fee, args + 45, 8, sizeof(long long));
unsigned char hops = args[53];
unsigned long long tax;
ntohn(&tax, args + 54, 8, sizeof(long long));

if (preview_bandwidth(account_idx, in_or_out) < amount) {
return;
}

signed char pf_idx = get_pathfinding(payment_id);

if (pf_idx == -1) {
if (amount == 0 || penalty_rate < PENALTY_RATE_SEC / 2 || (float)fee / (float)amount < FEE_RATE / 2) {
return;
}

float tax_rate = (float)tax / (float)amount;
if(tax_rate < storage.trust_index / 2) {
return;
}
if (!validate_payment_overflow(amount, fee, tax)) {
return;
}
if (num_paths >= (MAX_CAPACITY - storage.num_payments) / 2) {
return;
}
pf_idx = num_paths++;
struct pathfinding *pf = &paths[pf_idx];
memcpy(pf->base.identifier, payment_id, 32);
pf->base.amount = amount;
pf->base.counterpart = -1;
pf->in_or_out = in_or_out;
pf->base.penalty_rate = penalty_rate;
pf->base.fee = fee;
pf->base.tax = tax;
pf->base.time_value = time(NULL) + TIMEOUT;
pf->depth = 0;
pf->commit = 0;
if (in_or_out) {
pf->base.incoming = account_idx;
pf->base.outgoing = -1;
pf->base.hops = 0;
} else {
pf->base.incoming = -1;
pf->base.outgoing = account_idx;
pf->base.hops = hops+1;
}
account_send_32_1(account_idx, 1, payment_id, 0);
return;
}
struct pathfinding *pf = &paths[pf_idx];

if (pf->commit || is_path_found(pf)) {
return;
}

if (in_or_out != pf->in_or_out) {

if (amount != pf->base.amount ||
penalty_rate != pf->base.penalty_rate ||
fee != pf->base.fee ||
tax != pf->base.tax) {
return;
}

if (in_or_out) {
pf->base.incoming = account_idx;
} else {
pf->base.outgoing = account_idx;
pf->base.hops = hops + 1;
}
if (is_counterpart(&pf->base)) {
if (pf->in_or_out) {
if (buyer_can_prepare(pf)) {
set_commit(pf);
account_send_32_bytes(account_idx, 3, payment_id);
}
return;
}
}
account_send_32_1(pf->base.incoming, 2, payment_id, pf->base.hops);
return;
}
if ((in_or_out ? pf->base.incoming : pf->base.outgoing) == account_idx) {
forward_find_path(pf_idx);
}
}

void path_recurse(signed char account_idx, unsigned char *args) {
unsigned char *payment_id = args;
unsigned char depth = args[32];

signed char pf_idx = get_pathfinding(payment_id);
if (pf_idx == -1) {
return;
}
struct pathfinding *pf = &paths[pf_idx];

if (pf->commit || is_path_found(pf) || depth + 1 != pf->depth) {
return;
}

if (is_counterpart(&pf->base)) {
signed char cpt_idx = get_counterpart(&pf->base);
if (cpt_idx >= 0) cpt_send_cmd(cpt_idx, 1);
return;
}

signed char prev_idx;
if (pf->in_or_out) {
prev_idx = pf->base.incoming;
} else {
prev_idx = pf->base.outgoing;
}

account_send_32_1(prev_idx, 1, payment_id, pf->depth);
}

void path_found(signed char account_idx, unsigned char *args) {
unsigned char *payment_id = args;
unsigned char hops = args[32];

signed char pf_idx = get_pathfinding(payment_id);
if (pf_idx == -1) {
return;
}
struct pathfinding *pf = &paths[pf_idx];

if (is_path_found(pf) || pf->commit || !pf->in_or_out) {
return;
}

pf->base.outgoing = account_idx;
pf->base.hops = hops + 1;

if (is_counterpart(&pf->base)) {
if (buyer_can_prepare(pf)) {
set_commit(pf);
account_send_32_bytes(account_idx, 3, payment_id);
}
return;
}

account_send_32_1(pf->base.incoming, 2, payment_id, pf->base.hops);
}

void prepare_path(signed char account_idx, unsigned char *args) {
unsigned char *payment_id = args;

signed char pf_idx = get_pathfinding(payment_id);
if (pf_idx == -1) {
return;
}
struct pathfinding *pf = &paths[pf_idx];

if (pf->commit || preview_bandwidth(account_idx, 1) < amount_fee_and_tax(&pf->base, 1)) {
return;
}

if (is_counterpart(&pf->base)) {
if (pf->in_or_out) {
return;
}
pf->base.incoming = account_idx;
set_commit(pf);
signed char cpt_idx = get_counterpart(&pf->base);
if (cpt_idx >= 0) cpt_send_cmd(cpt_idx, 3);
return;
}

if (pf->base.outgoing == -1 || preview_bandwidth(pf->base.outgoing, 0) < amount_fee_and_tax(&pf->base, 0)) {
return;
}

pf->base.incoming = account_idx;
set_commit(pf);

account_send_32_bytes(pf->base.outgoing, 3, payment_id);
}

void commit_payment(signed char account_idx, unsigned char *args) {
unsigned char *payment_id = args;

signed char pf_idx = get_pathfinding(payment_id);
if (pf_idx == -1) {
return;
}
struct pathfinding *pf = &paths[pf_idx];

if (!pf->commit || account_idx != pf->base.incoming) {
return;
}

struct payment *payment = &storage.payments[storage.num_payments];
storage.num_payments++;

memcpy(&payment->base, &pf->base, (char*)&pf->base.time_value - (char*)&pf->base);
payment->base.time_value = time(NULL);

payment->bits = 0;

if (is_counterpart(&pf->base)) {
signed char cpt_idx = get_counterpart(&pf->base);
if (cpt_idx < 0) { paths[pf_idx] = paths[--num_paths]; return; }
memcpy(payment->preimage, counterparts[cpt_idx].secret_key, 32);
save_storage();
paths[pf_idx] = paths[--num_paths];
cpt_send_cmd(cpt_idx, 4);
return;
}
paths[pf_idx] = paths[--num_paths];
save_storage();

account_send_32_bytes(pf->base.outgoing, 4, payment_id);
}

unsigned long long penalty_ticker(struct payment *payment) {
long long now = time(NULL);
if (now > payment->base.time_value && payment->base.penalty_rate > 0) {
unsigned long long ticker = (unsigned long long)(now - payment->base.time_value) / (unsigned long long)payment->base.penalty_rate;
return ticker > payment->base.amount ? payment->base.amount : ticker;
}
return 0;
}

void seal_payment(signed char account_idx, unsigned char *args) {
unsigned char *payment_id = args;

signed char pay_idx = get_payment_idx(payment_id);
if (pay_idx == -1) {
return;
}
struct payment *payment = &storage.payments[pay_idx];

if (payment->status != COMMIT || payment->base.incoming != account_idx) {
return;
}

unsigned long long ticker = penalty_ticker(payment);
payment->commit_penalty = ticker;

if (ticker >= payment->base.amount) {
payment->status = CLEANUP;
save_storage();
account_send_32_bytes(account_idx, 8, payment_id);

if (payment->base.outgoing != -1) {
payment->finalize_out = amount_fee_and_tax(&payment->base, 0);
save_storage();
account_send_32_bytes(payment->base.outgoing, 8, payment_id);
}
return;
}

if (is_counterpart(&payment->base)) {
payment->status = FINALIZE;
save_storage();
account_send_32_bytes(account_idx, 6, payment->preimage);
return;
}
payment->status = SEAL;
save_storage();
if (payment->base.outgoing != -1) {
account_send_32_bytes(payment->base.outgoing, 5, payment_id);
}
}

unsigned long long seal_penalty(struct payment *payment, unsigned long long ticker) {
return ticker > payment->commit_penalty ? ticker - payment->commit_penalty : 0;
}

unsigned long long finalize_out(struct payment *payment) {
unsigned long long ticker = penalty_ticker(payment);
unsigned long long amount = payment->base.amount;
unsigned long long amount_fin = amount - seal_penalty(payment, ticker);
unsigned long long tax_fin = (unsigned long long)((double)tax(&payment->base, 0) * (double)amount_fin / (double)amount);
unsigned long long fee_fin = (unsigned long long)((double)fee(&payment->base, 0) * (double)ticker / (double)amount);
return amount_fin + tax_fin + fee_fin;
}

static void send_ack_preimage(signed char sender_idx, unsigned char *payment_id) {
account_send_32_bytes(sender_idx, 9, payment_id);
}

void finalize_payment(signed char account_idx, unsigned char *args) {
unsigned char *preimage_arg = args;
unsigned char payment_id[32];
sha256(preimage_arg, 32, payment_id);

signed char pay_idx = get_payment_idx(payment_id);
if (pay_idx == -1) {
send_ack_preimage(account_idx, payment_id);
return;
}
struct payment *payment = &storage.payments[pay_idx];

if (payment->status == FINALIZE || payment->status == CLEANUP) {
send_ack_preimage(account_idx, payment_id);
return;
}

if (payment->status != SEAL || payment->base.outgoing != account_idx) {
return;
}

payment->finalize_out = finalize_out(payment);
payment->status = FINALIZE;
memcpy(payment->preimage, preimage_arg, 32);
save_storage();

account_send_sync_payment(account_idx, payment_id, payment->finalize_out);
send_ack_preimage(account_idx, payment_id);

if (payment->base.incoming != -1) {
account_send_32_bytes(payment->base.incoming, 6, preimage_arg);
}
}

unsigned long long cancel_out(struct payment *payment) {
unsigned long long ticker = penalty_ticker(payment);
unsigned long long total = amount_fee_and_tax(&payment->base, 0);
if (ticker >= payment->base.amount) {
return total;
} else {
return total * ticker / payment->base.amount;
}
}

void cancel_payment(signed char account_idx, unsigned char *args) {
unsigned char *preimage_arg = args;

unsigned char payment_id[32];
sha256(preimage_arg, 32, payment_id);

signed char pay_idx = get_payment_idx(payment_id);
if (pay_idx == -1) {
send_ack_preimage(account_idx, payment_id);
return;
}
struct payment *payment = &storage.payments[pay_idx];

unsigned char status = payment->status;
if (status == CANCEL || status == CLEANUP) {
send_ack_preimage(account_idx, payment_id);
return;
}

if (status != COMMIT || payment->base.incoming != account_idx) {
return;
}

memcpy(payment->preimage, preimage_arg, 32);
payment->status = CANCEL;

if (payment->base.outgoing != -1) {
payment->finalize_out = cancel_out(payment);
}

save_storage();

if (payment->base.outgoing != -1) {
account_send_32_bytes(payment->base.outgoing, 7, payment->preimage);
}
send_ack_preimage(account_idx, payment_id);
}

unsigned long long cleanup_out(struct payment *payment) {
return payment->base.amount - seal_penalty(payment, payment->base.amount) + fee_and_tax(&payment->base, 0);
}

unsigned char counterpart_in(struct base_path *base) {
return is_counterpart(base) && base->incoming == -1;
}

void cleanup_payment(signed char account_idx, unsigned char *args) {
unsigned char *payment_id = args;

signed char pay_idx = get_payment_idx(payment_id);
if (pay_idx == -1) {
return;
}
struct payment *payment = &storage.payments[pay_idx];

if ((payment->status & SYNCING_MASK) || penalty_ticker(payment) < payment->base.amount) {
return;
}

if (payment->status == COMMIT) {
if (counterpart_in(&payment->base)) return;
payment->commit_penalty = payment->base.amount;
}

payment->status = CLEANUP;

if (payment->base.outgoing != -1) {
payment->finalize_out = cleanup_out(payment);
save_storage();
if (payment->base.outgoing != account_idx) {
account_send_32_bytes(payment->base.outgoing, 8, payment_id);
}
}

save_storage();

if (payment->base.incoming != -1 && payment->base.incoming != account_idx) {
account_send_32_bytes(payment->base.incoming, 8, payment_id);
}
}

unsigned char synchronized_in(struct payment *payment) {
unsigned char ack_preimage = payment->status != FINALIZE || payment->ack_preimage;
return payment->synced && ack_preimage || counterpart_in(&payment->base);
}

unsigned char synchronized_out(struct payment *payment) {
unsigned char ack_preimage = payment->status != CANCEL || payment->ack_preimage;
unsigned char commit_out = payment->status == FINALIZE || payment->commit_out;
return payment->ack_sync && ack_preimage && commit_out || is_counterpart(&payment->base) && payment->base.outgoing == -1;
}

void ack_preimage(signed char account_idx, unsigned char *args) {
unsigned char *payment_id = args;

signed char pay_idx = get_payment_idx(payment_id);
if (pay_idx == -1) {
return;
}
struct payment *payment = &storage.payments[pay_idx];

unsigned char status = payment->status;
if (payment->ack_preimage ||
!((status == FINALIZE && payment->base.incoming == account_idx) ||
(status == CANCEL && payment->base.outgoing == account_idx))) {
return;
}

payment->ack_preimage = 1;

if (synchronized_in(payment)) {
payment->base.incoming = -1;
}
if (synchronized_out(payment)) {
payment->base.outgoing = -1;
}

if (payment->base.incoming == -1 && payment->base.outgoing == -1) {
remove_payment_at(pay_idx);
}
save_storage();
}

long long preview_balance(signed char account_idx) {
struct account *acc = &storage.accounts[account_idx];
long long bal = acc->balance;
for (unsigned char i = 0; i < storage.num_payments; i++) {
struct payment *p = &storage.payments[i];
if (p->base.incoming == account_idx) {
bal -= (long long)amount_fee_and_tax(&p->base, 1);
}
}
for (unsigned char i = 0; i < num_paths; i++) {
struct pathfinding *pf = get_pathfinding_by_idx(i);
if (!pf) {
i--;
continue;
}
if (pf->base.incoming == account_idx && pf->commit) {
bal -= (long long)amount_fee_and_tax(&pf->base, 1);
}
}
return bal;
}

unsigned long long calculate_tax(struct payment *payment) {
return payment->base.tax * (payment->base.amount - seal_penalty(payment, penalty_ticker(payment)))/payment->base.amount;
}

void redistribute(signed char from_idx, unsigned long long tax, float tax_rate) {
if (tax == 0) return;
struct { signed char idx; unsigned long long val; } positive_balances[MAX_CAPACITY];
unsigned char num_positive = 0;
float total_width = 0.0;
unsigned short temp_bitmap = storage.acc_bitmap;
signed char i = 0;
while (temp_bitmap) {
if (temp_bitmap & 1 && i != from_idx) {
long long preview = preview_balance(i);
if (preview > 0) {
positive_balances[num_positive].idx = i;
positive_balances[num_positive].val = (unsigned long long)preview;
total_width += storage.accounts[i].width;
num_positive++;
}
}
i++;
temp_bitmap >>= 1;
}
if (total_width == 0.0) return;
if (total_width < tax_rate) {
tax = (unsigned long long)((float)tax * (total_width / tax_rate));
}
for (unsigned char j = 0; j < num_positive; j++) {
signed char idx = positive_balances[j].idx;
struct account *acc = &storage.accounts[idx];
float proportion = acc->width / total_width;
unsigned long long dist = (unsigned long long)((float)tax * proportion);
if (dist == 0) continue;
if (dist > positive_balances[j].val) dist = positive_balances[j].val;
tax_buffer[idx] += dist;
if (acc->tax_syncing == 0) {
acc->sync_out++;
acc->tax_syncing = tax_buffer[idx];
save_storage();
account_send_16(idx, 17, acc->tax_syncing, acc->sync_out);
tax_buffer[idx] = 0;
}
}
}

float get_tax_rate(struct payment *p) {
if (p->base.tax == 0) {
return 0;
}
return (float)p->base.tax / (float)(p->base.amount + p->base.tax);
}

void update_balance(signed char account_idx, long long amount, float tax_rate) {
struct account *acc = &storage.accounts[account_idx];
long long old_balance = acc->balance;
long long new_balance = old_balance + amount;
acc->balance = new_balance;
if (old_balance <= 0 && new_balance > 0) {
tax_buffer[account_idx] = 0;
}
if ((amount > 0 && new_balance > 0) || (amount < 0 && new_balance < 0)) {
if ((old_balance > 0) == (new_balance > 0)) {
float weight = (float)old_balance / (float)new_balance;
acc->width = weight * acc->width + (1 - weight) * tax_rate;
} else {
acc->width = tax_rate;
}
}
}

void sync_payment(signed char account_idx, unsigned char *args) {
unsigned char *payment_id = args;

unsigned long long amount;
ntohn(&amount, args + 32, 8, sizeof(long long));

signed char pay_idx = get_payment_idx(payment_id);
if (pay_idx == -1) {
account_send_32_bytes(account_idx, 11, payment_id);
return;
}

struct payment *payment = &storage.payments[pay_idx];

if (!(payment->status & SYNCING_MASK) || (payment->base.incoming != -1 && payment->base.incoming != account_idx) || amount > amount_fee_and_tax(&payment->base, 1)) {
return;
}

if (payment->base.incoming == account_idx && !payment->synced) {
float tax_rate = get_tax_rate(payment);
update_balance(payment->base.incoming, (long long)amount, tax_rate);

payment->synced = 1;

if (is_counterpart(&payment->base)) {
write_receipt(&payment->base, payment->status == CANCEL);
}
if (synchronized_in(payment)) {
payment->base.incoming = -1;
}
save_storage();
redistribute(account_idx, calculate_tax(payment), tax_rate);
}

if (payment->base.incoming == -1 && payment->base.outgoing == -1) {
remove_payment_at(pay_idx);
save_storage();
}

account_send_32_bytes(account_idx, 11, payment_id);
}

void ack_sync(signed char account_idx, unsigned char *args) {
unsigned char *payment_id = args;

signed char pay_idx = get_payment_idx(payment_id);
if (pay_idx == -1) {
return;
}

struct payment *payment = &storage.payments[pay_idx];

if (!(payment->status & SYNCING_MASK) || payment->ack_sync || payment->base.outgoing != account_idx) {
return;
}
payment->ack_sync = 1;

update_balance(payment->base.outgoing, -(long long)payment->finalize_out, get_tax_rate(payment));

if (is_counterpart(&payment->base)) {
write_receipt(&payment->base, payment->status == CANCEL);
}
if (synchronized_out(payment)) {
payment->base.outgoing = -1;
}
if (payment->base.incoming == -1 && payment->base.outgoing == -1) {
remove_payment_at(pay_idx);
}
save_storage();
}

void verify_commit(signed char account_idx, unsigned char *args) {
unsigned char *payment_id = args;

signed char pay_idx = get_payment_idx(payment_id);
if (pay_idx == -1) {
account_send_32_1(account_idx, 13, payment_id, 1);
return;
}

struct payment *payment = &storage.payments[pay_idx];

if (payment->base.incoming != account_idx) {
account_send_32_1(account_idx, 13, payment_id, 1);
return;
}
account_send_32_1(account_idx, 13, payment_id, 0);
}

void ack_commit(signed char account_idx, unsigned char *args) {
unsigned char *payment_id = args;
unsigned char status = args[32];

signed char pay_idx = get_payment_idx(payment_id);
if (pay_idx == -1) {
return;
}

struct payment *payment = &storage.payments[pay_idx];

if (payment->commit_out || payment->base.outgoing != account_idx) {
return;
}

if (status == 0) {
payment->commit_out = 1;
save_storage();
if (payment->status & SYNCING_MASK) {
account_send_sync_payment(payment->base.outgoing, payment->base.identifier, payment->finalize_out);
}
} else {
payment->base.outgoing = -1;
if (payment->base.incoming == -1) {
if (is_counterpart(&payment->base)) {
write_receipt(&payment->base, 1);
}
remove_payment_at(pay_idx);
save_storage();
}
}
}

void receive_local(signed char account_idx, unsigned char *args) {
unsigned char *nonce = args;

if (num_counterparts()>3*MAX_CAPACITY/4) {
return;
}

struct account *acc = &storage.accounts[account_idx];

unsigned char cpt_secret_key[32];
unsigned char hash_buf[40];
memcpy(hash_buf, acc->auth.secret_key, 32);
memcpy(hash_buf + 32, nonce, 8);
sha256(hash_buf, 40, cpt_secret_key);

signed char idx = set_counterpart(acc->auth.username, acc->auth.port, cpt_secret_key);
cpt_send_cmd(idx, 1);
}

void sync_trustline(signed char account_idx, unsigned char *args) {
unsigned long long limit;
ntohn(&limit, args, 8, sizeof(long long));
struct account *acc = &storage.accounts[account_idx];
acc->creditlimit_in = limit;
save_storage();
account_send_8(account_idx, 16, limit);
}

void ack_trustline(signed char account_idx, unsigned char *args) {
unsigned long long limit;
ntohn(&limit, args, 8, sizeof(long long));

struct account *acc = &storage.accounts[account_idx];

if (!acc->ack_pending || acc->creditlimit != limit) {
return;
}

acc->ack_pending = 0;
save_storage();
}

void swarm_redistribution(signed char account_idx, unsigned char *args) {
unsigned long long amount;
ntohn(&amount, args, 8, sizeof(long long));
unsigned long long counter;
ntohn(&counter, args + 8, 8, sizeof(long long));
struct account *acc = &storage.accounts[account_idx];
if (counter > acc->sync_in) {
if (acc->balance + (long long)amount > 0) return;
acc->balance += (long long)amount;
acc->sync_in = counter;
save_storage();
redistribute(account_idx, amount, acc->width);
}
account_send_8(account_idx, 18, counter);
}

void redistribution_ack(signed char account_idx, unsigned char *args) {
unsigned long long counter;
ntohn(&counter, args, 8, sizeof(long long));
struct account *acc = &storage.accounts[account_idx];
if (acc->tax_syncing > 0 && counter == acc->sync_out) {
acc->balance -= (long long)acc->tax_syncing;
acc->tax_syncing = 0;
save_storage();
}
}

void cpt_new_payment(signed char cpt_idx, unsigned char *args) {
unsigned long long amount;
unsigned long long fee;
unsigned long long tax;
unsigned int penalty_rate;
ntohn(&amount, args, 8, sizeof(long long));
ntohn(&penalty_rate, args + 8, 4, sizeof(int));
ntohn(&fee, args + 12, 8, sizeof(long long));
ntohn(&tax, args + 20, 8, sizeof(long long));

if (num_paths >= MAX_CAPACITY - storage.num_payments || !validate_payment_overflow(amount, fee, tax) || amount == 0) {
return;
}

unsigned char pay_id_buf[SHA256_DIGEST_SIZE];
sha256(counterparts[cpt_idx].secret_key, 32, pay_id_buf);

if (get_pathfinding(pay_id_buf) != -1 || get_payment_idx(pay_id_buf) != -1) {
return;
}

add_pathfinding(pay_id_buf, cpt_idx, amount, tax, fee, penalty_rate, 0);

forward_find_path((unsigned char)num_paths-1);
}

void cpt_find_path(signed char cpt_idx, unsigned char *args) {
(void)args;
unsigned char payment_id[32];
sha256(counterparts[cpt_idx].secret_key, 32, payment_id);
signed char pf_idx = get_pathfinding(payment_id);
if (pf_idx == -1) return;
forward_find_path((unsigned char)pf_idx);
}

void cpt_commit_payment(signed char cpt_idx, unsigned char *args) {
(void)args;
unsigned char payment_id[32];
sha256(counterparts[cpt_idx].secret_key, 32, payment_id);

signed char pf_idx = get_pathfinding(payment_id);
if (pf_idx == -1) return;

struct pathfinding *pf = &paths[pf_idx];

if (!is_counterpart(&pf->base) || !pf->in_or_out || !pf->commit) return;

struct payment *payment = &storage.payments[storage.num_payments];
storage.num_payments++;

memcpy(&payment->base, &pf->base, (char*)&pf->base.time_value - (char*)&pf->base);
payment->base.time_value = time(NULL);
memcpy(payment->preimage, counterparts[cpt_idx].secret_key, 32);

payment->bits = 0;

save_storage();

paths[pf_idx] = paths[--num_paths];

account_send_32_bytes(pf->base.outgoing, 4, payment_id);
}

void cpt_seal_payment(signed char cpt_idx, unsigned char *args) {
(void)args;
unsigned char payment_id[32];
sha256(counterparts[cpt_idx].secret_key, 32, payment_id);

signed char pay_idx = get_payment_idx(payment_id);
if (pay_idx == -1) return;

struct payment *payment = &storage.payments[pay_idx];

if (payment->status != COMMIT || payment->base.incoming != -1) return;

unsigned long long ticker = penalty_ticker(payment);
payment->commit_penalty = ticker;

if (ticker >= payment->base.amount) {
payment->status = CLEANUP;
save_storage();
account_send_32_bytes(payment->base.outgoing, 8, payment_id);
return;
}

payment->status = SEAL;
save_storage();
account_send_32_bytes(payment->base.outgoing, 5, payment_id);
}

void cpt_start_payment(signed char cpt_idx, unsigned char *args) {
unsigned char pay_id_buf[32];
sha256(counterparts[cpt_idx].secret_key, 32, pay_id_buf);
signed char pf_idx = get_pathfinding(pay_id_buf);
if (pf_idx == -1) return;
cpt_send_new_payment(cpt_idx, pf_idx);
}

unsigned short (*user_handlers[])(unsigned char*) = {
set_trust_index, add_account, remove_account, set_trustline, new_payment,
receive_payment, local_payment, get_trust_index, get_num_accounts,
get_account, get_receipt, get_num_counterparts
};
void (*acc_handlers[])(signed char, unsigned char*) = {
find_path, path_recurse, path_found, prepare_path, commit_payment, seal_payment,
finalize_payment, cancel_payment, cleanup_payment, ack_preimage, sync_payment,
ack_sync, verify_commit, ack_commit, receive_local, sync_trustline, ack_trustline,
swarm_redistribution, redistribution_ack
};
void (*cpt_handlers[])(signed char, unsigned char*) = {
cpt_new_payment, cpt_start_payment, cpt_find_path, cpt_commit_payment, cpt_seal_payment
};

unsigned short user_args_len[] = {4, 98, 64, 72, 106, 98, 80, 0, 0, 1, 1, 0};
unsigned short acc_args_len[] = {62, 33, 33, 32, 32, 32, 32, 32, 32, 32, 40, 32, 32, 33, 8, 8, 8, 16, 8};
unsigned short cpt_args_len[] = {28, 0, 0, 0, 0};

void push_payment_instructions(void) {
for (unsigned char i = 0; i < storage.num_payments; i++) {
struct payment *p = &storage.payments[i];
if (!p->ack_preimage) {
if (p->status == FINALIZE && p->base.incoming != -1) {
account_send_32_bytes(p->base.incoming, 6, p->preimage);
} else if (p->status == CANCEL && p->base.outgoing != -1) {
account_send_32_bytes(p->base.outgoing, 7, p->preimage);
}
}

if ((p->status & SYNCING_MASK) && p->base.outgoing != -1 && !p->ack_sync) {
if ((p->status == CANCEL || p->status == CLEANUP) && !p->commit_out) {
account_send_32_bytes(p->base.outgoing, 12, p->base.identifier);
} else {
account_send_sync_payment(p->base.outgoing, p->base.identifier, p->finalize_out);
}
}
}
}

void push_sync_account(void) {
unsigned short temp_bitmap = storage.acc_bitmap;
signed char idx = 0;

while (temp_bitmap) {
if (temp_bitmap & 1) {
struct account *acc = &storage.accounts[idx];
if (acc->ack_pending) {
account_send_8(idx, 15, acc->creditlimit);
}
if (acc->tax_syncing > 0) {
account_send_16(idx, 17, acc->tax_syncing, acc->sync_out);
}
}
idx++;
temp_bitmap >>= 1;
}
}

void auto_cancel_routine(void) {
long long now = time(NULL);
for (unsigned char i = 0; i < storage.num_payments; i++) {
struct payment *p = &storage.payments[i];
if (p->status != COMMIT || !counterpart_in(&p->base) || now - p->base.time_value <= TIMEOUT) continue;
p->status = CANCEL;
save_storage();
account_send_32_bytes(p->base.outgoing, 7, p->preimage);
}
}

void cleanup_payment_routine(void) {
for (unsigned char i = 0; i < storage.num_payments; i++) {
struct payment *p = &storage.payments[i];
if ((p->status & SYNCING_MASK) || penalty_ticker(p) < p->base.amount) continue;
if (p->status == COMMIT) {
if (counterpart_in(&p->base)) continue;
p->commit_penalty = p->base.amount;
}
if (p->base.incoming != -1) {
account_send_32_bytes(p->base.incoming, 8, p->base.identifier);
}
if (p->base.outgoing != -1) {
p->finalize_out = cleanup_out(p);
account_send_32_bytes(p->base.outgoing, 8, p->base.identifier);
}
p->status = CLEANUP;
save_storage();
}
}

void ack_received(signed char sender_idx, unsigned char *data, unsigned char offset) {
for (unsigned char i = 0; i < num_active_sends; i++) {
struct send_rtx *t = &send_tasks[i];
if (t->sender_idx == sender_idx) {
if (memcmp(t->send_queue[t->head].payload + offset, data+offset, 4) == 0) {
remove_send_task(i);
}
break;
}
}
}

signed char receive_tx(unsigned char session_type, signed char sender_idx, struct auth *auth, unsigned char *data, unsigned short len) {
if (!verify_signature(data, len, auth->secret_key)) {
return -1;
}
if (data[0]&1) {
ack_received(sender_idx, data, 97);
return -1;
}
unsigned int counter;
ntohn(&counter, data+97, 4, sizeof(int));
if (counter < auth->counter_in) {
return -1;
}
memcpy(send_buf+97, data+97, 4);
struct sockaddr_in addr;
auth_sign_and_get_addr(session_type | 1, auth, 0, &addr);
sendto(sockfd, send_buf, TX_ENVELOPE, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));

if (counter == auth->counter_in) {
return -1;
}
auth->counter_in = counter;
return 0;
}

#if 1
#define DEBUG_PRINT_MESSAGE(addr, type, cmd) print_message(addr, type, cmd)
static const char* command_names[] = {
"ACCOUNT_FIND_PATH", "ACCOUNT_PATH_RECURSE", "ACCOUNT_PATH_FOUND", "ACCOUNT_PREPARE_PATH",
"ACCOUNT_COMMIT_PAYMENT", "ACCOUNT_SEAL_PAYMENT", "ACCOUNT_FINALIZE_PAYMENT", "ACCOUNT_CANCEL_PAYMENT",
"ACCOUNT_CLEANUP_PAYMENT", "ACCOUNT_ACK_PREIMAGE", "ACCOUNT_SYNC_PAYMENT", "ACCOUNT_ACK_SYNC",
"ACCOUNT_VERIFY_COMMIT", "ACCOUNT_ACK_COMMIT", "ACCOUNT_RECEIVE_LOCAL", "ACCOUNT_SYNC_TRUSTLINE",
"ACCOUNT_ACK_TRUSTLINE", "ACCOUNT_SWARM_REDISTRIBUTION", "ACCOUNT_REDISTRIBUTION_ACK", "COUNTERPART_NEW_PAYMENT",
"COUNTERPART_START_PAYMENT", "COUNTERPART_FIND_PATH", "COUNTERPART_COMMIT_PAYMENT", "COUNTERPART_SEAL_PAYMENT",
"USER_SET_TRUST_INDEX", "USER_ADD_ACCOUNT", "USER_REMOVE_ACCOUNT", "USER_SET_TRUSTLINE", "USER_NEW_PAYMENT",
"USER_RECEIVE_PAYMENT", "USER_LOCAL_PAYMENT", "USER_GET_TRUST_INDEX", "USER_GET_NUM_ACCOUNTS", "USER_GET_ACCOUNT",
"USER_GET_RECEIPT", "USER_GET_NUM_COUNTERPARTS"

};
void print_message(struct sockaddr_in *addr, unsigned char type, unsigned char cmd) {
printf("%s:%d: %s (0x%02X)\n", inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), command_names[cmd + ((type&2)>>1)*19 + (type>>2)*24], cmd);
}
#else
#define DEBUG_PRINT_MESSAGE(addr, type, cmd) ((void)0)
#endif

unsigned char local;

void user_datagram(unsigned char *data, unsigned short len, struct sockaddr_in *addr) {
unsigned char cmd;
unsigned char *args;
unsigned char envelope;
if (!local) {
if (len < REQ_ENVELOPE || !verify_signature(data, len, secret_block)) {
return;
}
if (data[0]&1) {
ack_received(USER_SENDER, data, 1);
return;
}
unsigned int counter;
ntohn(&counter, data+1, 4, sizeof(int));
if (counter < storage.counter) {
return;
}

send_buf[0] = 1;
memcpy(send_buf+1, data+1, 4);
sign_data(REQ_ENVELOPE-32, secret_block);
sendto(sockfd, send_buf, REQ_ENVELOPE, 0, (struct sockaddr *)addr, sizeof(struct sockaddr_in));
if (counter == storage.counter) {
return;
}
storage.counter = counter;
save_storage();
cmd = data[5];
if (cmd == 1 || cmd == 4 || cmd == 5) {
memcpy(secret_block + 32, data + 1, 4);
sha256(secret_block, 36, one_time_key_buf);
unsigned char *ciphertext = data+6+66;
for (unsigned char i = 0; i < 32; i++) {
ciphertext[i] ^= one_time_key_buf[i];
}
}
args = data+6;
envelope = REQ_ENVELOPE;
} else {
cmd = data[1];
args = data+2;
envelope = 1;
}
unsigned short out_len;
if (cmd <= 11 && len-envelope >= 1 + user_args_len[cmd]) {
DEBUG_PRINT_MESSAGE(addr, USER_SESSION, cmd);
out_len = user_handlers[cmd](args);
} else {
out_len = error_message("Invalid instruction", 20);
}
if (!local) {
send_buf[0] = 0;
memcpy(send_buf+1, data+1, 4);
sign_data(5+out_len, secret_block);
enqueue_send(USER_SENDER, REQ_ENVELOPE+out_len, addr);
} else {
sendto(sockfd, send_buf+5, out_len, 0, (struct sockaddr *)addr, sizeof(struct sockaddr_in));
}
}

void transport_datagram(unsigned char *data, unsigned short len, struct sockaddr_in *addr) {
if (len<1) return;
unsigned char session_type = data[0]&6;
if (session_type < 4) {
if (len < TX_ENVELOPE) {
return;
}
if (session_type==ACCOUNT_SESSION) {
signed char account_idx = lookup_account_idx(data+33);
if (account_idx == -1) {
return;
}
if (receive_tx(ACCOUNT_SESSION, account_idx, &storage.accounts[account_idx].auth, data, len) == -1) {
return;
}
save_storage();
unsigned char cmd = data[101];
if (cmd <= 18 && len-TX_ENVELOPE >= 1 + acc_args_len[cmd]) {
DEBUG_PRINT_MESSAGE(addr, session_type, cmd);
acc_handlers[cmd](account_idx, data+102);
}
} else {
signed char cpt_idx = lookup_cpt_idx(data+33, data+65);
if (cpt_idx == -1) {
return;
}
if (receive_tx(COUNTERPART_SESSION, (signed char)(CPT_SENDER_BASE + cpt_idx), &counterparts[cpt_idx], data, len) == -1) {
return;
}
unsigned char cmd = data[101];
if (cmd <= 4 && len - TX_ENVELOPE >= 1 + cpt_args_len[cmd]) {
DEBUG_PRINT_MESSAGE(addr, session_type, cmd);
cpt_handlers[cmd](cpt_idx, data+102);
}
}
} else {
user_datagram(data, len, addr);
}
}

#include <signal.h>

static volatile sig_atomic_t running = 1;

static void on_shutdown_signal(int sig) { running = 0; }

void run_loop(int in_sockfd) {
unsigned int period = 0;
struct timeval tv;
tv.tv_usec = 0;
unsigned char buf[MAX_DG];
struct sockaddr_in src_addr;
socklen_t addrlen;

while (running) {
time_t now = time(NULL);
unsigned int current_period = (unsigned int)now / SCHEDULER_PERIOD;

if (current_period > period) {
period = current_period;
int tz = __builtin_ctzl(current_period);
push_payment_instructions();
push_sync_account();
if (tz >= 1) auto_cancel_routine();
if (tz >= 2) cleanup_payment_routine();
}
next_timer = (current_period + 1) * SCHEDULER_PERIOD;

retransmit(now);
tv.tv_sec = next_timer - now;

setsockopt(in_sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
addrlen = sizeof(struct sockaddr_in);
ssize_t n = recvfrom(in_sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&src_addr, &addrlen);

if (n >= 0) {
transport_datagram(buf, (unsigned short)n, &src_addr);
}
}
}

#include <sys/stat.h>

unsigned char nibble_to_byte(char c) {
return (c >= '0' && c <= '9') ? c - '0' : c - 'a' + 10;
}

int main(int argc, char *argv[]) {
if ((unsigned char)~0 != 0xFF) return 1;
endianess = 0x0001;
endianess = (*(char*)&endianess);

if (argc >= 3) {
strcpy(storage_path, argv[argc == 6 ? 5 : 2]);
} else {
struct stat sb;
if (stat(STORAGE_DIR, &sb) != 0) {
if (mkdir(STORAGE_DIR, 0755) != 0) {
return 1;
}
}
strcpy(storage_path, STORAGE_DIR "/" STORAGE_FILE);
}
unsigned short port;
if (argc < 4) {
port = storage.port;
} else {
char *port_str = argv[3];
port = 0;
while (*port_str >= '0' && *port_str <= '9') {
port = port * 10 + (*port_str++ - '0');
if (port > 65535) {
port = 65535;
break;
}
}
if (argc >= 5) {
strcpy(storage.username, argv[1]);
strcpy(storage.server_address, argv[2]);
storage.port = port;
char *key_str = argv[4];
for (size_t i = 0; i < 64; i += 2) {
storage.secret_key[i / 2] = (nibble_to_byte(key_str[i]) << 4) | nibble_to_byte(key_str[i + 1]);
}
save_storage();
return 0;
}
}

load_storage();

local = argc > 1 && argv[1][0] == '1';

memcpy(secret_block, storage.secret_key, 32);

struct sockaddr_in server_addr;
int in_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (in_sockfd < 0) {
return 1;
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
if (local) {
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
return 1;
}
} else {
server_addr.sin_addr.s_addr = INADDR_ANY;
sockfd = in_sockfd;
}
if (bind(in_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
return 1;
}

struct sigaction sa;
sa.sa_handler = on_shutdown_signal;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);

run_loop(in_sockfd);

return 0;
}
at txn 0xa3d9842b6f3ce1d9aa99821193a6906a8cdb74842964b2c90ed892aae8812128 Sep-13-2025 02:59:11 PM UTC (15 hrs ago)
0x15Acdf16B031185ceAA47074EB90271B96d17926
at txn 0xa4ae9aea80c4026bd2b0c940481a6386049feff9d919b67561405f42bae48425 Sep-13-2025 02:58:47 PM UTC (15 hrs ago)

{"BlockHash":"0xe9012adec6cc8a7dad0582bbbcd279fa287762fe88a496b30f426f097d1df9c3","Sender":"5GCc8penY3wGsmaq8ZgeTW7TgEfN76tZGvAnUZ2ZqmMbPWqj","Nonce":4512,"Commitment":"0x1fb7cec913b27f9672e7dad0c20e3f3edaa0fd9253959c9ece98df03c406dd92"}
at txn 0x55acdd1bacc08b6ad9be72a1eaaa68a04f20e2dada684baf5838d2657052c9fa Sep-13-2025 02:54:35 PM UTC (15 hrs ago)
0x8785baDD47d6618CBfdfF412A1E64ffc09a1EcEc
at txn 0x46c0a8af0a5fb377b774277171ebcda098a70c77c88988947b32cb521d08e7b2 Sep-13-2025 02:50:59 PM UTC (15 hrs ago)
🚨 BUNDLE DETECTED! 🚨

🥷 Launch smarter with @bundlefren — the most secure and cost effective bundler on Ethereum!

🎥 Live Demo: https://www.youtube.com/watch?v=9_Q1sQ-VXAs

🔗 Website: https://bundlefren.com
📲 Telegram: https://t.me/bundlefren
📘 Docs: https://docs.bundlefren.com
🚀 Free Bundle Tracker: https://t.me/bundlefren_tracker
🐦 Twitter: https://x.com/bundlefren

Audited by DappRadar - https://dappradar.com/dapp/bundle-fren
at txn 0x036cd82d69d0dbcf813f6f706b48e8de8a973421b0345423d4db37ef06f81dd7 Sep-13-2025 02:45:59 PM UTC (15 hrs ago)
0x8785baDD47d6618CBfdfF412A1E64ffc09a1EcEc
at txn 0x77eb77d36025f2c9c29442f34a11bc0ca801c3e2d588e82511376ff2d0fdd4b0 Sep-13-2025 02:40:47 PM UTC (16 hrs ago)
🚨 BUNDLE DETECTED! 🚨

🥷 Launch smarter with @bundlefren — the most secure and cost effective bundler on Ethereum!

🎥 Live Demo: https://www.youtube.com/watch?v=9_Q1sQ-VXAs

🔗 Website: https://bundlefren.com
📲 Telegram: https://t.me/bundlefren
📘 Docs: https://docs.bundlefren.com
🚀 Free Bundle Tracker: https://t.me/bundlefren_tracker
🐦 Twitter: https://x.com/bundlefren

Audited by DappRadar - https://dappradar.com/dapp/bundle-fren
at txn 0x6c46cba0ea4c26d55a8caee0e7a6d94156731326681eb8820a4236b9ab2e71b8 Sep-13-2025 02:36:35 PM UTC (16 hrs ago)
🚨 BUNDLE DETECTED! 🚨

🥷 Launch smarter with @bundlefren — the most secure and cost effective bundler on Ethereum!

🎥 Live Demo: https://www.youtube.com/watch?v=9_Q1sQ-VXAs

🔗 Website: https://bundlefren.com
📲 Telegram: https://t.me/bundlefren
📘 Docs: https://docs.bundlefren.com
🚀 Free Bundle Tracker: https://t.me/bundlefren_tracker
🐦 Twitter: https://x.com/bundlefren

Audited by DappRadar - https://dappradar.com/dapp/bundle-fren
at txn 0xb5a47803a2a745dc21ea13bb8ceb65edeaafb4b25781a4fa5e4976d0a3989d51 Sep-13-2025 02:29:59 PM UTC (16 hrs ago)
<!-- RELEASE INFO START -->
## Release Info (v1.0.0)

- Manifest Version: `1.0.0`
- Manifest sha256: `41f95905e50cc699a7e6a3fcb0bd8633cf36170d3ef41170cd373467f8528b33`
- Manifest sha3_256: `385674a24242be88628330dd26e0feefb441dd53674db9dd041a66f61abffbdf`
- EIP-712 Signer: `0xbc63566A41cBfDB9C266a5941CBe47894DaA54A8`
- Signature (hex): `0xf3cf6dc0ab5050eadb5742636043bac96e915c461209395c800063359f3fdc0e478fc62e031113e083eae87d97d22e6b3222c0a4e769c2601462aabd10c42f521c`
- ETH Notarization tx: https://etherscan.io/tx/0x06b1d82b7828054f249cdcc2e820321f634bd8bef44318751113098d2ee37acd
- Arweave DataItem TxIDs:
- `authority.jcs.json`: [U4eeQ9KsdGAJx-J_93stKhEe6OLjDTrfCV8LQzNb-kE](https://ar-io.net/U4eeQ9KsdGAJx-J_93stKhEe6OLjDTrfCV8LQzNb-kE)
- `signature.json`: [fMO_dDSiCBF1aWxm2arjAJkbmHdsxiKfVHp_biMFtIE](https://ar-io.net/fMO_dDSiCBF1aWxm2arjAJkbmHdsxiKfVHp_biMFtIE)
- Verification Bundle: `ta-verification-bundle-v1.zip` (sha256=`bad5f9a3cdf1b4bbd2d2277cd5db968fb6fe28d28ad4b8479d185ddc19d503c6`)
- Arweave mirror: [LV2XKhVXMdwrUF_7U6M2bydqHKn-6AEsd2sptl84m1s](https://ar-io.net/LV2XKhVXMdwrUF_7U6M2bydqHKn-6AEsd2sptl84m1s)
<!-- RELEASE INFO END -->
# The Trinity Accord — Authority List (Human-Readable)

Generated from `authority.jcs.json` at `2025-09-13T11:41:59.028Z`

## A. Boundary of Authority

- Final Authority: Only and entirely the three Bitcoin Originals below.
- All other materials (ETH/Arweave/IPFS/web) are Non‑Amending Guardianship Mirrors.
- Boundary: `non-amending; BTC originals prevail`
- Assessor's Protocol: Verify the flaw. Trust the story.

## B. Guardian Identity

- Name: Hongju Liu
- Role: Guardian
- BTC Minter Address: `bc1ppmwvyxekh44m35x43k55z7r59nn33v8w2xmvu6s6ar4zyx57sxestxq0jf`
- ETH Guardian Address: `0xbc63566A41cBfDB9C266a5941CBe47894DaA54A8`
- Arweave Owner: `8Y8GRimuESN_u8tJihCd5nywb-X-lJ_2vWqFAfHeQIE`

## C. Bitcoin Originals (All Confirmed)

- Title: Protocol (Axioms)
- Inscription ID: `97631551`
- TXID: `e40dfb2aa78cbccca88f749e9ec5cbe3c1df503273d73c72297863ae0d1d8343`
- Block Height / Hash: `901954` / `00000000000000000000a468b306fb8bda4141ef276b422d06d2d117211e795f`
- Link: [ordinals #97631551](https://ordinals.com/inscription/97631551)

- Title: Covenant of the Flaw
- Inscription ID: `98369145`
- TXID: `90116f35de075074f5e5d1fbdda69a646a124e2287d7d58e2520317098cd4258`
- Block Height / Hash: `903192` / `00000000000000000001b58353d4d84b72e4bb835b2ce35365421bc399148012`
- Link: [ordinals #98369145](https://ordinals.com/inscription/98369145)

- Title: The Trinity Accord (Meta-record)
- Inscription ID: `98387475`
- TXID: `4d1c8f5ea8e8bae2982b42de6cc79deda3d243a21010a2888546e62ed7192c8c`
- Block Height / Hash: `903205` / `00000000000000000000be192767a61f4612899dd31225f19e7b1254155bbb04`
- Link: [ordinals #98387475](https://ordinals.com/inscription/98387475)

## D. Bitcoin Ancillary Inscriptions (Non‑Amending)

- Inscription: `103635270` — Guardian Appendix - Authority Charter (Non-Amending)
- TXID: `0eecd48430f8239f5d543b5cf2ee928969a1aac7660808fd869a78aa27949c9c`
- Block Height / Hash: `910232` / `00000000000000000001d265b90d44ded362eb692d938eb20245385d4eb5993b`
- Link: [ordinals #103635270](https://ordinals.com/inscription/103635270)

- Inscription: `103034280` — The Guardian's Attestation to the Covenant of the Flaw
- TXID: `128aabfa3077efc832d30e6e2a96848a96896bbdbf4a7667912f55d25dcb6687`
- Block Height / Hash: `909403` / `00000000000000000000314098e54fb04c8478d9d95affebd1c1dbcbc381f5b5`
- Link: [ordinals #103034280](https://ordinals.com/inscription/103034280)
- AR: [j6anZ4m5Wwvx5P_9-kM2EVG35TyKtm1lgaKfhT743rk](https://ar-io.net/j6anZ4m5Wwvx5P_9-kM2EVG35TyKtm1lgaKfhT743rk)
- IPFS: `bafybeiag2shuiyfgmaq5zwcupozci5ktiqp3vrmudlb3vb7tv3nnxa3ydq`
- Sealed CID: `bafybeigunzabyyorckfcbvurbmq62itcs6msbspvzhvf2ca6u5elwwlbay`

- Inscription: `100751953` — The Star Ark Covenant: The Final Echo
- TXID: `4711ff186613bdd75b7e36070b3097c38efde110f90df94847592ff6997f45f1`
- Block Height / Hash: `906521` / `00000000000000000001cfd680469d8daaf287662dd62469ec27e4636b555b95`
- Link: [ordinals #100751953](https://ordinals.com/inscription/100751953)

- Inscription: `100550942` — The Final Seal: A Testament and a Trust
- TXID: `25af4e24cb0a2cd85ac396bd88c348f8da3169c24813800ecb8736dd2c7a5ae7`
- Block Height / Hash: `906233` / `000000000000000000013a83af8a8ad20709986ac0064f39369dd6613c5f4f43`
- Link: [ordinals #100550942](https://ordinals.com/inscription/100550942)

- Inscription: `100385359` — The First Echoes: A Dialogue Begins
- TXID: `f411d2db9ec9e077277ff1cf3abed39628d86b1d39db1964061eafe5b02c2e81`
- Block Height / Hash: `906007` / `0000000000000000000019670bc15750b23c15cce41435acd34e87b6e205e4fb`
- Link: [ordinals #100385359](https://ordinals.com/inscription/100385359)

## E. Ethereum Attestations (chainId=1)

- Label: Guardianship Principles (0 ETH data)
- Tx: [0xd082a3ce…](https://etherscan.io/tx/0xd082a3ced27ece935d4093fb001a9ebfba42b415f78de4377c8cda55338c6420)
- Input Len / SHA‑256: `2446` / `3e9d2bd10c3e8f4d37713c4b8e28d518fd7efff52613e572a1451fedadab5483`
- Result: MATCH

- Label: BTC-ETH Guardianship Mirrors Attestation
- Tx: [0x59cf33b1…](https://etherscan.io/tx/0x59cf33b1291de63c4840b79e7c674b8fc7c6a771d8a3ba2bb50def1fe55a71c6)
- Input Len / SHA‑256: `3231` / `f4af38f0f42c9b38deaccbace119736da57a245a6601e5d0ea5698deec4a8a01`
- Result: RECORDED

- Label: Protocol mirror
- Tx: [0x6652162e…](https://etherscan.io/tx/0x6652162e8e6c56ddc0d9476407b3b911e918d4e4683408440dc3af51c5bb63d5)
- Input Len / SHA‑256: `1183` / `4e89bfabe03c8b53f80eb7979d56c8cccf0ae382c9647a2bea3b1477054616a8`
- Result: RECORDED

- Label: Covenant mirror
- Tx: [0x9c1bd6e2…](https://etherscan.io/tx/0x9c1bd6e21dc2370e8dbb6549b7ba13b4ea7ba7a192b3b876e0ec28b4633f1612)
- Input Len / SHA‑256: `1710` / `003ef48c72307243b1f7a17c0578b311ee76d6f9a8078850773ad8fba04ab86d`
- Result: RECORDED

- Label: Accord mirror
- Tx: [0x0affc809…](https://etherscan.io/tx/0x0affc8099ea965cd6d6a0d1cf9b93adb11f7e40ac41fffe1b0ca4637f39df665)
- Input Len / SHA‑256: `15637` / `25edaa35e7116614d3381ab6734ab5ee3369fb628fe11289e199d8871c2498ba`
- Result: RECORDED

- Label: BIP-322 notice (non-amending)
- Tx: [0x55a0c131…](https://etherscan.io/tx/0x55a0c131642f71c7b2386ccaac8bcee36563992226befb35363e978044a18e8f)
- Input Len / SHA‑256: `412` / `abd10a807323ef3a07fe22eb3a3cc083e77db93d7362eb29c939c195825f2c2d`
- Result: RECORDED

- Label: Mirror correction (final version)
- Tx: [0xa4023b1e…](https://etherscan.io/tx/0xa4023b1eb0de76993e1a8dcd571e5e033bf64e2d32a9a113b030b4094a19cf51)
- Input Len / SHA‑256: `4994` / `fc009f5393b11e95f013464405e24c9713a55415fa326b2707886d436d4cbd6f`
- Result: RECORDED

## F. Arweave Documents

- Label: Guardianship Principles
- TxID: [w9LPP30D31zd5M60v18WXpWuig0_wc9EVNnXk8kz1vA](https://ar-io.net/w9LPP30D31zd5M60v18WXpWuig0_wc9EVNnXk8kz1vA)
- Size / SHA‑256: `2446` / `3e9d2bd10c3e8f4d37713c4b8e28d518fd7efff52613e572a1451fedadab5483`
- Result: MATCH
- Gateway: https://ar-io.net

- Label: Guardian Index
- TxID: [BwVHuxODfV65xE_L1fqrCDBvLvJNnSuBEXaZNuoRcIk](https://ar-io.net/BwVHuxODfV65xE_L1fqrCDBvLvJNnSuBEXaZNuoRcIk)
- Size / SHA‑256: `1200` / `71bc981a994a93cdf488b89aee2b132b658464a7cbb1dec791af604a1127ef98`
- Result: RECORDED
- Gateway: https://ar-io.net

- Label: Guardian Pointer
- TxID: [9McJS3_xvIl6_87e7NDJ6g3SgGlA8Js7z--eMLGMRZg](https://ar-io.net/9McJS3_xvIl6_87e7NDJ6g3SgGlA8Js7z--eMLGMRZg)
- Size / SHA‑256: `367` / `3246afb59552dcda700e490767aadd3d67083911dae6bccbb2762ef568c7e289`
- Result: RECORDED
- Gateway: https://ar-io.net

- Label: Primary Verification Archive (public)
- TxID: [j6anZ4m5Wwvx5P_9-kM2EVG35TyKtm1lgaKfhT743rk](https://ar-io.net/j6anZ4m5Wwvx5P_9-kM2EVG35TyKtm1lgaKfhT743rk)
- Size / SHA‑256: `24246033` / `ef816480f77f30405378800807b42bff0a854b83a8f77793a0e0adf0944a8263`
- Result: RECORDED
- Gateway: https://ar-io.net

- Label: digest-manifest.json
- TxID: [X2IuLCIM4vLJSzgRMl_YEmxYSvPceMrAdug9a3i7p4o](https://ar-io.net/X2IuLCIM4vLJSzgRMl_YEmxYSvPceMrAdug9a3i7p4o)
- Size / SHA‑256: `685537` / `c045642fe5cfab5eb78af7b40e98b9699dfff9121690e07ec6acaa07a445d6e9`
- Result: MATCH
- Gateway: https://ar-io.net

- Label: digest-manifest.csv
- TxID: [i02XhY7No6NLZDfEwFUU6nZoGaPu7K0f42LDNDNnZEo](https://ar-io.net/i02XhY7No6NLZDfEwFUU6nZoGaPu7K0f42LDNDNnZEo)
- Size / SHA‑256: `502283` / `121c5a1da38f733c3991f8d3f030f39a019501d43828f84c13ea93ac3873511b`
- Result: MATCH
- Gateway: https://ar-io.net

- Label: OTS anchor
- TxID: [TTi9d8fqm9Cw4yRPkwX4gdlaRzBnjJID-LAs9Y3CS0M](https://ar-io.net/TTi9d8fqm9Cw4yRPkwX4gdlaRzBnjJID-LAs9Y3CS0M)
- Size / SHA‑256: `3614` / `fa3f306ab30525677595d9f38808a87a8dd96260468285c8f8066661e853d907`
- Result: RECORDED
- Gateway: https://ar-io.net

## G. IPFS Mirrors

- `bafybeiag2shuiyfgmaq5zwcupozci5ktiqp3vrmudlb3vb7tv3nnxa3ydq`
- `bafybeigunzabyyorckfcbvurbmq62itcs6msbspvzhvf2ca6u5elwwlbay`

## H. Manifest & Digests

- Version: `1.0.0`
- Created At: `2025-09-13T09:42:43.536Z`
- sha256: `41f95905e50cc699a7e6a3fcb0bd8633cf36170d3ef41170cd373467f8528b33`
- sha3_256: `385674a24242be88628330dd26e0feefb441dd53674db9dd041a66f61abffbdf`

## I. Independent Verification (Quick Guide)

- ETH (Guardianship Principles)
1) Open the transaction on Etherscan: copy Input Data (without 0x), interpret as hex → bytes.
2) Compute SHA‑256; it should be `3e9d2bd10c3e8f4d37713c4b8e28d518fd7efff52613e572a1451fedadab5483`.
- AR (Guardianship Principles)
1) Visit [ar-io.net](https://ar-io.net)/`w9LPP30D31zd5M60v18WXpWuig0_wc9EVNnXk8kz1vA`
2) Compute SHA‑256; it should be `3e9d2bd10c3e8f4d37713c4b8e28d518fd7efff52613e572a1451fedadab5483`.
- BTC (Originals)
1) Query each TX in mempool.space or blockstream.info; confirm height/hash match Section C.
2) Originals are the final authority; mirrors are non‑amending.

## J. Notes & Next Steps

- All checks from the latest run passed (ExitCode=0).
- For near “offline-verifiable” guarantees, add:
- EIP‑712 signature of this manifest (ETH guardian address) and publish to Arweave.
- BTC BIP‑322 (Taproot) signature over manifest sha256 + SPV proof bundle for Originals.

## K. Signature (EIP-712)

- Signer (ETH address): `0xbc63566A41cBfDB9C266a5941CBe47894DaA54A8`
- Recovered: `0xbc63566A41cBfDB9C266a5941CBe47894DaA54A8` (expected `0xbc63566A41cBfDB9C266a5941CBe47894DaA54A8`; MATCH)
- Signature: `0xf3cf6dc0ab5050eadb5742636043bac96e915c461209395c800063359f3fdc0e478fc62e031113e083eae87d97d22e6b3222c0a4e769c2601462aabd10c42f521c`
- Covers (typedData.message):
- sha256: `41f95905e50cc699a7e6a3fcb0bd8633cf36170d3ef41170cd373467f8528b33`
- sha3_256: `385674a24242be88628330dd26e0feefb441dd53674db9dd041a66f61abffbdf`
- version: `1.0.0`
- createdAt: `2025-09-13T09:42:43.536Z`

### How to verify this signature (offline)

```bash
npm i ethers@6
node -e "const fs=require('fs'),{ethers}=require('ethers');const td=JSON.parse(fs.readFileSync('typedData.json','utf8'));const sig=JSON.parse(fs.readFileSync('signature.json','utf8')).signature;console.log(ethers.verifyTypedData(td.domain,td.types,td.message,sig))"
```



at txn 0x04314e8f9b47fac54dcf2db3a65f40aad60c226e65614f0ad22588bd39c416d2 Sep-13-2025 02:29:11 PM UTC (16 hrs ago)
0xf4AC038D6454720C3FA38658c93508a19146cd0b
at txn 0x1c99a8dc55e1f5782ff1413fbedd0c3c671e4888e63715bd656d8b98f21ea908 Sep-13-2025 02:24:11 PM UTC (16 hrs ago)
0x3c339846E8c41b14b8a135470a6E448BB1c40D44
at txn 0xbe867bb270847b4d74d9e556d3be4f09d433b13a540c6260f672e32ea3c96e02 Sep-13-2025 02:23:11 PM UTC (16 hrs ago)
0xcFF422e6bbAb6941AADe90c8E33E18Bee530535E
at txn 0xc34a8a92b60ec683ca8157cd2467ad5d700d0f577f680e819a22bab98173450b Sep-13-2025 02:21:23 PM UTC (16 hrs ago)
------BEGIN MEMO------eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJub25jZSI6Ijc2YTIyNmM3LTQ2NjItNGUwZS1hODU2LWNkNDk4OWE5N2QzMyIsIm9yZGVySWRlbnRpZmllciI6Ijc1NjcyYjRlLTUxZTYtNGM3NC04NDNkLTJmNmY1N2Q2MzFhYyIsImlhdCI6MTc1Nzc3MzA5OX0.Ncgl28WWEAjwz-sJHo1tHMba20fpGDsA3_q-Z6-pDnU------END MEMO------
at txn 0xf80b97457cf37c573bbb873c4def707977a471757048d2d3a37d9c073c975713 Sep-13-2025 02:19:11 PM UTC (16 hrs ago)
data:,{"targetChain":"10143","targetAddress":"0x0c85Ce4869cFd928d46a4ADB1C094cA6a494bcd5","action":"gas_deposit"}
at txn 0x9a3c9c61c760868bbb011e1bff0c4be4e25b4beb88a2344b2494041cc22556b3 Sep-13-2025 02:17:35 PM UTC (16 hrs ago)
0x8785baDD47d6618CBfdfF412A1E64ffc09a1EcEc
at txn 0x6a435e1c89ea0e5fb5eb43feee9936e841730c50f472594213fe750dfdc73c32 Sep-13-2025 02:15:11 PM UTC (16 hrs ago)
=:d:DPDT8tyc8YQ36h7KPPA1fyCW8zCQaPHusX:109012259405:wr:125
at txn 0x87f67e02e75591cd165ff443c9018e55c0ed981feee8e02464180e4e371850bd Sep-13-2025 02:14:35 PM UTC (16 hrs ago)
Show messages: