-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexample_contract.c
More file actions
119 lines (102 loc) · 3.89 KB
/
example_contract.c
File metadata and controls
119 lines (102 loc) · 3.89 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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "hotpocket_contract.h"
// gcc echo_contract.c -o echo_contract
void store_timestamp(const uint64_t timestamp);
void process_user_message(const struct hp_user *user, const void *buf, const uint32_t len);
int main(int argc, char **argv)
{
// Initialize the HotPocket contract context for this execution.
if (hp_init_contract() == -1)
return 1;
const struct hp_contract_context *ctx = hp_get_context();
// We store the execution timestamp as an example state file change.
if (!ctx->readonly)
store_timestamp(ctx->timestamp);
// Read and process all user inputs from the mmap.
const void *input_mmap = hp_init_user_input_mmap();
// Iterate through all users.
for (size_t u = 0; u < ctx->users.count; u++)
{
const struct hp_user *user = &ctx->users.list[u];
// Iterate through all inputs from this user.
for (size_t i = 0; i < user->inputs.count; i++)
{
const struct hp_user_input input = user->inputs.list[i];
// Instead of mmap, we can also read the inputs from 'ctx->users.in_fd' using file I/O.
// However, using mmap is recommended because user inputs already reside in memory.
const uint8_t *buf = (uint8_t *)input_mmap + input.offset;
process_user_message(user, buf, input.size);
}
}
// NPL message send example:
// hp_write_npl_msg("Hello!", 6);
// NPL message receive example:
// // Allocate buffers for received message.
// char sender[HP_KEY_SIZE];
// char *msg = malloc(HP_NPL_MSG_MAX_SIZE);
// // Wait for 200ms for incoming message. We will receive our own message as well if we are part of unl.
// const int len = hp_read_npl_msg(msg, sender, 200);
// if (len > 0)
// printf("Received %.*s from %.*s", len, msg, HP_KEY_SIZE, sender);
// free(msg);
// Peers update example:
// const char *add_peers[2] = {"localhost:4444", "localhost:3333"};
// hp_update_peers(add_peers, 2, NULL, 0);
// Config update example:
// struct hp_config *config = hp_get_config();
// hp_set_config_string(&config->version, "2.0", 4);
// config->round_limits.user_input_bytes = 1024;
// struct hp_public_key new_unl[2] = {{"ed726f9f536904b125bdca10bbdd1e66591b274799b92ac8bcfc75bf45d7da4c0f"},
// {"ed3e63992d62804ea0c182e5b22fe43c4b652fbbf068ec7520f3020f4c3771416a"}};
// hp_set_config_unl(config, new_unl, 2);
// hp_update_config(config);
// hp_free_config(config);
hp_deinit_user_input_mmap();
hp_deinit_contract();
return 0;
}
void store_timestamp(const uint64_t timestamp)
{
int fd = open("exects.txt", O_RDWR | O_CREAT | O_APPEND, 0644);
if (fd > 0)
{
char tsbuf[20];
memset(tsbuf, 0, 20);
sprintf(tsbuf, "%lu\n", timestamp);
struct iovec vec[2] = {{(void *)"ts:", 3}, {(void *)tsbuf, strlen(tsbuf)}};
writev(fd, vec, 2);
close(fd);
}
}
void process_user_message(const struct hp_user *user, const void *buf, const uint32_t len)
{
if (strncmp((const char *)buf, "ts", 2) == 0)
{
int fd = open("exects.txt", O_RDONLY);
if (fd > 0)
{
struct stat st;
if (fstat(fd, &st) != -1)
{
char tsbuf[st.st_size];
if (read(fd, tsbuf, st.st_size) > 0)
{
for (int i = 0; i < st.st_size; i++)
{
if (tsbuf[i] == '\n' || tsbuf[i] == 0)
tsbuf[i] = ' ';
}
hp_write_user_msg(user, tsbuf, st.st_size - 1);
}
}
close(fd);
}
}
else
{
struct iovec vec[2] = {{(void *)"Echoing: ", 9}, {(void *)buf, len}};
hp_writev_user_msg(user, vec, 2);
}
}